/* roommate-compatibility-test.html — the public, indexable landing page for
   compatibility groups. Built on css/index.css tokens (both themes) and the
   avatar / ring pieces in css/match-group.css. Everything below the hero
   arrives on scroll and drifts at depth — see "Scroll choreography" — but
   only once js/ct-parallax.js has put `ct-motion` on <html>. Without that
   class, which is to say with JS off or motion turned down, every word on
   this page is still painted on the first frame. */

/* ── Type scale ───────────────────────────────────────────────────────────
   The page used to run almost everything between .88rem and 1.05rem, which
   is why it read as one undifferentiated block: a card's heading was barely
   larger than its own body text, so nothing announced itself and the eye had
   no way in. Five steps, each separated by size AND weight AND colour, so
   the hierarchy survives at any width:

     display  h1          clamp(2.3 → 3.4rem)   800   --text
     title    h2          clamp(1.9 → 2.55rem)  800   --text
     heading  h3, summary 1.125rem              700   --text
     body     p, li       .9375rem              400   --text-2
     micro    kickers     .72rem                800   accent, tracked

   Ratios are ~1.2 between adjacent steps, which is enough to read as
   deliberate without the jumps looking like different pages. Tracking goes
   negative as size goes up (Manrope opens up badly at display sizes) and
   back to zero for body. Measure is capped in `ch` so it follows the font
   rather than the viewport. ---------------------------------------------- */
.ct-main {
  --ct-h3: 1.125rem;
  --ct-body: .9375rem;
  --ct-lh-body: 1.7;
}
.ct-main p { text-wrap: pretty; }          /* no one-word last lines */
.ct-main h1, .ct-main h2, .ct-main h3 { text-wrap: balance; }

.ct-skip { position: absolute; left: 12px; top: -60px; z-index: 2000; padding: .6rem 1rem; border-radius: 10px;
  background: var(--text); color: var(--bg); font-weight: 700; font-size: .9rem; }
.ct-skip:focus { top: 12px; }
.ct-main { overflow-x: hidden; overflow-x: clip; }
.ct-main:focus { outline: none; }
.ct-main a:not(.btn):focus-visible, .ct-faq summary:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; border-radius: 6px; }
.ct-main p a:not(.btn), .ct-note a, .ct-uses a { color: var(--mg-accent-text); font-weight: 600;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* ── Hero ─────────────────────────────────────────────────────────────────
   The hero is the one animated part of the page, and the animation is kept
   strictly off the reading path: nothing in .ct-hero-copy starts hidden, so
   the h1 (the LCP element) paints immediately and the rest of the copy is
   there on first frame with or without CSS animation, JS or motion.
   Everything that moves is decoration — the aurora, the orbit scene, the
   card's lit border, the gauge filling — plus two text effects (the headline
   sheen and the underline draw) that only ever add ink, never remove it.
   The whole lot is silenced under prefers-reduced-motion at the end of
   this file. -------------------------------------------------------------- */

/* Registered so the conic gauge and the lit border can be animated at all;
   unregistered custom properties are not interpolable. Both fall back to a
   finished-looking static value where @property is unsupported. */
@property --p   { syntax: '<number>'; inherits: false; initial-value: 88; }
@property --ang { syntax: '<angle>';  inherits: false; initial-value: 0deg; }

.ct-hero { position: relative; padding: clamp(6.5rem, 12vw, 8.5rem) 0 clamp(3rem, 6vw, 4.5rem); }
.ct-hero-grid { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
  align-items: center; gap: clamp(2rem, 5vw, 4rem); }

/* Ambient light behind the whole hero. */
.ct-aurora { position: absolute; inset: -10% -6% 0; pointer-events: none; overflow: hidden; contain: strict; }
.ct-blob { position: absolute; border-radius: 50%; filter: blur(90px); opacity: .5; will-change: transform; }
.ct-blob.b1 { width: 46vw; max-width: 620px; aspect-ratio: 1; left: -16vw; bottom: -18vw; background: var(--ambient-1);
  animation: ct-drift-a 22s ease-in-out infinite; }
.ct-blob.b2 { width: 40vw; max-width: 540px; aspect-ratio: 1; right: -10vw; top: -8vw; background: var(--ambient-2);
  animation: ct-drift-b 27s ease-in-out infinite; }
.ct-blob.b3 { width: 34vw; max-width: 460px; aspect-ratio: 1; right: 16vw; bottom: -12vw; opacity: .3;
  background: var(--ambient-1); animation: ct-drift-c 31s ease-in-out infinite; }
[data-theme="light"] .ct-blob.b3 { opacity: .18; }
@keyframes ct-drift-a { 50% { transform: translate3d(7vw, -4vw, 0) scale(1.14); } }
@keyframes ct-drift-b { 50% { transform: translate3d(-6vw, 5vw, 0) scale(1.1); } }
@keyframes ct-drift-c { 50% { transform: translate3d(-9vw, -6vw, 0) scale(.86); } }

.ct-crumbs ol { display: flex; flex-wrap: wrap; gap: .35rem; margin: 0 0 1rem; padding: 0; list-style: none; font-size: .8rem; color: var(--text-2); }
.ct-crumbs li + li::before { content: '›'; margin-right: .35rem; color: var(--text-3); }
.ct-crumbs a { color: var(--text-2); text-decoration: underline; text-underline-offset: 3px; }

.ct-chips { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 1.1rem; }
.ct-chips span { display: inline-flex; align-items: center; gap: .42rem; padding: .4rem .8rem; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--orange) 26%, transparent); background: var(--tint);
  color: var(--mg-accent-text); font-size: .765rem; font-weight: 700; letter-spacing: 0; }
.ct-chips svg { width: 14px; height: 14px; flex: none; }
/* The icon glints in turn, left to right — the label itself never moves. */
.ct-chips span:nth-child(1) svg { animation: ct-glint 6s ease-in-out infinite; }
.ct-chips span:nth-child(2) svg { animation: ct-glint 6s ease-in-out .5s infinite; }
.ct-chips span:nth-child(3) svg { animation: ct-glint 6s ease-in-out 1s infinite; }
@keyframes ct-glint { 0%, 74%, 100% { transform: none; } 80% { transform: scale(1.22) rotate(-9deg); } 88% { transform: scale(1.05) rotate(4deg); } }

.ct-hero h1 { margin: 0; font-size: clamp(2.25rem, 4.4vw, 3.35rem); font-weight: 800; line-height: 1.07;
  letter-spacing: -.032em; }
/* A wider ramp than the shared token, swept slowly across the clipped text.
   Text-fill stays transparent either way, so a stalled animation still reads. */
.ct-hero h1 .gradient-text { background-image: linear-gradient(96deg, var(--orange), var(--yellow) 52%, var(--orange));
  background-size: 240% 100%; animation: ct-sheen 16s linear infinite; }
@keyframes ct-sheen { to { background-position: 300% 0; } }



