/* =============================================================================
   contact.css — the Contact page.

   Written to sit beside css/about.css rather than beside itself. It borrows
   that page's whole vocabulary so the two read as one site:

     - the same measure and gutter (1180px / clamp(20px, 5vw, 64px)),
     - the same easing, cubic-bezier(.22, 1, .36, 1),
     - the same reveal pair: .ct-rise for a block, .ct-stagger for its children,
       both switched by an `in` class an IntersectionObserver adds,
     - the same kicker (mono, .18em, with a 22px rule before it) and the same
       display heading with a gradient-clipped <em> / <b>,
     - the same scroll spine down the left edge,
     - and the same semantic for line work: SOLID means chosen and measured,
       DASHED means idle or guessed.

   The page's own idea is the routing diagram. Picking a subject in the form
   draws the line the message will actually travel and lights the inbox at the
   end of it, so "it goes to the right place" is shown rather than asserted. It
   is driven by the same radios the form submits, so it cannot disagree with
   what is sent.

   Theme: light is the :root default, dark is opt-in, every surface is
   token-derived. Only --ct-* names are declared, so tests/theme-lint.mjs sees
   no second source of truth for a colour.
   ========================================================================== */

.contact-page {
  /* about.css's reading measure. Kept as the reference the wide one is judged
     against; no container is set to it any more. */
  --ct-wrap: 1180px;
  /* The wide measure, borrowed from about.css's --ab-wide / .ab-wrap--wide.
     Only the two-column desk uses it: that row carries a diagram and a form
     side by side and wants the room, while the single-column acts below stay
     at the reading measure where a longer line would hurt. */
  --ct-wide: 1400px;
  --ct-gut: clamp(20px, 5vw, 64px);

  /* Bands are a change of SURFACE, not of theme: --bg-2 is light in light mode
     and deepens in dark, so a band is never a dark slab in a light page. */
  --ct-band-bg: var(--bg-2);

  --ct-tint: color-mix(in srgb, var(--brand) 9%, transparent);
  --ct-tint-2: color-mix(in srgb, var(--brand) 16%, transparent);
  --ct-ring: color-mix(in srgb, var(--purple) 20%, transparent);
  --ct-wash: color-mix(in srgb, var(--brand) 12%, transparent);

  /* meaning, borrowed from about.css */
  --ct-idle: var(--muted);
  --ct-live: var(--green);

  /* --purple is tuned for the dark surfaces it was drawn for; on a light card
     it lands near 4:1, under the 4.5:1 body text needs. Light pulls it toward
     --text, dark takes the bright variant. */
  --ct-link: color-mix(in srgb, var(--purple) 74%, var(--text));

  --ct-ease: cubic-bezier(.22, 1, .36, 1);

  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
[data-theme="dark"] .contact-page {
  --ct-link: var(--purple-bright);
  --ct-wash: color-mix(in srgb, var(--brand) 20%, transparent);
}
.contact-page *,
.contact-page *::before,
.contact-page *::after { box-sizing: border-box; }

/* Every section uses the wide measure now, not just the desk. Blocks that need
   a shorter line still carry their own max-width (the lede at 60ch, the FAQ at
   the component width), so widening the container gives the grids room without
   stretching a line of prose past its measure. */
.ct-wrap { max-width: var(--ct-wide); margin: 0 auto; padding: 0 var(--ct-gut); }

/* ---- reveal, the about.css pair ------------------------------------------ */
.ct-rise { opacity: 0; transform: translateY(22px); transition: opacity .8s var(--ct-ease), transform .8s var(--ct-ease); }
.ct-rise.in { opacity: 1; transform: none; }
.ct-stagger > * { opacity: 0; transform: translateY(18px); transition: opacity .7s var(--ct-ease), transform .7s var(--ct-ease); }
.ct-stagger.in > * { opacity: 1; transform: none; }
.ct-stagger.in > *:nth-child(2) { transition-delay: .09s; }
.ct-stagger.in > *:nth-child(3) { transition-delay: .18s; }
.ct-stagger.in > *:nth-child(4) { transition-delay: .27s; }
.ct-stagger.in > *:nth-child(5) { transition-delay: .36s; }
.ct-stagger.in > *:nth-child(6) { transition-delay: .45s; }
.ct-stagger.in > *:nth-child(7) { transition-delay: .54s; }
.ct-stagger.in > *:nth-child(8) { transition-delay: .63s; }

/* ---- the scroll spine ---------------------------------------------------- */
.ct-spine {
  position: fixed;
  top: 0; left: 0;
  width: 2px; height: 100vh;
  background: var(--hairline);
  z-index: 4;
  pointer-events: none;
}
.ct-spine i {
  display: block;
  width: 100%;
  height: 0;
  background: var(--gradient);
}

/* ---- type, the about.css scale ------------------------------------------- */
.ct-kicker {
  display: inline-flex; align-items: center; gap: 9px;
  font: 700 10.5px/1 var(--font-mono); letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}
.ct-kicker::before { content: ""; width: 22px; height: 1px; background: currentColor; opacity: .55; }

.ct-h {
  font-family: var(--font-heading);
  font-weight: 800; letter-spacing: -0.035em; line-height: 1.02;
  font-size: clamp(32px, 5.4vw, 58px);
  color: var(--text); margin: 18px 0 0; text-wrap: balance;
}
.ct-h-2 { font-size: clamp(28px, 4.2vw, 46px); }
.ct-h em {
  font-family: 'Fraunces', Georgia, serif; font-style: italic; font-weight: 400;
  letter-spacing: -0.02em;
  background: var(--gradient); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.ct-h b {
  font-weight: 800;
  background: var(--gradient); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.ct-lede {
  font-size: clamp(15.5px, 1.5vw, 17.5px); line-height: 1.68;
  color: var(--text-3); max-width: 60ch; margin: 16px 0 0; text-wrap: pretty;
}

/* ---- ACT 1 — the desk ---------------------------------------------------- */
.ct-stage { position: relative; padding: clamp(52px, 7vw, 96px) 0 clamp(56px, 8vw, 104px); isolation: isolate; overflow: hidden; }
.ct-wash {
  position: absolute; z-index: -1;
  top: -180px; right: -10%;
  width: min(900px, 90%); height: 780px;
  background: radial-gradient(ellipse 55% 50% at 60% 40%, var(--ct-wash), transparent 70%);
  pointer-events: none;
}

.ct-two {
  display: grid;
  /* The form is the taller, denser column, so it takes the wider track. */
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr);
  gap: clamp(32px, 4.5vw, 68px);
  align-items: start;
}
.ct-left { min-width: 0; }
/* Sticks while the page scrolls, so the routing diagram stays beside the
   chooser that drives it instead of scrolling away from it. */
.ct-right { min-width: 0; position: sticky; top: 92px; }

/* ---- the routing diagram ------------------------------------------------- */
.ct-route {
  position: relative;
  margin: 34px 0 0;
  padding: 18px 18px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--shadow-sm);
}
.ct-route-cap { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 6px; }
.ct-route-lab { font: 700 10px/1 var(--font-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.ct-route-live { display: inline-flex; align-items: center; gap: 7px; font: 600 10px/1 var(--font-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--text-3); }
.ct-route-live i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ct-live); box-shadow: 0 0 9px var(--ct-live);
  animation: ct-pulse 2s ease-in-out infinite;
}
@keyframes ct-pulse { 50% { opacity: .35; } }

.ct-route-svg { display: block; width: 100%; height: auto; overflow: visible; }

/* Idle wires are dashed and grey. The chosen one goes solid and brand, and
   draws itself in rather than snapping on. */
.ct-wire {
  fill: none;
  stroke: var(--ct-idle);
  stroke-width: 1.5;
  stroke-dasharray: 4 5;
  opacity: .45;
  transition: opacity .3s var(--ct-ease), stroke .3s var(--ct-ease), stroke-width .3s var(--ct-ease), stroke-dasharray .3s var(--ct-ease);
}
/* The chosen wire goes solid; the rest stay dashed. That IS the animation —
   a stroke-dashoffset draw was tried and removed, because non-scaling-stroke
   renders the dash pattern in SCREEN pixels while the path length is in viewBox
   units, so no dasharray value can equal the path at every width. pathLength
   normalises that, but it normalises the idle 4/5 dashes too and turns them
   solid. A colour and weight change is honest, robust at any size, and still
   reads as the route lighting up. */
.ct-wire.is-on {
  stroke: var(--purple);
  stroke-width: 2.4;
  stroke-dasharray: none;
  opacity: 1;
}


/* The labels are real DOM beside the drawing, not <text> inside it, so the
   i18n runtime translates them and a screen reader gets them in reading order.
   Alignment is STRUCTURAL: the key column is five equal rows and the inbox
   column two, so their centres land at 10/30/50/70/90% and 25/75% of the
   height. The SVG stretches to the same box with preserveAspectRatio="none"
   and its paths start and end at exactly those percentages, so the wires meet
   the labels at any width without a single magic pixel. non-scaling-stroke
   keeps the line weight even though the box is being stretched. */
.ct-route-grid {
  display: grid;
  grid-template-columns: auto minmax(60px, 1fr) auto;
  align-items: stretch;
  gap: 10px;
  /* min-height, not height: five label rows set the real height, and a fixed
     one clipped the fifth. The SVG stretches to whatever the labels need, which
     is what keeps the wires meeting them. */
  min-height: 188px;
}
.ct-route-keys, .ct-route-boxes { list-style: none; margin: 0; padding: 0; display: grid; }
.ct-route-keys { grid-template-rows: repeat(5, 1fr); }
.ct-route-boxes { grid-template-rows: repeat(2, 1fr); text-align: right; }
.ct-route-key,
.ct-route-box {
  font: 500 10.5px/1.2 var(--font-mono);
  letter-spacing: .02em;
  color: var(--muted);
  display: flex; align-items: center; gap: 7px;
  transition: color .3s var(--ct-ease);
  white-space: nowrap;
}
.ct-route-box { justify-content: flex-end; }
/* The node dots live on the labels rather than in the stretched SVG, where a
   circle would render as an ellipse. */
.ct-route-key::after,
.ct-route-box::before {
  content: ""; flex: 0 0 auto;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--panel);
  box-shadow: inset 0 0 0 1.5px var(--ct-idle);
  transition: box-shadow .3s var(--ct-ease), background .3s var(--ct-ease);
}
.ct-route-key.is-on { color: var(--text); font-weight: 700; }
.ct-route-box.is-on { color: var(--text); font-weight: 700; }
.ct-route-key.is-on::after { background: var(--purple); box-shadow: inset 0 0 0 1.5px var(--purple); }
.ct-route-box.is-on::before { background: var(--magenta); box-shadow: inset 0 0 0 1.5px var(--magenta); }