.ct-lede { margin: 1.15rem 0 0; max-width: 52ch; color: var(--text-2);
  font-size: clamp(1.02rem, 1.2vw, 1.13rem); line-height: 1.68; }
.ct-lede strong { color: var(--text); font-weight: 800; }
.ct-ctas { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.7rem; }

/* The one call to action: a warmer ramp than the shared button, a glow that
   breathes, and a highlight that sweeps across every few seconds. */
.ct-cta { position: relative; overflow: hidden; isolation: isolate; padding: 1rem 1.9rem; font-size: 1rem; font-weight: 700;
  letter-spacing: -.005em;
  background-image: linear-gradient(100deg, var(--yellow), var(--orange) 58%, var(--orange-strong));
  background-size: 200% 100%; box-shadow: 0 10px 28px color-mix(in srgb, var(--orange) 34%, transparent); }
.ct-cta::after { content: ''; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%; z-index: -1;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.42), transparent); transform: skewX(-18deg);
  animation: ct-shine 4.5s ease-in-out 1.2s infinite; }
.ct-cta:hover { background-position: 100% 0; transform: translateY(-2px);
  box-shadow: 0 16px 36px color-mix(in srgb, var(--orange) 46%, transparent); }
.ct-cta:active { transform: translateY(0); }
@keyframes ct-shine { 0% { left: -60%; } 34%, 100% { left: 130%; } }

.ct-fine { display: flex; align-items: flex-start; gap: .5rem; margin: 1.15rem 0 0; max-width: 46ch;
  font-size: .8125rem; color: var(--text-3); line-height: 1.6; }
.ct-fine-icon { width: 15px; height: 15px; flex: none; margin-top: .15rem; color: var(--text-3); }

/* ── The example result, and the scene around it ──────────────────────── */
.ct-demo { margin: 0; perspective: 1400px; }
/* The card stays in normal flow and sets the stage height; the orbits, the
   faces and the sparks are absolutely positioned over it, so nothing here
   can reflow the card or shift the page. --rx/--ry come from the pointer
   (js/compat-hero.js) and are 0 until it moves. */
.ct-stage { --rx: 0deg; --ry: 0deg; --pad-y: clamp(34px, 10%, 62px); --pad-x: clamp(26px, 9%, 56px);
  position: relative; padding: var(--pad-y) var(--pad-x);
  transform-style: preserve-3d; transform: rotateX(var(--rx)) rotateY(var(--ry));
  transition: transform .5s cubic-bezier(.22, 1, .36, 1); }
.ct-stage.is-tracking { transition: transform .12s linear; }

.ct-orbits { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; transform: translateZ(-60px); }
.ct-orbit { fill: none; stroke-width: 1.4; stroke-dasharray: 3 10; stroke-linecap: round; transform-origin: 50% 50%; }
.ct-orbit.a { stroke: url(#ctOrbA); animation: ct-spin 56s linear infinite; }
.ct-comet { filter: drop-shadow(0 0 6px currentColor); }
.ct-comet.c1 { fill: var(--orange); color: var(--orange); opacity: .8; }
@keyframes ct-spin { to { transform: rotate(360deg); } }

/* The perimeter of the scene. Nothing is interactive out here; it drifts on
   a CSS clock and is dropped from the reading order entirely. */
.ct-orbiters { position: absolute; inset: 0; pointer-events: none; transform: translateZ(76px); }
.ct-house { position: absolute; left: 46%; bottom: 0; width: 30px; height: 30px; color: var(--orange); opacity: .75;
  animation: ct-float 6.2s ease-in-out -2.8s infinite; }
.ct-house svg { width: 100%; height: 100%; }
@keyframes ct-float { 0%, 100% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, -7px, 0); } }

/* The card. Its border is a lit conic sweep that never stops turning. */
.ct-demo-card { position: relative; display: grid; gap: .85rem; padding: 1.4rem; border-radius: 26px;
  border: 1.6px solid transparent; box-shadow: var(--shadow-lg); transform: rotate(1.2deg) translateZ(40px);
  background:
    linear-gradient(var(--bg-card), var(--bg-card)) padding-box,
    conic-gradient(from var(--ang),
      color-mix(in srgb, var(--text) 13%, transparent) 0deg,
      color-mix(in srgb, var(--orange) 85%, transparent) 62deg,
      var(--yellow) 96deg,
      color-mix(in srgb, var(--orange) 55%, transparent) 136deg,
      color-mix(in srgb, var(--text) 13%, transparent) 210deg,
      color-mix(in srgb, var(--text) 13%, transparent) 360deg) border-box;
  animation: ct-card-in .9s cubic-bezier(.2, .9, .3, 1) both, ct-rotate 9s linear infinite; }
/* The halo is a sibling, not a pseudo-element, for the same reason: it has
   to be genuinely behind the card, and inset off the stage's own padding is
   the only thing that tracks the card's box without measuring it. */
.ct-card-glow { position: absolute; inset: calc(var(--pad-y) - 16px) calc(var(--pad-x) - 16px);
  border-radius: 40px; opacity: .4; filter: blur(32px); pointer-events: none; transform: translateZ(10px);
  background: conic-gradient(from var(--ang), transparent 0deg,
    color-mix(in srgb, var(--orange) 60%, transparent) 70deg,
    color-mix(in srgb, var(--yellow) 50%, transparent) 120deg,
    transparent 230deg, transparent 360deg);
  animation: ct-rotate 9s linear infinite; }
[data-theme="light"] .ct-card-glow { opacity: .22; }
@keyframes ct-rotate { to { --ang: 360deg; } }
@keyframes ct-card-in { from { opacity: 0; transform: rotate(5deg) translate3d(0, 26px, 0) scale(.94); } }

.ct-demo-people { display: flex; align-items: center; gap: .9rem; padding-bottom: .9rem; border-bottom: 1px dashed var(--border-2); }
.ct-demo-people .mg-avatar { width: 52px; height: 52px; animation: ct-float 6.6s ease-in-out infinite; }
.ct-demo-people .mg-avatar:nth-child(2) { animation-delay: -2.2s; }
.ct-demo-people .mg-avatar:nth-child(3) { animation-delay: -4.4s; }
.ct-demo-people .mg-avatar-face { font-size: 28px; }
.ct-demo-open { position: relative; display: grid; place-items: center; width: 52px; height: 52px;
  color: var(--text-2); font-weight: 800; font-size: .9rem; }
/* The ring turns; the "+2" inside it must not, or it reads as a stray glyph. */
.ct-demo-open::before { content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 2px dashed var(--border-2); animation: ct-spin 30s linear infinite; }
.ct-demo-pair { display: flex; align-items: center; gap: .8rem; }
.ct-demo-names { flex: 1; min-width: 0; }
.ct-demo-names strong { display: block; font-size: 1.0625rem; font-weight: 700; letter-spacing: -.012em; }
.ct-demo-names span { font-size: .8125rem; color: var(--green); font-weight: 700; }

/* The gauge fills from empty; the number beside it is counted up in JS and
   is already correct in the markup if JS never runs. */
.ct-demo .mg-ring { width: 78px; height: 78px; filter: drop-shadow(0 0 10px color-mix(in srgb, var(--green) 28%, transparent));
  animation: ct-fill 1.8s cubic-bezier(.25, 1, .3, 1) .35s both; }
.ct-demo .mg-ring::before { inset: 8px; }
.ct-demo .mg-ring b { font-size: 1.22rem; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
@keyframes ct-fill { from { --p: 0; } }

.ct-demo-line { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .42rem; margin: 0;
  font-size: .875rem; line-height: 1.62; color: var(--text-2); }
/* The lead-in is a label, not part of the sentence: micro, tracked, quiet. */
.ct-demo-line strong { flex-basis: 100%; font-size: .675rem; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-3); }
.ct-demo-line.warn { display: block; }
.ct-demo-line.warn strong { display: block; margin-bottom: .3rem; color: var(--mg-accent-text); }
.ct-sync { display: inline-block; padding: .16rem .5rem; border-radius: 7px; background: var(--tint);
  color: var(--text); font-size: .8125rem; font-weight: 600;
  animation: ct-pop .5s cubic-bezier(.2, 1.4, .4, 1) both; }
.ct-sync:nth-of-type(1) { animation-delay: 1.15s; }
.ct-sync:nth-of-type(2) { animation-delay: 1.3s; }
.ct-sync:nth-of-type(3) { animation-delay: 1.45s; }
.ct-dot { color: var(--text-3); }
@keyframes ct-pop { from { opacity: 0; transform: translateY(6px) scale(.86); } }

.ct-demo-starter { display: flex; align-items: center; gap: .55rem; margin: 0; padding: .8rem .9rem; border-radius: 16px;
  background: var(--bg-2); font-size: .8375rem; font-weight: 500; line-height: 1.55; color: var(--text);
  animation: ct-pop .6s cubic-bezier(.2, 1.1, .4, 1) 1.6s both; }
.ct-demo-bubble { flex: none; width: 17px; height: 17px; color: var(--mg-accent-text);
  animation: ct-nudge 3.4s ease-in-out 2.4s infinite; }
.ct-demo-chev { width: 16px; height: 16px; flex: none; margin-left: auto; color: var(--text-3);
  animation: ct-nudge-x 2.6s ease-in-out infinite; }
@keyframes ct-nudge { 0%, 78%, 100% { transform: none; } 86% { transform: translateY(-3px) rotate(-8deg); } }
@keyframes ct-nudge-x { 0%, 100% { transform: none; } 50% { transform: translateX(3px); } }

.ct-demo figcaption { margin-top: 1.15rem; text-align: center; font-size: .78rem; color: var(--text-3); }

/* ── Scroll choreography ─────────────────────────────────────────────────
   The page has two motions and they are kept on two different properties on
   purpose, so neither needs a wrapper element and neither can clobber the
   other:

     ARRIVAL  owns `translate` + `opacity` — each block fades and rises the
              first time it reaches the viewport, siblings in turn.
     DRIFT    owns `transform` — the decoration behind each section, and the
              cards in the factors grid, ride the scroll at their own speed.
              js/ct-parallax.js writes one length, --ct-py, per frame; what
              moves because of it is decided here.

   The hover lift is the third property, `scale` (see the shared card rule).

   Both are gated on `ct-motion`, which the script adds only when it has an
   IntersectionObserver to work with and the visitor has not asked for less
   motion. Nothing starts hidden without it. ------------------------------ */
html.ct-motion [data-ct-reveal] {
  --ct-rise: 30px;                /* declared, not defaulted in var(), so a */
  opacity: 0;                     /* revealed parent cannot zero a child    */
  translate: 0 var(--ct-rise);
  transition: opacity .75s cubic-bezier(.22, .78, .28, 1) var(--ct-delay, 0s),
              translate .75s cubic-bezier(.22, .78, .28, 1) var(--ct-delay, 0s);
}
html.ct-motion [data-ct-reveal].is-in { --ct-rise: 0px; opacity: 1; }

html.ct-motion [data-ct-px] { transform: translate3d(0, var(--ct-py, 0px), 0); }
/* On paper there is no scroll to arrive on, and a block still waiting for
   its observer would print as a blank. */
@media print {
  html.ct-motion [data-ct-reveal] { opacity: 1; translate: none; transition: none; }
  html.ct-motion [data-ct-px], html.ct-motion .ct-section[data-ct-px]::before { transform: none; }
}
/* A section carries the value for its own ambient wash rather than moving
   itself — the band, its hairlines and everything in the flow stay put. */
html.ct-motion .ct-section[data-ct-px] { transform: none; }
html.ct-motion .ct-section[data-ct-px]::before { transform: translate3d(0, var(--ct-py, 0px), 0); }
/* The hero's light is the one drifting layer above the fold, and it is
   given room to travel so a shifted blob never uncovers a corner. That room
   is taken below the hero as well, and the layer clips its own blurred blobs
   (overflow + contain) — so left alone its bottom edge is a hard line drawn
   straight across the section underneath, between that section's kicker and
   its heading. Dissolve the layer over exactly the spill instead: the hero's
   own bottom sits at 1.22/1.36 of this box, so the light inside the hero is
   untouched and there is nothing left to cut by the time the next section
   starts. */