.ct-route-svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* ---- contact rows -------------------------------------------------------- */
.ct-meta { margin: 30px 0 0; display: grid; }
.ct-meta-row {
  display: grid; grid-template-columns: 78px minmax(0, 1fr);
  gap: 16px; align-items: baseline;
  padding: 12px 0; border-top: 1px solid var(--hairline);
}
.ct-meta-row:last-child { border-bottom: 1px solid var(--hairline); }
.ct-meta-l { margin: 0; font: 700 10px/1.4 var(--font-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.ct-meta-v { margin: 0; font-size: 14.5px; font-weight: 500; color: var(--text-2); word-break: break-word; }
.ct-meta-v a { color: var(--text-2); text-decoration: none; border-bottom: 1px solid var(--border-strong); transition: color .16s var(--ct-ease), border-color .16s var(--ct-ease); }
.ct-meta-v a:hover { color: var(--ct-link); border-bottom-color: var(--ct-link); }
.ct-meta-v a:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }
.ct-fineprint { margin: 16px 0 0; font-size: 12.5px; line-height: 1.65; color: var(--muted); max-width: 52ch; }

/* ---- the form card ------------------------------------------------------- */
.ct-card {
  position: relative;
  padding: clamp(22px, 2.6vw, 34px);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  background: var(--card);
  /* Two stops: a tight contact shadow that seats the edge and a wide soft one
     that lifts the card. One alone reads either flat or floaty. */
  box-shadow: var(--shadow-sm), var(--shadow-lg);
}
.ct-card::before {
  content: "";
  position: absolute; top: -1px; left: 26px; right: 26px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--purple), var(--magenta), transparent);
  opacity: .85;
}