html.ct-motion .ct-aurora { inset: -22% -6% -14%;
  -webkit-mask-image: linear-gradient(to bottom, #000 89.7%, transparent 98%);
          mask-image: linear-gradient(to bottom, #000 89.7%, transparent 98%); }

/* ── Sections ─────────────────────────────────────────────────────────────
   Below the hero the page is one material: a card cut from --bg-card with a
   hairline, a sheen down its top edge and an orange accent. The sheen is
   mixed from --text rather than written as white, so the same declaration is
   a highlight in dark and a soft grey in light. Sections are `clip`ped
   because each one paints its own ambient bloom past the container. ------- */
.ct-section { position: relative; overflow: hidden; overflow: clip; padding: clamp(3.5rem, 7vw, 5.5rem) 0; }
.ct-section > .container { position: relative; z-index: 1; }
.ct-alt { background: var(--band); border-block: 1px solid var(--border); }
/* The banded sections get the same light as the hero, just far dimmer. */
.ct-alt::before { content: ''; position: absolute; inset: -60px 0; pointer-events: none;
  background: radial-gradient(42rem 22rem at 94% -10%, var(--ambient-1), transparent 68%),
              radial-gradient(34rem 20rem at 2% 110%, var(--ambient-2), transparent 70%); }
/* The same ambient light for the unbanded sections, as a layer of its own so
   it can be drifted independently of the section it sits in. */
.ct-drift { position: absolute; inset: -60px -4%; pointer-events: none; z-index: 0;
  background: radial-gradient(38rem 22rem at 6% 8%, var(--ambient-1), transparent 66%),
              radial-gradient(32rem 20rem at 96% 88%, var(--ambient-2), transparent 70%); }
.ct-drift.alt { background: radial-gradient(34rem 20rem at 88% 4%, var(--ambient-1), transparent 68%),
                            radial-gradient(30rem 20rem at 8% 96%, var(--ambient-2), transparent 72%); }
[data-theme="light"] .ct-drift { opacity: .8; }
.ct-kicker { margin: 0 0 .7rem; font-size: .72rem; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--mg-accent-text); }
.ct-section h2 { margin: 0; font-size: clamp(1.9rem, 3vw, 2.55rem); font-weight: 800; line-height: 1.1;
  letter-spacing: -.03em; }
.ct-intro { max-width: 62ch; margin: 1rem 0 0; color: var(--text-2); font-size: 1rem; line-height: 1.72; }
.ct-note { margin: 1.6rem 0 0; font-size: var(--ct-body); color: var(--text-2); line-height: 1.65; }

/* The one card surface, shared by every section below the hero. */
.ct-steps li, .ct-factor, .ct-q, .ct-uses article, .ct-faq details {
  border: 1px solid var(--border); background: linear-gradient(180deg, color-mix(in srgb, var(--text) 5%, transparent), transparent 46%), var(--bg-card);
  box-shadow: var(--shadow-sm), inset 0 1px 0 color-mix(in srgb, var(--text) 8%, transparent);
  transition: scale var(--t), border-color var(--t), box-shadow var(--t);
}
/* The lift is `scale`, not a translate, and that is load-bearing: `translate`
   is spoken for by the scroll arrival and `transform` by the drift, so the
   hover needs the third property to itself. Only for a pointer that can
   actually hover — on a touch screen the rule would latch after a tap. */
@media (hover: hover) {
  .ct-steps li:hover, .ct-factor:hover, .ct-q:hover, .ct-uses article:hover {
    scale: 1.017; border-color: color-mix(in srgb, var(--orange) 34%, transparent);
    box-shadow: var(--shadow-md), 0 0 0 1px color-mix(in srgb, var(--orange) 10%, transparent),
                inset 0 1px 0 color-mix(in srgb, var(--text) 10%, transparent);
  }
}
.ct-faq details:hover { border-color: color-mix(in srgb, var(--orange) 26%, transparent); }

/* ── How it works ─────────────────────────────────────────────────────────
   The illustrated section. Three decorative layers sit behind the copy: an
   ambient bloom, a flight path that leaves at the top right, and a dotted
   run threaded through the step badges. All three are drawn behind the cards
   and none of them is in the flow, so the steps read the same without them.
   The four scenes are inline SVG: they repaint with the theme (every colour
   is mixed from --text or the brand tokens) and cost no request. --------- */
.ct-how-glow { position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(40rem 26rem at 2% 96%, var(--ambient-1), transparent 68%),
              radial-gradient(36rem 26rem at 99% 26%, var(--ambient-2), transparent 70%); }
[data-theme="light"] .ct-how-glow { opacity: .6; }

.ct-how-trail { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.ct-how-trail .t0 { stop-color: var(--orange); stop-opacity: 0; }
.ct-how-trail .t1 { stop-color: var(--orange); stop-opacity: .5; }
.ct-how-trail .t2 { stop-color: var(--orange); stop-opacity: .95; }
.ct-how-trail .t3 { stop-color: var(--yellow); stop-opacity: 1; }
.ct-trail-arc { fill: none; stroke: url(#ctTrailGrad); stroke-width: 1.6; }
.ct-trail-arc.faint { stroke-width: 1.1; stroke-dasharray: 2 9; stroke-linecap: round; opacity: .5; }
/* The plane sits on the end of the path — 1364,128 of the 1440x760 viewBox —
   as its own element, because the viewBox is stretched and a filled shape
   put inside it would be stretched with it. --fly is the tangent there, and
   the drift rides along that heading rather than across the screen. */
.ct-how-plane { --fly: -52deg; position: absolute; left: 90.3%; top: 18.4%; width: 44px; height: 39px;
  margin: -19px 0 0 -22px; pointer-events: none; transform: rotate(var(--fly));
  filter: drop-shadow(0 2px 14px color-mix(in srgb, var(--orange) 75%, transparent));
  animation: ct-fly 9s ease-in-out infinite; }
.ct-how-plane svg { display: block; width: 100%; height: 100%; }
.ct-how-plane .p-top { fill: var(--yellow); }
.ct-how-plane .p-bot { fill: var(--orange); }
.ct-how-plane .p-keel { fill: var(--orange-strong); }
@keyframes ct-fly {
  0%, 100% { transform: rotate(var(--fly)) translateX(0); }
  50%      { transform: rotate(var(--fly)) translateX(11px); }
}
[data-theme="light"] .ct-how-trail { opacity: .8; }

.ct-steps { position: relative; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem;
  margin: 2.6rem 0 0; padding: 0; list-style: none; }
/* The dotted run sits on the card's top edge — where the badges are centred —
   and behind them, so it only ever shows in the gaps between cards. */
.ct-steps::before { content: ''; position: absolute; z-index: 0; left: 2.6rem; right: 2.6rem; top: 0;
  border-top: 2px dashed color-mix(in srgb, var(--orange) 42%, transparent); }
.ct-steps li { position: relative; z-index: 1; padding: 1.5rem 1.25rem 1.6rem; border-radius: 22px; }

.ct-step-n { position: absolute; top: 0; left: 1.4rem; z-index: 2; display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 50%; background: var(--grad-brand); color: #fff;
  font-size: 1.05rem; font-weight: 800; transform: translateY(-50%);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--orange) 55%, transparent),
              0 0 30px color-mix(in srgb, var(--orange) 45%, transparent); }

.ct-step-art { position: relative; display: block; height: 116px; margin: .9rem 0 1.15rem; }
.ct-step-art::before { content: ''; position: absolute; inset: -8% -4%; border-radius: 22px;
  background: radial-gradient(68% 66% at 50% 46%, color-mix(in srgb, var(--orange) 15%, transparent), transparent 70%); }
.ct-step-art svg { position: relative; display: block; width: 100%; height: 100%; overflow: visible; }

/* The scene parts. Neutrals are mixed from --text so one set of rules draws
   in both themes; only the accents are brand colours. */
.a-panel { fill: color-mix(in srgb, var(--text) 9%, transparent); stroke: color-mix(in srgb, var(--text) 17%, transparent); stroke-width: 1.2; }
.a-panel.dim { fill: color-mix(in srgb, var(--text) 5%, transparent); }
.a-panel.lit { fill: color-mix(in srgb, var(--orange) 15%, transparent); stroke: color-mix(in srgb, var(--orange) 36%, transparent); }
.a-tile { fill: var(--orange); }
.a-ink { fill: none; stroke: #fff; stroke-width: 2.6; }
.a-ink.thin { stroke: color-mix(in srgb, var(--text) 52%, transparent); stroke-width: 1.7; }
.a-ink.faint { stroke: color-mix(in srgb, var(--text) 26%, transparent); }
.a-avatars .a-ink { stroke: var(--orange); stroke-width: 2.1; }
.a-line { fill: color-mix(in srgb, var(--text) 27%, transparent); }
.a-line.dim { fill: color-mix(in srgb, var(--text) 14%, transparent); }
.a-chip { fill: color-mix(in srgb, var(--text) 16%, transparent); }
.a-chip.dim { fill: color-mix(in srgb, var(--text) 9%, transparent); }
.a-dot { fill: color-mix(in srgb, var(--text) 36%, transparent); }
.a-spark { fill: var(--yellow); opacity: .9; }
.a-spark.sm { fill: var(--orange); opacity: .75; }
.a-heart { fill: color-mix(in srgb, var(--orange) 58%, transparent); }
.a-squiggle { fill: none; stroke: var(--orange); stroke-width: 3.2; }
.a-label { fill: var(--text); font: 800 14px var(--font); letter-spacing: -.01em; }
.a-score { fill: var(--text); font: 800 17px var(--font); text-anchor: middle; }
.av { stroke: color-mix(in srgb, var(--text) 20%, transparent); stroke-width: 1.4; }
/* Four people, told apart by tone within the one brand hue rather than by
   four unrelated colours. */
.av.a1 { fill: color-mix(in srgb, var(--orange) 42%, var(--bg-card)); }
.av.a2 { fill: var(--orange); }
.av.a3 { fill: var(--yellow); }
.av.a4 { fill: var(--orange-strong); }
.a-add { fill: none; stroke: color-mix(in srgb, var(--orange) 55%, transparent); stroke-width: 1.6; stroke-dasharray: 4 4; }
/* The people in scenes two and three: a ringed bubble with a silhouette
   knocked out of it in the card's own colour, so it reads at 34px. */
.a-head, .a-body { fill: var(--bg-card); opacity: .92; }
.a-thread { fill: none; stroke: color-mix(in srgb, var(--orange) 70%, transparent); stroke-width: 1.8;
  stroke-dasharray: 2 5; stroke-linecap: round; }
/* The invites leaving the link: four of them, so each one is drawn lighter
   than the single connector in scene three. */
.a-thread.fan { stroke: color-mix(in srgb, var(--orange) 46%, transparent); stroke-width: 1.4; stroke-dasharray: 1.5 5; }
.a-url { fill: var(--text-2); font: 600 11.5px var(--font); }
.a-send { fill: var(--orange); }
.a-send-ink { fill: #fff; }
.a-pill { fill: color-mix(in srgb, var(--orange) 18%, transparent); stroke: color-mix(in srgb, var(--orange) 42%, transparent); stroke-width: 1.2; }
.a-pill-text { fill: var(--mg-accent-text); font: 800 9.5px var(--font); letter-spacing: .09em; text-anchor: middle; }
.a-dial-bg { fill: color-mix(in srgb, var(--text) 7%, transparent); }
.a-dial-track { fill: none; stroke: color-mix(in srgb, var(--text) 15%, transparent); stroke-width: 7; }
/* r=29 → circumference 182.2; 88% leaves 21.9 of it empty. */
.a-dial-fill { fill: none; stroke: var(--orange); stroke-width: 7; stroke-linecap: round;
  stroke-dasharray: 182.2; stroke-dashoffset: 21.9; }

.ct-steps h3, .ct-factor h3, .ct-uses h3 { margin: .85rem 0 .45rem; font-size: var(--ct-h3); font-weight: 700;
  line-height: 1.32; letter-spacing: -.014em; }
.ct-steps h3 { margin-top: 0; }
/* Side by side the titles have to leave their copy on one baseline, and they
   do not all wrap the same way — "Invite up to four friends" fits on one
   line where the other three take two, which lifted its paragraph a line
   above its neighbours'. Reserve the taller of the two boxes for every
   title (2 lines at the 1.32 line-height above). Dropped once the cards
   stack, where there is no neighbour to line up with. */
@media (min-width: 601px) {
  .ct-steps h3 { min-height: 2.64em; }
}
.ct-steps p, .ct-factor p, .ct-uses p { margin: 0; font-size: var(--ct-body); color: var(--text-2);
  line-height: var(--ct-lh-body); }

/* The footnote under the steps: one bar, the caveat on the left and the way
   to read more about it on the right. */
.ct-note-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.1rem; margin-top: 2.2rem;
  padding: .85rem 1.3rem; border: 1px solid var(--border); border-radius: 999px;
  background: color-mix(in srgb, var(--bg-card) 72%, transparent); backdrop-filter: blur(8px); }
.ct-note-icon { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 11px;
  background: var(--tint-2); color: var(--mg-accent-text); }
.ct-note-icon svg { width: 18px; height: 18px; }
.ct-note-text { flex: 1 1 22rem; }
.ct-note-link { flex: none; display: inline-flex; align-items: center; gap: .4rem; }
.ct-note-link svg { width: 15px; height: 15px; transition: transform var(--t); }
.ct-note-link:hover svg { transform: translateX(3px); }

/* ── What makes roommates compatible ─────────────────────────────────────
   Twelve cards on two belts that run past each other. Behind them, and not
   in the flow, sit the same two layers as before: a soft wash of the four
   topic accents and a ruled backdrop that drifts the other way. Each card
   carries one accent, --f-a, rotated four-wide; it tints the icon tile, the
   corner bloom and the rule along the top edge, and nothing else, so the
   section still reads as one material rather than twelve. ---------------- */
.ct-factors-bg, .ct-factors-rule { position: absolute; inset: -70px -6%; pointer-events: none; z-index: 0; }
.ct-factors-bg {
  background: radial-gradient(30rem 22rem at 12% 14%, color-mix(in srgb, var(--orange) 12%, transparent), transparent 70%),
              radial-gradient(28rem 20rem at 88% 74%, color-mix(in srgb, var(--yellow) 11%, transparent), transparent 72%),
              radial-gradient(24rem 18rem at 62% 4%, color-mix(in srgb, var(--orange) 8%, transparent), transparent 74%);
}
[data-theme="light"] .ct-factors-bg { opacity: .78; }
/* Faint verticals, one per grid column at the widest layout. Masked to a
   soft oval so the lines never reach an edge and give the drift away. */
.ct-factors-rule {
  opacity: .9;
  background-image: repeating-linear-gradient(90deg,
    color-mix(in srgb, var(--text) 7%, transparent) 0 1px, transparent 1px clamp(96px, 11vw, 168px));
  -webkit-mask-image: radial-gradient(66% 58% at 50% 46%, #000 30%, transparent 78%);
          mask-image: radial-gradient(66% 58% at 50% 46%, #000 30%, transparent 78%);
}

.ct-marquee {
  --mq-gap: clamp(.9rem, 1.5vw, 1.15rem);
  display: grid; gap: var(--mq-gap); margin: 2.4rem 0 0;
  /* Full-bleed. The strip runs to the window edges rather than stopping at
     the container gutter, so there is always a card entering; the section is
     `clip`ped, so the extra width never reaches the document. */
  margin-inline: calc(50% - 50vw);
  /* The fade is a length, not a percentage: at 5% of a phone it is 20px and
     the cards read as cut off rather than as running past the edge. */
  --mq-fade: clamp(44px, 7vw, 96px);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--mq-fade), #000 calc(100% - var(--mq-fade)), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 var(--mq-fade), #000 calc(100% - var(--mq-fade)), transparent);
}
/* The row is the window, the track is the belt. Until the script has cloned
   the belt this is an ordinary strip you scroll or swipe by hand — which is
   what a visitor with JS off or motion turned down gets, and it is why the
   default here is `auto` rather than `hidden`. */
.ct-mq-row { overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  scrollbar-width: none; -ms-overflow-style: none; }
.ct-mq-row::-webkit-scrollbar { display: none; }
.ct-mq-track { display: flex; align-items: stretch; width: max-content; padding-block: 4px; }

/* The loop is exact because the belt is translated by half of itself and the
   belt is two identical copies. The gap rides on each card as a margin
   rather than on the track as `gap`: with `gap`, half the belt would be one
   full set of cards *minus* one gap, and the seam would tick once a lap. */
html.ct-motion .ct-marquee.is-live .ct-mq-row { overflow: hidden; }
html.ct-motion .ct-marquee.is-live .ct-mq-track {
  animation: ct-mq var(--mq-dur, 60s) linear infinite; will-change: transform; }
html.ct-motion .ct-marquee.is-live .ct-mq-rev .ct-mq-track { animation-direction: reverse; }
@keyframes ct-mq { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }
/* Stop under the pointer so a card can actually be read, and stop for a
   keyboard too — a link inside a card that is sliding away is unusable. */
@media (hover: hover) {
  html.ct-motion .ct-marquee.is-live .ct-mq-row:hover .ct-mq-track { animation-play-state: paused; }
}
html.ct-motion .ct-marquee.is-live .ct-mq-row:focus-within .ct-mq-track { animation-play-state: paused; }

.ct-factor { flex: none; width: clamp(236px, 23vw, 292px); margin-inline-end: var(--mq-gap);
  position: relative; overflow: hidden; isolation: isolate;
  padding: 1.4rem 1.35rem 1.5rem; border-radius: 20px; }
/* The accent is carried by a class, not nth-child: the script clones each
   belt, and a positional rule would restart the four-colour rotation at the
   seam. */
.ct-factor.fa1 { --f-a: var(--orange); }
.ct-factor.fa2 { --f-a: var(--yellow); }
.ct-factor.fa3 { --f-a: var(--orange-strong); }
.ct-factor.fa4 { --f-a: color-mix(in srgb, var(--orange) 62%, var(--yellow)); }
/* A bloom in the corner behind the icon, and a rule along the top edge that
   runs the width of the card when you point at it. */
.ct-factor::before { content: ''; position: absolute; z-index: -1; inset: -55% 52% 58% -45%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--f-a) 24%, transparent), transparent 72%);
  opacity: .42; transition: opacity var(--t); }
.ct-factor::after { content: ''; position: absolute; inset: 0 auto auto 0; width: 38%; height: 2px;
  background: linear-gradient(90deg, var(--f-a), transparent);
  transition: width .5s cubic-bezier(.22, .78, .28, 1); }
.ct-factor-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.ct-factor-icon { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 15px;
  font-size: 1.35rem; line-height: 1;
  background: color-mix(in srgb, var(--f-a) 13%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--f-a) 32%, transparent);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--f-a) 16%, transparent);
  transition: scale var(--t), box-shadow var(--t); }