.ct-form { margin: 0; }
.ct-fs { border: 0; padding: 0; margin: 0 0 16px; min-width: 0; }
.ct-legend {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.ct-label {
  display: block;
  font: 700 10px/1 var(--font-mono); letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 9px;
}
.ct-topics { display: flex; flex-wrap: wrap; gap: 8px; }
.ct-topic { display: block; }
/* The radio keeps its keyboard behaviour and stays in the accessibility tree;
   the pill is only its face. */
.ct-topic input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }
.ct-topic-face {
  display: inline-flex; align-items: center;
  padding: 9px 15px; border-radius: var(--radius-pill);
  border: 1px solid var(--border); background: var(--bg);
  font-size: 13.5px; font-weight: 500; color: var(--text-3);
  cursor: pointer; white-space: nowrap;
  transition: background .16s var(--ct-ease), border-color .16s var(--ct-ease), color .16s var(--ct-ease);
}
.ct-topic:hover .ct-topic-face { border-color: var(--border-strong); color: var(--text); }
.ct-topic input:checked + .ct-topic-face {
  background: var(--ct-tint-2); border-color: var(--purple); color: var(--text); font-weight: 600;
}
/* Focus belongs on the face: the input is invisible, so without this a keyboard
   user arrowing through the group has no idea where they are. */