.ct-factor-n { font-size: 1.4rem; font-weight: 800; line-height: 1; letter-spacing: -.05em;
  font-variant-numeric: tabular-nums; color: color-mix(in srgb, var(--text) 15%, transparent);
  transition: color var(--t); }
@media (hover: hover) {
  .ct-factor:hover::after { width: 100%; }
  .ct-factor:hover::before { opacity: .85; }
  .ct-factor:hover .ct-factor-icon { scale: 1.06; box-shadow: 0 10px 24px color-mix(in srgb, var(--f-a) 28%, transparent); }
  .ct-factor:hover .ct-factor-n { color: color-mix(in srgb, var(--f-a) 62%, var(--text)); }
  /* The card's own accent takes over the shared orange hover edge. */
  .ct-factor:hover { border-color: color-mix(in srgb, var(--f-a) 40%, transparent);
    box-shadow: var(--shadow-md), 0 0 0 1px color-mix(in srgb, var(--f-a) 14%, transparent),
                inset 0 1px 0 color-mix(in srgb, var(--text) 10%, transparent); }
}
.ct-factor h3 { margin: 1rem 0 .4rem; }

/* ── Questions to ask ───────────────────────────────────────────────────
   Six topic sheets. Each one carries an accent, --q-a, on the same four-wide
   rotation as the factor cards, and each question sits on its own small
   surface with the quote mark hung in the gutter — these are lines you say
   out loud, so they are set to be read off one at a time rather than skimmed
   as bullets. --------------------------------------------------------- */