.ct-topic input:focus-visible + .ct-topic-face { outline: 2px solid var(--purple); outline-offset: 2px; }

/* All five notes ship in the markup and are toggled by class, so the extractor
   sees every one and none is built by JS. */
.ct-note { margin: 0 0 24px; padding-left: 13px; border-left: 2px solid var(--ct-tint-2); }
.ct-note-line { display: none; margin: 0; font-size: 13px; line-height: 1.55; color: var(--muted); }
.ct-note-line.is-on { display: block; }

.ct-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.ct-field { display: block; margin-bottom: 16px; }
.ct-input {
  display: block; width: 100%;
  /* 16px, not smaller: below 16px iOS Safari zooms on focus and never zooms
     back out. */
  font-size: 16px; font-family: inherit; line-height: 1.5;
  color: var(--text);
  /* Recessed against the card, which makes the card read as a surface the
     fields are cut into rather than a box they sit on. */
  background: var(--bg);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 13px 15px;
  transition: border-color .15s var(--ct-ease), box-shadow .15s var(--ct-ease), background .15s var(--ct-ease);
}
.ct-input::placeholder { color: var(--muted); }
.ct-input:hover { border-color: var(--purple); }
.ct-input:focus { outline: none; border-color: var(--purple); background: var(--card); box-shadow: 0 0 0 4px var(--ct-ring); }
.ct-textarea { resize: vertical; min-height: 132px; }
/* Only after a submit attempt, so a field is never red before it is answered. */
.ct-form.is-checked .ct-input:invalid { border-color: var(--red); }

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

.ct-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; margin-top: 6px;
  padding: 17px 30px; border-radius: var(--radius-pill);
  border: 1px solid transparent;
  /* --purple/--magenta, NOT var(--gradient). They look identical in dark, but
     --gradient is built from --brand-2, declared once in :root and never
     re-declared per theme. --magenta IS per-theme and its light value is
     darker: white on --brand-2 measures 3.89:1 and fails AA, on --magenta
     4.67:1 and passes. index.html:748 uses these two directly for the same
     reason, so this matches the homepage rather than forking it. */
  background: linear-gradient(135deg, var(--purple), var(--magenta));
  color: var(--on-brand);
  font-family: inherit;
  /* 19px/700 is also large text by WCAG's definition, so the gradient's darker
     end has margin rather than sitting on the line. */
  font-size: 19px; font-weight: 700;
  cursor: pointer;
  
  transition: transform .2s ease, box-shadow .2s var(--ct-ease);
}
.ct-btn:hover { transform: translateY(-2px);  }
.ct-btn:active { transform: translateY(0); }
.ct-btn:focus-visible { outline: 2px solid var(--purple); outline-offset: 3px; }
.ct-btn[disabled] { opacity: .6; pointer-events: none; }
.ct-arrow { width: 18px; height: 18px; flex: 0 0 auto; }

.ct-status { margin: 16px 0 0; font-size: 14px; line-height: 1.55; color: var(--text-3); }
.ct-status:empty { margin: 0; }
.ct-status.is-ok { color: var(--green); font-weight: 600; }
.ct-status.is-bad { color: var(--red); font-weight: 600; }
.ct-fine { margin: 14px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--muted); }
.ct-inline-link { color: var(--ct-link); text-decoration: underline; text-underline-offset: 2px; transition: color .15s var(--ct-ease); }
.ct-inline-link:hover { color: var(--magenta); }
.ct-inline-link:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

/* ---- the acts below ------------------------------------------------------ */
.ct-act { padding: clamp(56px, 7vw, 96px) 0; position: relative; }
.ct-band { background: var(--ct-band-bg); border-block: 1px solid var(--hairline); }

/* ---- the six things ------------------------------------------------------ */
/* Numerals are CSS counters, so twelve digits never enter the DOM for the i18n
   extractor to translate. */
.ct-steps {
  counter-reset: ctstep; list-style: none; margin: 42px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 30px 34px;
}
.ct-step { position: relative; padding-top: 34px; }
.ct-step::before {
  counter-increment: ctstep; content: counter(ctstep, decimal-leading-zero);
  position: absolute; top: 0; left: 0;
  font: 700 11px/1 var(--font-mono); letter-spacing: .18em; color: var(--ct-link);
}
.ct-step::after { content: ""; position: absolute; top: 22px; left: 0; width: 26px; height: 1px; background: var(--border-strong); }
.ct-step-t { font-family: var(--font-heading); font-size: 17px; font-weight: 800; letter-spacing: -.02em; line-height: 1.3; color: var(--text); margin: 0 0 6px; }
.ct-step-p { font-size: 14.5px; line-height: 1.6; color: var(--text-3); margin: 0; }