.ct-questions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(.9rem, 1.5vw, 1.1rem); margin-top: 2.4rem; }
.ct-q { position: relative; overflow: hidden; isolation: isolate;
  padding: 1.35rem 1.3rem 1.4rem; border-radius: 20px; }
.ct-q.qa1 { --q-a: var(--orange); }
.ct-q.qa2 { --q-a: var(--yellow); }
.ct-q.qa3 { --q-a: var(--orange-strong); }
.ct-q.qa4 { --q-a: color-mix(in srgb, var(--orange) 62%, var(--yellow)); }
.ct-q::before { content: ''; position: absolute; z-index: -1; inset: -58% 54% 60% -46%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--q-a) 22%, transparent), transparent 72%);
  opacity: .5; transition: opacity var(--t); }
.ct-q::after { content: ''; position: absolute; inset: 0 auto auto 0; width: 44%; height: 2px;
  background: linear-gradient(90deg, var(--q-a), transparent);
  transition: width .5s cubic-bezier(.22, .78, .28, 1); }
.ct-q-head { display: flex; align-items: center; gap: .7rem; margin-bottom: 1rem; }
.ct-q-icon { flex: none; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 14px;
  font-size: 1.2rem; line-height: 1;
  background: color-mix(in srgb, var(--q-a) 13%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--q-a) 32%, transparent);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--q-a) 16%, transparent);
  transition: scale var(--t), box-shadow var(--t); }