/* ---- response windows ---------------------------------------------------- */
.ct-times { margin: 42px 0 0; display: grid; }
.ct-time {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px 32px; align-items: center;
  padding: 20px 0; border-top: 1px solid var(--hairline);
}
.ct-time:last-child { border-bottom: 1px solid var(--hairline); }
.ct-time-k { margin: 0; font-size: 15.5px; font-weight: 600; color: var(--text); }
.ct-time-v { margin: 0; display: flex; align-items: baseline; gap: 10px; justify-content: flex-end; }
.ct-num {
  font-family: var(--font-heading); font-weight: 800; letter-spacing: -.03em;
  font-size: clamp(26px, 3vw, 38px); line-height: 1;
  background: var(--gradient); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.ct-time-u { font: 500 12px/1.4 var(--font-mono); letter-spacing: .04em; color: var(--muted); text-align: right; }
/* The open-ended row must not look like a number that failed to load. */
.ct-time-none { font: 700 12px/1.4 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ct-idle); }

/* ---- self-serve ---------------------------------------------------------- */
.ct-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin: 42px 0 0; }
.ct-link-card {
  display: flex; flex-direction: column; gap: 7px;
  padding: 24px; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--card); text-decoration: none;
  transition: border-color .16s var(--ct-ease), transform .2s ease;
}
.ct-link-card:hover { border-color: var(--purple); transform: translateY(-2px); }
.ct-link-card:focus-visible { outline: 2px solid var(--purple); outline-offset: 3px; }
.ct-link-t { font-family: var(--font-heading); font-size: 18px; font-weight: 800; letter-spacing: -.02em; color: var(--text); }
.ct-link-p { font-size: 14.5px; line-height: 1.55; color: var(--text-3); flex: 1; }
.ct-link-go { font: 700 10.5px/1 var(--font-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ct-link); margin-top: 4px; }

/* ---- responsive ---------------------------------------------------------- */
/* The two columns hold to 1080px. Below that the form is too narrow for two
   fields on a row and the diagram too narrow to read, so they stack with the
   text first and the form directly under it. */
@media (max-width: 1080px) {
  .ct-two { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .ct-right { position: static; }
  .ct-card { max-width: 640px; }
  .ct-route { max-width: 560px; }
  .ct-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 28px; }
}
@media (max-width: 860px) {
  .ct-links { grid-template-columns: minmax(0, 1fr); }
  .ct-spine { display: none; }
}
@media (max-width: 620px) {
  .ct-steps { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .ct-row { grid-template-columns: minmax(0, 1fr); gap: 0; }
  /* Right-aligned values opposite a wrapping label read as two unrelated
     columns on a narrow screen. */
  .ct-time { grid-template-columns: minmax(0, 1fr); gap: 6px; padding: 16px 0; }
  .ct-time-v { justify-content: flex-start; }
  .ct-time-u { text-align: left; }
  .ct-meta-row { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  /* Inline links are only as tall as their text; padding them out gives a
     usable touch target without changing how they read. */
  .ct-meta-v a, .ct-inline-link { display: inline-block; padding: 4px 0; }
}

/* The diagram's labels are positioned against a fixed viewBox, so below this
   width they shrink rather than collide. */
@media (max-width: 420px) {
  .ct-route { padding: 14px; }
  .ct-route-key, .ct-route-box { font-size: 9px; }
  .ct-route-keys { left: 14px; }
  .ct-route-boxes { right: 14px; }
}

/* ---- reduced motion ------------------------------------------------------ */
/* The JS returns before adding a reveal class, so this is the belt-and-braces
   pass for anything class-driven. Content is never hidden, only stilled. */
@media (prefers-reduced-motion: reduce) {
  .ct-rise, .ct-stagger > * { opacity: 1 !important; transform: none !important; transition: none !important; }
  .ct-route-live i { animation: none; }
  .ct-btn, .ct-input, .ct-topic-face, .ct-link-card { transition: none; }
  .ct-btn:hover, .ct-link-card:hover { transform: none; }
}

/* ---- FAQ placement ------------------------------------------------------- */
/* The .mvte component centres itself (margin-inline:auto in
   css/tool-explainer.css) and that is left in place, so the cards sit centred
   in the section exactly as they do on the free-tools pages. No override here
   on purpose: the earlier left-aligned variant was removed rather than kept
   alongside, so there is only one rule deciding this.
   The heading above stays left-aligned in about.css style. */