.ct-q-title { display: grid; gap: .16rem; min-width: 0; }
.ct-q-eyebrow { font-size: .66rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: color-mix(in srgb, var(--q-a) 60%, var(--text-3)); }
.ct-q h3 { margin: 0; font-size: var(--ct-h3); font-weight: 700; line-height: 1.3; letter-spacing: -.014em; }
.ct-questions ul { display: grid; gap: .5rem; margin: 0; padding: 0; list-style: none; }
.ct-questions li { position: relative; padding: .62rem .8rem .62rem 2.05rem; border-radius: 13px;
  font-size: var(--ct-body); line-height: 1.6; color: var(--text-2);
  background: color-mix(in srgb, var(--q-a) 5%, var(--bg-card-2));
  border: 1px solid color-mix(in srgb, var(--text) 8%, transparent);
  transition: border-color var(--t); }
.ct-questions li::before { content: '\201C'; position: absolute; left: .66rem; top: .28rem;
  font-size: 1.35rem; font-weight: 800; line-height: 1;
  color: color-mix(in srgb, var(--q-a) 72%, transparent); }
@media (hover: hover) {
  .ct-q:hover::after { width: 100%; }
  .ct-q:hover::before { opacity: .9; }
  .ct-q:hover .ct-q-icon { scale: 1.06; box-shadow: 0 10px 24px color-mix(in srgb, var(--q-a) 28%, transparent); }
  /* The card's own accent takes over the shared orange hover edge. */
  .ct-q:hover { border-color: color-mix(in srgb, var(--q-a) 40%, transparent);
    box-shadow: var(--shadow-md), 0 0 0 1px color-mix(in srgb, var(--q-a) 14%, transparent),
                inset 0 1px 0 color-mix(in srgb, var(--text) 10%, transparent); }
  .ct-questions li:hover { border-color: color-mix(in srgb, var(--q-a) 34%, transparent); }
}

/* ── Who it's for ───────────────────────────────────────────────────────
   Three scenes on the same 240x128 stage as the steps, drawn from the same
   a-* parts, with one looping detail each: the two signatures being written,
   the rooms lighting in turn, the pin landing on the map. Nothing in them
   carries meaning the copy does not, and all three are stilled at the foot
   of this file. ------------------------------------------------------- */
.ct-uses { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .9rem; margin-top: 2.2rem; }
.ct-uses article { position: relative; overflow: hidden; padding: 1.4rem 1.3rem; border-radius: 20px; }
/* A lit edge along the top of each card, brightest in the middle. */
.ct-uses article::before { content: ''; position: absolute; inset: 0 0 auto; height: 2px;
  background: linear-gradient(90deg, transparent, var(--orange) 50%, transparent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--orange) 55%, transparent); }
.ct-uses h3 { margin-top: 0; }

.ct-use-art { position: relative; display: block; height: 124px; margin: .35rem 0 1.15rem; }
.ct-use-art::before { content: ''; position: absolute; inset: -8% -4%; border-radius: 22px;
  background: radial-gradient(68% 66% at 50% 48%, color-mix(in srgb, var(--orange) 15%, transparent), transparent 70%); }
.ct-use-art svg { position: relative; display: block; width: 100%; height: 100%; overflow: visible; }

/* 1 — the lease. Both signatures are drawn on, held, then lifted; the paths
   carry pathLength="1", so one dash length fits every curve exactly. */
.u-rule { fill: none; stroke: color-mix(in srgb, var(--text) 22%, transparent); stroke-width: 1.4; stroke-dasharray: 3 3; }
.u-sign { fill: none; stroke: var(--orange); stroke-width: 2.4;
  stroke-dasharray: 1; stroke-dashoffset: 1; animation: u-sign 7s ease-in-out infinite; }
.u-sign.s2 { stroke: var(--yellow); animation-delay: 1.15s; }
@keyframes u-sign {
  0%, 5%    { stroke-dashoffset: 1; }
  32%, 80%  { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 1; }
}

/* 2 — the block. A wash of the room's own colour over the window, one after
   the next, so the building reads as filling up rather than blinking. */
.u-win { fill: var(--orange); opacity: 0; animation: u-lit 6.4s ease-in-out infinite; }
.u-win.w2 { fill: var(--yellow); animation-delay: .5s; }
.u-win.w3 { fill: var(--orange-strong); animation-delay: 1s; }
.u-win.w4 { fill: color-mix(in srgb, var(--orange) 62%, var(--yellow)); animation-delay: 1.5s; }
@keyframes u-lit { 0%, 100% { opacity: 0; } 20%, 70% { opacity: .2; } }

/* 3 — the new city: the route marches in and the pin drops onto the flat. */
.u-route { fill: none; stroke: color-mix(in srgb, var(--orange) 70%, transparent); stroke-width: 1.8;
  stroke-dasharray: 2 6; stroke-linecap: round; animation: u-march 2.6s linear infinite; }
@keyframes u-march { to { stroke-dashoffset: -8; } }
.u-pin-body { fill: var(--orange); }
.u-pin-hole { fill: var(--bg-card); }
.u-pin { animation: u-drop 4.4s cubic-bezier(.34, 1.36, .5, 1) infinite; }
@keyframes u-drop {
  0%        { transform: translateY(-16px); opacity: 0; }
  18%, 76%  { transform: translateY(0); opacity: 1; }
  90%, 100% { transform: translateY(-16px); opacity: 0; }
}
.u-shadow { fill: color-mix(in srgb, var(--text) 16%, transparent);
  animation: u-drop-shadow 4.4s cubic-bezier(.34, 1.36, .5, 1) infinite; }
@keyframes u-drop-shadow { 0%, 100% { opacity: 0; } 18%, 76% { opacity: 1; } }
.u-lights rect { animation: u-blink 5.2s ease-in-out infinite; }
.u-lights rect:nth-child(3n) { animation-delay: -1.7s; }
.u-lights rect:nth-child(3n + 2) { animation-delay: -3.4s; }
@keyframes u-blink { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

/* ── FAQ ────────────────────────────────────────────────────────────────
   Two columns, placed rather than wrapped: the heading rail on the left, the
   accordion on the right. The rail's left edge is the container gutter, so
   the kicker and the h2 begin on the same line as every other section — the
   old centred 860px column started a further 170px in, which is what made
   this section look like it belonged to a different page. The four items
   are still direct children of .container, because the arrival observer in
   js/ct-parallax.js keys on exactly that relationship; the columns are grid
   placement, not a wrapper. ------------------------------------------- */
.ct-faq-wrap { display: grid; grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
  grid-template-rows: auto auto auto 1fr; column-gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
.ct-faq-wrap > .ct-kicker { grid-area: 1 / 1; }
.ct-faq-wrap > h2         { grid-area: 2 / 1; }
.ct-faq-wrap > .ct-intro  { grid-area: 3 / 1; }
/* Row 4 is the 1fr row, so the footnote settles on the foot of the rail and
   the column ends level with the accordion instead of trailing off. */
.ct-faq-wrap > .ct-note   { grid-area: 4 / 1; align-self: end; }
.ct-faq-wrap > .ct-faq    { grid-area: 1 / 2 / 5 / 3; }

.ct-faq { display: grid; gap: .55rem; margin-top: 0; }
.ct-faq details { position: relative; scroll-margin-top: 110px; overflow: hidden; border-radius: 16px;
  transition: border-color var(--t), box-shadow var(--t); }
/* Open is a state worth seeing at a glance down the stack: a tinted head, an
   accent rail on the leading edge, and the toggle filled in. */
.ct-faq details[open]:not(.is-closing) { border-color: color-mix(in srgb, var(--orange) 30%, transparent);
  background: linear-gradient(180deg, var(--tint), transparent 44%), var(--bg-card); }
.ct-faq details[open]:not(.is-closing)::before { content: ''; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--grad-brand); }
.ct-faq summary { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 48px;
  padding: .95rem 1.1rem .95rem 1.25rem; cursor: pointer; list-style: none; }
.ct-faq summary::-webkit-details-marker { display: none; }
.ct-faq summary::after { content: '+'; flex: none; display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 50%; background: var(--tint-2); font-size: 1.15rem; font-weight: 700; line-height: 1;
  color: var(--mg-accent-text); transition: transform .3s cubic-bezier(.22, .8, .24, 1), background .2s, color .2s; }
.ct-faq details[open]:not(.is-closing) summary::after { transform: rotate(45deg); background: var(--grad-brand); color: #fff; }
.ct-faq summary h3 { margin: 0; font-size: 1.0625rem; font-weight: 700; line-height: 1.4; letter-spacing: -.012em; }
.ct-faq details p { margin: 0; padding: 0 1.1rem 1.1rem 1.25rem; color: var(--text-2); line-height: 1.7; font-size: .92rem;
  transition: opacity .2s; }
/* faq-accordion.js keeps a folding card [open] until the height settles. */
.ct-faq details.is-closing p { opacity: 0; }

.ct-final h2 { margin: .9rem 0 .8rem; }

/* The shared friends band (css/match-group.css) tints its third score badge
   violet. That file is also used by index.html, so it is left alone and the
   colour is brought into the brand here, on this page only. Green stays on
   the first badge: there it means a good score, same as the hero's ring. */
.ct-main .fd-score.s3 { color: var(--orange-strong); }


@media (max-width: 980px) {
  .ct-hero-grid { grid-template-columns: 1fr; }
  /* Stacked, the scene is centred and given a little more air. */
  .ct-demo { max-width: 520px; margin-inline: auto; }
  /* Two up: the dotted run no longer joins four badges in a line, and the
     flight path has nothing left to fly over. */
  .ct-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 2.4rem; }
  .ct-steps::before, .ct-how-trail, .ct-how-plane { display: none; }
  .ct-questions, .ct-uses { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* One column: the rail is no longer beside anything, so the placement is
     dropped and the four items fall back into reading order. */
  .ct-faq-wrap { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .ct-faq-wrap > .ct-kicker, .ct-faq-wrap > h2, .ct-faq-wrap > .ct-intro,
  .ct-faq-wrap > .ct-note, .ct-faq-wrap > .ct-faq { grid-area: auto; }
  .ct-faq { margin-top: 1.8rem; }
}
@media (max-width: 600px) {
  .ct-steps, .ct-questions, .ct-uses { grid-template-columns: 1fr; }
  /* The belts keep running on a phone — a narrower card so two are always
     partly in view, and no ruled backdrop: at this width it is denser than
     the strips it is meant to be echoing. */
  .ct-factor { width: clamp(220px, 74vw, 280px); padding: 1.25rem 1.2rem 1.35rem; }
  .ct-factors-rule { display: none; }
  .ct-use-art { height: 132px; }
  .ct-ctas .btn { width: 100%; justify-content: center; }
  .ct-step-art { height: 128px; }
  /* The bar becomes a stack, so it loses the pill shape and the link drops
     onto its own line rather than being squeezed against the caveat. */
  .ct-note-bar { border-radius: 20px; padding: 1rem 1.15rem; }
  .ct-note-text { flex-basis: 100%; }
  /* No room to orbit on a phone: the card squares up, the house goes, and the
     pointer tilt is switched off in JS anyway. */
  .ct-demo-card { transform: translateZ(40px); }
  .ct-stage { padding: 30px 26px; }
  .ct-house { display: none; }
  .ct-demo .mg-ring { width: 66px; height: 66px; }
  .ct-demo .mg-ring b { font-size: 1.05rem; }
  .ct-cta { padding: .95rem 1.4rem; font-size: 1rem; }
}
@media (prefers-reduced-motion: reduce) {
  .ct-faq summary::after, .ct-faq details p, .ct-note-link svg { transition: none; }
  .ct-steps li:hover, .ct-factor:hover, .ct-q:hover, .ct-uses article:hover { scale: none; }
  .ct-factor::before, .ct-factor::after, .ct-factor-icon, .ct-factor-n,
  .ct-q::before, .ct-q::after, .ct-q-icon { transition: none; }
  .ct-factor:hover::after { width: 38%; }
  .ct-q:hover::after { width: 44%; }
  .ct-factor:hover .ct-factor-icon, .ct-q:hover .ct-q-icon { scale: none; }
  /* The belts never start — the script does not arm `ct-motion` — but say so
     anyway, for a preference that changes after the class is on. */
  .ct-mq-track { animation: none; }
  html.ct-motion .ct-marquee.is-live .ct-mq-row { overflow-x: auto; }
  /* The three scenes settle into their finished state: both names signed,
     every room lit, the pin landed. */
  .u-sign { stroke-dashoffset: 0; animation: none; }
  .u-win { opacity: .2; animation: none; }
  .u-route, .u-lights rect { animation: none; }
  .u-pin, .u-shadow { transform: none; opacity: 1; animation: none; }
  /* The script never arms `ct-motion` under reduced motion; this is the
     backstop for a preference that changes after the class is on. */
  html.ct-motion [data-ct-reveal] { opacity: 1; translate: none; transition: none; }
  html.ct-motion [data-ct-px] { transform: none; }
  html.ct-motion .ct-section[data-ct-px]::before { transform: none; }
  .ct-how-plane { animation: none; }
  /* Everything in the hero settles into its finished state: the gauge full,
     the underline drawn, the card landed, the orbits still. */
  .ct-blob, .ct-chips svg, .ct-hero h1 .gradient-text, .ct-cta, .ct-cta::after,
  .ct-orbit, .ct-house, .ct-demo-card, .ct-card-glow,
  .ct-demo-people .mg-avatar, .ct-demo-open::before, .ct-demo .mg-ring,
  .ct-sync, .ct-demo-starter, .ct-demo-bubble, .ct-demo-chev { animation: none; }
  .ct-comet { display: none; }
  .ct-stage { transform: none; transition: none; }
  .ct-cta:hover { transform: none; }
}
