/* ============================================================================
   Calenzy — W2 design system
   Used by the rebuilt pages (home, platform, pricing). The remaining pages
   still load the previous template CSS; the two never load together.
   Fonts: Plus Jakarta Sans (headings) + Inter (body), same pair as before.
   ========================================================================= */
:root {
  --navy: #1E2A3B;
  --ink: #3B4456;
  --muted: #66708A;
  --line: #E4E8F0;
  --ground: #FFFFFF;
  --mist: #F6F8FB;
  --jade: #00AF6B;
  --jade-deep: #00814F;
  --grad: linear-gradient(90deg, #002fff, #ab00ff, #ff137d, #ff562f, #ee8502);
  --grad-cta: linear-gradient(135deg, #ff137d, #ee8502);
  --font-alt: "Plus Jakarta Sans", "Inter", -apple-system, sans-serif;
  --font-body: "Inter", -apple-system, "Segoe UI", sans-serif;
  --radius: 14px;
  --dot-tile: 26px;          /* dot grid pitch, shared by the grid and its light */
  --shadow: 0 18px 50px -18px rgba(30, 42, 59, .22);
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16.5px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  /* Full-bleed bands (mock backdrop) reach the viewport edge; never let them
     create a horizontal scrollbar. */
  overflow-x: hidden;
  overflow-x: clip;
}
h1, h2, h3 { font-family: var(--font-alt); color: var(--navy); text-wrap: balance; margin: 0; }
p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; }
.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }

::selection { background: #ffd9e9; }
a:focus-visible, button:focus-visible {
  outline: 3px solid #ab00ff55; outline-offset: 3px; border-radius: 8px;
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-alt); font-weight: 700; font-size: 15.5px;
  padding: 13px 26px; border-radius: 999px; text-decoration: none;
  border: 0; cursor: pointer; transition: transform .15s ease, box-shadow .15s ease;
  white-space: nowrap;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary {
  background: var(--grad-cta); color: #fff;
  box-shadow: 0 10px 26px -10px rgba(255, 19, 125, .55);
}
.btn-primary:hover { box-shadow: 0 14px 30px -10px rgba(255, 19, 125, .6); }
.btn-ghost {
  background: transparent; color: var(--navy);
  box-shadow: inset 0 0 0 2px var(--line);
}
.btn-ghost:hover { box-shadow: inset 0 0 0 2px var(--navy); }
.btn-sm { padding: 9px 20px; font-size: 14.5px; }

/* ---- Header / nav ---- */
.w2-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255, 255, 255, .88); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.nav { display: flex; align-items: center; gap: 28px; height: 72px; }
.nav .logo img { height: 42px; display: block; }
.nav-links { display: flex; gap: 26px; margin-left: 12px; flex: 1; }
.nav-links a {
  text-decoration: none; font-weight: 500; font-size: 15px; color: var(--ink);
  padding: 6px 2px;
}
.nav-links a:hover, .nav-links a.on { color: var(--navy); }
.nav-links a.on { font-weight: 600; }
.lang { display: flex; gap: 2px; border: 1px solid var(--line); border-radius: 999px; padding: 3px; }
.lang a {
  text-decoration: none; font: 600 12.5px var(--font-body);
  color: var(--muted); padding: 5px 10px; border-radius: 999px;
}
.lang a.on { background: var(--navy); color: #fff; }

/* Mobile menu */
.nav-burger {
  display: none; background: none; border: 0; padding: 8px; cursor: pointer;
}
.nav-burger span {
  display: block; width: 22px; height: 2px; background: var(--navy);
  margin: 5px 0; border-radius: 2px;
}
.nav-mobile { display: none; border-top: 1px solid var(--line); padding: 10px 24px 20px; }
.nav-mobile a {
  display: block; text-decoration: none; font: 600 16px var(--font-alt);
  color: var(--navy); padding: 11px 0;
}
.nav-mobile a.btn { display: inline-flex; margin-top: 10px; padding: 10px 22px; color: #fff; }
@media (max-width: 900px) {
  .nav-links, .nav .btn-cta { display: none; }
  /* space-between across three children (logo, language, burger) parked the
     FR/EN pill in the middle of the header, which is not where a language
     switch lives. The logo takes the free space instead, so language and burger
     sit together on the right; the switch stays one tap away, which matters on
     a bilingual site, rather than being buried in the menu. */
  .nav { justify-content: flex-start; gap: 14px; }
  .nav .logo { margin-right: auto; }
  .nav-burger { display: block; margin-right: -8px; }
  .nav-mobile.open { display: block; }
}

/* ---- Hero ---- */
/* padding-block, not the shorthand: .hero is also a .wrap, and `padding: 84px 0 0`
   reset its 24px inline padding to zero. The headline, the sub and the CTA row
   then ran edge to edge on a phone while every other section sat in the column,
   and at 390px the two buttons fitted the unpadded width and centred 13px from
   the screen (Andre, 2026-08-21). Same reason on .page-head and section.block. */
.hero { text-align: center; padding-block: 84px 0; }
.eyebrow-pill {
  display: inline-flex; align-items: center; gap: 8px;
  font: 600 13.5px var(--font-body); letter-spacing: .02em;
  color: var(--jade-deep); background: #E7F7F0; border: 1px solid #C4EBDC;
  padding: 7px 16px; border-radius: 999px; margin-bottom: 28px;
}
.eyebrow-pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--jade); }
.hero h1 {
  font-size: clamp(2.35rem, 5.4vw, 3.7rem); line-height: 1.12;
  font-weight: 800; letter-spacing: -.025em; max-width: 850px; margin: 0 auto;
}
.rot {
  background: var(--grad); background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: gradShift 14s ease-in-out infinite alternate;
  display: inline-block; transition: opacity .3s ease, transform .3s ease;
  /* background-clip: text paints the glyphs only inside the border box, and the
     tight h1 line-height puts descenders (guesthouse) outside it. Grow the
     paint box, cancel the growth in layout. */
  padding: .1em .04em .18em; margin: -.1em -.04em -.18em;
}
.rot.swap { opacity: 0; transform: translateY(8px); }
@keyframes gradShift { from { background-position: 0% 0; } to { background-position: 100% 0; } }
.hero .sub { max-width: 640px; margin: 24px auto 0; font-size: 18.5px; color: var(--muted); }
.hero-ctas { display: flex; gap: 14px; justify-content: center; align-items: center; margin-top: 34px; flex-wrap: wrap; }
.hero .micro { margin-top: 14px; font-size: 13.5px; color: var(--muted); }

/* ---- Dashboard mock ---- */
.mock-stage { margin-top: 64px; position: relative; }
/* The band behind the mock's lower half bleeds to the viewport edge. It used to
   end flat, because the trust strip below carried the same tint and the two met
   with no seam. That strip is gone from the home page and the wellness page
   overrides the section below to white, so a flat end now draws a hard line
   across the page. It fades out instead, and runs past the bottom of the stage
   so the fade has room inside the next section's top padding. Nothing else has
   to change background, which is what made the alternatives awkward: dropping
   the band leaves two white sections in a row. */
.mock-stage::after {
  content: ""; position: absolute; top: 55%; bottom: -110px;
  left: calc(50% - 50vw); right: calc(50% - 50vw);
  background: linear-gradient(180deg, var(--mist) 0%, var(--mist) 58%, transparent 100%);
  z-index: -1;
}
/* Callouts naming what the preview shows. They sit beside the frame, so they
   only appear where there is room for them; the dot points back at the part
   they describe. */
.callout {
  display: none;
  position: absolute; z-index: 2;
  font: 600 13px var(--font-body); color: var(--navy);
  background: #fff; border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 15px; white-space: nowrap;
  box-shadow: 0 8px 22px -14px rgba(30, 42, 59, .5);
}
.callout::after {
  content: ""; position: absolute; top: 50%; width: 7px; height: 7px;
  border-radius: 50%; background: var(--jade); transform: translateY(-50%);
}
/* The frame is 960px wide and centred in the stage, so 480px from the centre
   reaches its edge whatever the viewport. The tops line up with the middle of
   the sidebar, the stats row and the calendar. --callout-gap keeps the pill and
   its dot in step: the pill stands off the frame by the gap, the dot sits in the
   middle of it and reads as the line back to what the label describes. */
.callout { left: 50%; --callout-gap: 34px; }
.callout-one   { top: 219px; transform: translateX(calc(-480px - 100% - var(--callout-gap))); }
.callout-two   { top: 119px; transform: translateX(calc(480px + var(--callout-gap))); }
.callout-three { top: 280px; transform: translateX(calc(480px + var(--callout-gap))); }
.callout-one::after { right: calc(var(--callout-gap) / -2 - 3.5px); }
.callout-two::after, .callout-three::after { left: calc(var(--callout-gap) / -2 - 3.5px); }
@media (min-width: 1180px) { .callout { display: block; } }

/* The pills drift, so they read as labels hovering over the screenshot rather
   than as parts of it. The drift uses `translate`, not `transform`: the
   positioning above already owns `transform`, and the two compose instead of
   overwriting each other. Negative delays start the three out of phase. */
@keyframes calloutFloat {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -7px; }
}
.callout { animation: calloutFloat 5.5s ease-in-out infinite; }
.callout-two   { animation-delay: -1.9s; }
.callout-three { animation-delay: -3.7s; }

.mock {
  max-width: 960px; margin: 0 auto; background: #fff;
  border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow);
  overflow: hidden; text-align: left; font-size: 12.5px;
}
.mock-chrome {
  display: flex; align-items: center; gap: 6px; padding: 11px 16px;
  border-bottom: 1px solid var(--line); background: #FBFCFE;
}
.mock-chrome i { width: 10px; height: 10px; border-radius: 50%; background: var(--line); }
.mock-chrome .url {
  margin-left: 12px; font: 500 11.5px var(--font-body); color: var(--muted);
  background: var(--mist); border-radius: 6px; padding: 3px 12px;
}
.mock-body { display: grid; grid-template-columns: 176px 1fr; min-height: 380px; }
.mock-side { border-right: 1px solid var(--line); padding: 14px 0; background: #FBFCFE; }
.mock-side .item {
  display: flex; align-items: center; gap: 9px; padding: 7.5px 18px;
  color: var(--muted); font-weight: 500;
}
.mock-side .item::before { content: ""; width: 8px; height: 8px; border-radius: 3px; background: var(--line); }
.mock-side .item.on { color: var(--navy); font-weight: 600; background: #EDF6F2; border-right: 2px solid var(--jade); }
.mock-side .item.on::before { background: var(--jade); }
.mock-side .grp {
  padding: 12px 18px 4px; font: 700 9.5px var(--font-body); letter-spacing: .1em;
  color: #9AA3B8; text-transform: uppercase;
}
.mock-main { padding: 18px 22px; }
.mock-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.mock-top .tenant { font: 700 14px var(--font-alt); color: var(--navy); }
.mock-btn {
  background: var(--jade); color: #fff; font: 600 11.5px var(--font-body);
  padding: 6px 14px; border-radius: 7px;
}
.mock-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; }
.stat { border: 1px solid var(--line); border-radius: 10px; padding: 10px 14px; background: #fff; }
.stat b { display: block; font: 700 17px var(--font-alt); color: var(--navy); font-variant-numeric: tabular-nums; }
.stat span { color: var(--muted); font-size: 11px; }
.mock-cal { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: #fff; }
.cal-head { display: grid; grid-template-columns: repeat(5, 1fr); background: #FBFCFE; border-bottom: 1px solid var(--line); }
.cal-head div { padding: 7px 10px; font-weight: 600; color: var(--muted); font-size: 11px; border-left: 1px solid var(--line); }
.cal-head div:first-child { border-left: 0; }
.cal-grid { display: grid; grid-template-columns: repeat(5, 1fr); min-height: 190px; }
.cal-col { border-left: 1px solid var(--line); padding: 8px 7px; display: flex; flex-direction: column; gap: 7px; }
.cal-col:first-child { border-left: 0; }
.evt { border-radius: 7px; padding: 6px 9px; font-size: 10.5px; line-height: 1.35; font-weight: 500; }
.evt b { display: block; font-size: 10.5px; }
.evt.a { background: #EDF6F2; color: #00693F; border-left: 3px solid var(--jade); }
.evt.b { background: #F0EDFB; color: #4A3AA6; border-left: 3px solid #7C64E8; }
.evt.c { background: #FFF0F0; color: #A83A45; border-left: 3px solid #F08791; }
@media (max-width: 760px) {
  .mock-body { grid-template-columns: 1fr; }
  .mock-side { display: none; }
  .cal-head div:nth-child(n+4), .cal-col:nth-child(n+4) { display: none; }
  .cal-head, .cal-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---- Trust strip ---- */
.trust { background: var(--mist); padding: 44px 0 60px; text-align: center; }
.trust .cap { font-size: 13px; color: var(--muted); margin-bottom: 18px; }
.trust .names { display: flex; gap: 22px 54px; justify-content: center; align-items: center; flex-wrap: wrap; }
/* Client logos come in every weight and proportion, so each carries its own
   height (set inline from the copy file) and they share one quiet treatment. */
.trust .names img {
  width: auto; object-fit: contain;
  filter: grayscale(1); opacity: .62;
  /* Some marks are JPGs with a white box baked in; multiply drops that box
     into the tinted band instead of showing it as a white card. */
  mix-blend-mode: multiply;
  transition: filter .25s ease, opacity .25s ease;
}
.trust .names img:hover { filter: none; opacity: 1; }
@media (max-width: 560px) { .trust .names img { max-width: 40vw; } }

/* ---- What we build on -------------------------------------------------------
   Supplier logos, quieter than the client strip above: these say what runs
   underneath, not who trusts us. The marks in images/partners/ are already
   monochrome on transparent, so they only need sizing and a little restraint. */
.built-on { margin-top: 56px; text-align: center; }
.built-on .cap { font-size: 13px; color: var(--muted); margin-bottom: 20px; }
.built-on .marks {
  display: flex; gap: 20px 46px; justify-content: center; align-items: center; flex-wrap: wrap;
}
.built-on .marks img {
  width: auto; object-fit: contain; opacity: .5;
  transition: opacity .25s ease;
}
.built-on .marks img:hover { opacity: .9; }
/* Four 3:1 marks fit three-to-a-row on a phone and leave an orphan, so the row
   becomes a two-column grid instead. */
@media (max-width: 560px) {
  .built-on .marks { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 20px; }
  .built-on .marks img { justify-self: center; }
}

/* ---- Sections ---- */
section.block { padding-block: 96px; }
.eyebrow {
  font: 700 12.5px var(--font-body); letter-spacing: .12em; text-transform: uppercase;
  color: #A05CE8; margin-bottom: 14px;
}
.block h2 { font-size: clamp(1.7rem, 3.4vw, 2.4rem); font-weight: 800; letter-spacing: -.02em; line-height: 1.18; }
.block .lead { max-width: 620px; color: var(--muted); font-size: 17px; margin-top: 16px; }
.center { text-align: center; }
.center .lead { margin-left: auto; margin-right: auto; }

/* Families */
.fam-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 48px; }
@media (max-width: 860px) { .fam-grid { grid-template-columns: 1fr; } }
.fam {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 30px 28px;
  display: flex; flex-direction: column; gap: 12px; background: #fff; text-align: left;
  transition: box-shadow .2s ease, transform .2s ease;
}
.fam:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.fam .tag {
  align-self: flex-start; font: 700 11px var(--font-body); letter-spacing: .09em;
  text-transform: uppercase; padding: 5px 11px; border-radius: 999px;
}
.fam.platform .tag { background: #E7F7F0; color: var(--jade-deep); }
.fam.studio .tag { background: #F0EDFB; color: #5A46C7; }
.fam.cloud .tag { background: #E8F1FE; color: #1D63D8; }
.fam h3 { font-size: 21px; font-weight: 800; }
.fam p { color: var(--muted); font-size: 15.5px; flex: 1; }
.fam a { font: 700 15px var(--font-alt); color: var(--navy); text-decoration: none; }
.fam a:hover { text-decoration: underline; }

/* Modules grid (home) */
.mods { background: var(--mist); }
.mod-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 48px; }
@media (max-width: 860px) { .mod-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .mod-grid { grid-template-columns: 1fr; } }
.mod {
  background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 20px 22px;
  display: flex; gap: 14px; align-items: flex-start; text-align: left;
  text-decoration: none; transition: box-shadow .2s ease;
}
a.mod:hover { box-shadow: var(--shadow); }
.mod-ic {
  width: 42px; height: 42px; border-radius: 12px; flex: none;
  display: grid; place-items: center;
  background: var(--mist); color: var(--navy);
  transition: background .25s ease, color .25s ease, transform .25s ease;
}
.mod-ic svg { width: 21px; height: 21px; }
a.mod:hover .mod-ic { background: var(--grad-cta); color: #fff; transform: scale(1.07) rotate(-3deg); }
.mod b { display: block; font-family: var(--font-alt); font-size: 15.5px; color: var(--navy); }
.mod span { color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.mods .after { text-align: center; margin-top: 40px; }
.mods .after .price { color: var(--muted); font-size: 16px; margin-bottom: 18px; }
.mods .after .price b { font-family: var(--font-alt); font-weight: 800; color: var(--navy); }

/* Fair block */
.fair { background: var(--navy); color: #C6CDDC; }
.fair .eyebrow { color: var(--jade); }
.fair h2 { color: #fff; }
.fair .lead { color: #9AA6BC; }
.fair-table {
  margin-top: 44px; border: 1px solid #33405A; border-radius: var(--radius);
  overflow: hidden; overflow-x: auto;
}
.fair-table table { width: 100%; border-collapse: collapse; min-width: 560px; }
.fair-table td { padding: 17px 22px; border-top: 1px solid #33405A; font-size: 15.5px; vertical-align: top; }
.fair-table tr:first-child td { border-top: 0; }
.fair-table td:first-child { font: 700 16px var(--font-alt); color: #fff; width: 26%; }
.fair-table td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.fair-table tr.us { background: rgba(0, 175, 107, .12); }
.fair-table tr.us td:first-child { color: var(--jade); }
.fair-table tr.us td { color: #DFF5EB; }
.fair .note { font-size: 12.5px; color: #7C89A3; margin-top: 14px; }

/* Humans */
.humans .row { display: grid; grid-template-columns: 1.1fr 1fr; gap: 60px; align-items: center; }
@media (max-width: 860px) { .humans .row { grid-template-columns: 1fr; gap: 36px; } }
.faces { display: flex; align-items: center; }
.face {
  width: 74px; height: 74px; border-radius: 50%; border: 3px solid #fff;
  display: grid; place-items: center; font: 800 24px var(--font-alt); color: #fff;
  margin-left: -14px; box-shadow: 0 6px 18px -8px rgba(30,42,59,.35);
}
.face:first-child { margin-left: 0; }
/* A member with a photo shows it; one without keeps the initial on their colour,
   which is how someone whose picture has not arrived yet still fits the row. */
.face.has-photo { overflow: hidden; background: var(--mist); }
.face img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%; }
.face.f1 { background: #1E2A3B; }
.face.f2 { background: #7C64E8; }
.face.f3 { background: #00AF6B; }
.faces-cap { font-size: 13.5px; color: var(--muted); margin-top: 18px; }
.humans a.more { font: 700 15px var(--font-alt); color: var(--navy); }

/* Our own apps ----------------------------------------------------------------
   Rendered by scripts/w2_apps.php. Same card language as the quotes, and the
   same rule about the column count: a class (a1/a2/a4), never an inline
   grid-template-columns. */
.app-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 44px; text-align: left; }
.app-grid.a1 { grid-template-columns: 1fr; max-width: 640px; margin-left: auto; margin-right: auto; }
@media (max-width: 860px) { .app-grid, .app-grid.a1 { grid-template-columns: 1fr; } }
.app {
  display: flex; gap: 18px; background: #fff;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 24px 26px;
  transition: box-shadow .2s ease, transform .2s ease;
}
.app:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
/* Two of the four icons ship as full squares and two already carry a rounded
   corner, so the radius is applied here and no ring is drawn: a ring would
   trace the CSS corner outside the baked one. */
.app-ic { width: 56px; height: 56px; flex: none; border-radius: 13px; }
.app b { display: block; font: 800 17px var(--font-alt); color: var(--navy); }
.app p { color: var(--muted); font-size: 14.5px; line-height: 1.6; margin-top: 6px; }
/* Taglines differ in length, so the badges are pushed to the foot of the card
   and line up across a row instead of floating at three heights. */
.app > div { display: flex; flex-direction: column; flex: 1; }
.app-stores { display: flex; gap: 10px; margin-top: auto; padding-top: 15px; flex-wrap: wrap; }
.app-stores img { height: 38px; width: auto; display: block; }

/* Client quotes ---------------------------------------------------------------
   Real testimonials from the previous site, rendered by scripts/w2_quotes.php.
   The column count rides on a class (q2/q3/q4) written by that include, never
   on an inline grid-template-columns: an inline value beats the media queries
   below and clips the cards on a phone. */
.quotes { background: var(--mist); }
.quote-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 20px; margin-top: 48px; text-align: left;
}
.quote-grid.q2, .quote-grid.q4 {
  grid-template-columns: repeat(2, 1fr);
  max-width: 900px; margin-left: auto; margin-right: auto;
}
@media (max-width: 860px) {
  .quote-grid, .quote-grid.q2, .quote-grid.q4 { grid-template-columns: 1fr; }
}
.quote {
  margin: 0; background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 24px 26px 22px; display: flex; flex-direction: column; gap: 18px;
  transition: box-shadow .2s ease, transform .2s ease;
}
.quote:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.quote blockquote {
  margin: 0; flex: 1; position: relative; padding-top: 24px;
  color: var(--ink); font-size: 15.5px; line-height: 1.7;
}
.quote blockquote::before {
  content: "\201C"; position: absolute; top: -4px; left: -3px;
  font: 800 52px/1 var(--font-alt); color: #E9E2FA;
}
.quote figcaption {
  display: flex; align-items: center; gap: 12px;
  border-top: 1px solid var(--line); padding-top: 16px;
}
/* Faces and company marks share the circle; the ring stops a mark that is
   mostly white from floating on the card. */
.quote figcaption img {
  width: 46px; height: 46px; flex: none; border-radius: 50%;
  object-fit: cover; background: #fff; box-shadow: 0 0 0 1px var(--line);
}
.quote figcaption > span { line-height: 1.45; }
.quote figcaption b { display: block; font: 700 15px var(--font-alt); color: var(--navy); }
.quote figcaption > span > span { color: var(--muted); font-size: 13px; }

/* Closing */
.closing { background: var(--mist); text-align: center; }
.closing .hero-ctas { margin-top: 30px; }

/* ---- Platform page ---- */
.page-head { text-align: center; padding-block: 76px 20px; }
.page-head h1 { font-size: clamp(2rem, 4.4vw, 3rem); font-weight: 800; letter-spacing: -.02em; max-width: 780px; margin: 0 auto; }
.page-head .lead { max-width: 620px; margin: 18px auto 0; color: var(--muted); font-size: 17.5px; }
.feature-list { display: flex; flex-direction: column; gap: 22px; margin-top: 56px; }
.feature {
  display: grid; grid-template-columns: 56px 1fr auto; gap: 20px; align-items: start;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 28px 30px;
  background: #fff; scroll-margin-top: 96px;
}
.feature .ic {
  width: 56px; height: 56px; border-radius: 14px;
  background: var(--tbg, var(--mist));
  display: grid; place-items: center; color: var(--tfg, var(--navy));
}
.feature .ic svg { width: 26px; height: 26px; }

/* One tint per tool, shared by the home grid tiles, the feature pages, the
   pricing chips and the card watermarks. Same palette family as the
   dashboard's colored chips. */
.mi-booking   { --tbg: #E7F7F0; --tfg: #00814F; background: var(--tbg); color: var(--tfg); }
.mi-stays     { --tbg: #E8F1FE; --tfg: #1D63D8; background: var(--tbg); color: var(--tfg); }
.mi-website   { --tbg: #EDEBFB; --tfg: #5A46C7; background: var(--tbg); color: var(--tfg); }
.mi-menus     { --tbg: #FCF0DF; --tfg: #B26A00; background: var(--tbg); color: var(--tfg); }
.mi-invoicing { --tbg: #FDEBEF; --tfg: #C2334D; background: var(--tbg); color: var(--tfg); }
.mi-clients   { --tbg: #E0F5F3; --tfg: #0F766E; background: var(--tbg); color: var(--tfg); }
.mi-campaigns { --tbg: #E0F2FA; --tfg: #0369A1; background: var(--tbg); color: var(--tfg); }
.mi-analytics { --tbg: #FDEEE4; --tfg: #C2410C; background: var(--tbg); color: var(--tfg); }
.mi-storage   { --tbg: #EEF1F6; --tfg: #475569; background: var(--tbg); color: var(--tfg); }
.mi-code      { --tbg: #EDEBFB; --tfg: #5A46C7; background: var(--tbg); color: var(--tfg); }
.mi-mobile    { --tbg: #E8F1FE; --tfg: #1D63D8; background: var(--tbg); color: var(--tfg); }
.mi-server    { --tbg: #EEF1F6; --tfg: #475569; background: var(--tbg); color: var(--tfg); }
.mi-design    { --tbg: #FDEBEF; --tfg: #C2334D; background: var(--tbg); color: var(--tfg); }
.mi-megaphone { --tbg: #FCF0DF; --tfg: #B26A00; background: var(--tbg); color: var(--tfg); }
.mi-email     { --tbg: #E0F2FA; --tfg: #0369A1; background: var(--tbg); color: var(--tfg); }
.mi-licence   { --tbg: #E7F7F0; --tfg: #00814F; background: var(--tbg); color: var(--tfg); }

/* Watermark: the feature's own icon, large and faint, in its tint color. */
.feature { position: relative; overflow: hidden; }
.feature-ghost {
  position: absolute; right: -14px; bottom: -24px; width: 138px; height: 138px;
  opacity: .16; pointer-events: none; transform: rotate(-8deg);
  background: none !important;
}
.feature-ghost svg { width: 100%; height: 100%; stroke-width: 1.1; }
@media (max-width: 700px) { .feature-ghost { display: none; } }
.feature h3 { font-size: 19px; font-weight: 800; margin-bottom: 6px; }
.feature p { color: var(--muted); font-size: 15.5px; max-width: 62ch; }
.feature .plan-note {
  font: 600 12px var(--font-body); color: var(--jade-deep); background: #E7F7F0;
  border-radius: 999px; padding: 5px 12px; white-space: nowrap;
}
@media (max-width: 700px) {
  .feature { grid-template-columns: 1fr; }
  .feature .plan-note { justify-self: start; }
}

/* ---- Pricing page ---- */
.freq { display: inline-flex; background: var(--mist); border: 1px solid var(--line); border-radius: 999px; padding: 4px; margin-top: 34px; }
.freq button {
  border: 0; background: transparent; cursor: pointer; border-radius: 999px;
  font: 600 14.5px var(--font-body); color: var(--muted); padding: 9px 20px;
  display: inline-flex; align-items: center; gap: 8px;
}
.freq button.on { background: #fff; color: var(--navy); box-shadow: 0 2px 8px -2px rgba(30,42,59,.18); }
.freq .save {
  font: 700 11px var(--font-body); color: #fff; background: var(--jade);
  border-radius: 999px; padding: 3px 9px;
}
.chips { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 40px; align-items: center; }
.chips .lbl { font: 700 12.5px var(--font-body); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-right: 4px; }
.chips.trades { margin-top: 26px; margin-bottom: 8px; }
.chips span:not(.lbl) {
  font: 600 13.5px var(--font-body); color: var(--navy); background: var(--mist);
  border: 1px solid var(--line); border-radius: 999px; padding: 6px 14px;
}
.chips span[class*="mi-"] { background: var(--tbg); color: var(--tfg); border-color: transparent; }
.plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 28px; align-items: stretch; }
@media (max-width: 900px) { .plans { grid-template-columns: 1fr; max-width: 460px; margin-left: auto; margin-right: auto; } }
.plan {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 30px 28px;
  display: flex; flex-direction: column; text-align: left; background: #fff; position: relative;
}
/* The featured card's border drifts through the brand gradient (two-layer
   background-clip; animates background-position only). */
.plan.hero-plan {
  border: 2px solid transparent;
  background:
    linear-gradient(#fff, #fff) padding-box,
    var(--grad) border-box;
  background-size: auto, 300% 100%;
  animation: gradShift 14s ease-in-out infinite alternate;
}
.plan .pop {
  position: absolute; top: -13px; left: 50%; transform: translateX(-50%);
  font: 700 11.5px var(--font-body); letter-spacing: .05em; text-transform: uppercase;
  color: #fff; background: var(--grad); background-size: 300% 100%;
  animation: gradShift 14s ease-in-out infinite alternate;
  border-radius: 999px; padding: 5px 14px; white-space: nowrap;
}
.plan-ic {
  width: 42px; height: 42px; border-radius: 12px; margin-bottom: 14px;
  display: grid; place-items: center;
}
.plan-ic svg { width: 21px; height: 21px; }
.plan-ic.grad { background: var(--grad-cta); color: #fff; }
.plan-ic.mi-essential { background: #E7F7F0; color: #00814F; }
.plan-ic.mi-premium { background: #EDEBFB; color: #5A46C7; }
.plan h3 { font-size: 20px; font-weight: 800; }
.plan .desc { color: var(--muted); font-size: 14.5px; margin-top: 6px; min-height: 44px; }
.plan .price { margin-top: 18px; font-family: var(--font-alt); color: var(--navy); }
.plan .price b { font-size: 34px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.plan .price span { color: var(--muted); font: 500 14px var(--font-body); }
.plan .price .from { display: block; font: 600 12px var(--font-body); color: var(--muted); margin-bottom: 2px; }
.plan ul { list-style: none; margin: 20px 0 26px; padding: 0; flex: 1; }
.plan li {
  position: relative; padding: 6px 0 6px 26px; font-size: 14.5px; color: var(--ink);
}
/* (i) detail on a plan feature -----------------------------------------------
   The trigger is a real <button>, so it takes focus: that is what opens the
   bubble on a touch screen, where :hover never fires. :focus-within keeps it
   open while the finger is down. The bubble is anchored to the <li>, not to the
   icon, so its width is the card's width and it can never push the page wide
   however far along the line the icon sits. */
.plan .tip { display: inline-block; position: static; }
.plan .tip button {
  width: 15px; height: 15px; margin-left: 5px; padding: 0; vertical-align: 1px;
  border: 0; border-radius: 50%; cursor: pointer;
  background: var(--line); color: var(--muted);
  font: 700 10px/15px var(--font-body); text-align: center;
  transition: background .18s ease, color .18s ease;
}
.plan .tip button:hover { background: var(--navy); color: #fff; }
.plan .bubble {
  position: absolute; left: 0; right: 0; top: calc(100% - 2px); z-index: 5;
  background: var(--navy); color: #E8ECF4; border-radius: 10px;
  padding: 10px 13px; font-size: 12.5px; line-height: 1.55; text-align: left;
  box-shadow: 0 14px 34px -12px rgba(30, 42, 59, .5);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.plan li:hover .bubble, .plan li:focus-within .bubble {
  opacity: 1; visibility: visible; transform: none;
}
@media (prefers-reduced-motion: reduce) { .plan .bubble { transition: none; } }

.plan li::before {
  content: ""; position: absolute; left: 0; top: 13px; width: 14px; height: 8px;
  border-left: 2.5px solid var(--jade); border-bottom: 2.5px solid var(--jade);
  transform: rotate(-45deg);
}
.plan .btn { justify-content: center; }
.plans-note { text-align: center; color: var(--muted); font-size: 13.5px; margin-top: 22px; }

/* Studio card on the pricing page */
.studio-card {
  position: relative; overflow: hidden; margin-top: 64px;
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 36px 40px; background: #fff; text-align: left;
  display: flex; align-items: center; gap: 32px;
  box-shadow: 0 12px 36px -22px rgba(30, 42, 59, .25);
}
.studio-card .body { flex: 1; }
.studio-card .tag {
  display: inline-block; font: 700 11px var(--font-body); letter-spacing: .09em;
  text-transform: uppercase; padding: 5px 11px; border-radius: 999px;
  background: #F0EDFB; color: #5A46C7; margin-bottom: 12px;
}
.studio-card h3 { font-size: 21px; font-weight: 800; }
.studio-card p { color: var(--muted); font-size: 15px; margin-top: 8px; max-width: 56ch; }
.studio-card .actions { display: flex; flex-direction: column; align-items: center; gap: 12px; flex: none; }
.studio-card .more { font: 700 14.5px var(--font-alt); color: var(--navy); text-decoration: none; }
.studio-card .more:hover { text-decoration: underline; }
@media (max-width: 760px) {
  .studio-card { flex-direction: column; align-items: flex-start; }
  .studio-card .actions { flex-direction: row; align-items: center; }
}

/* Studio work strip */
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 44px; text-align: left; }
@media (max-width: 860px) { .work-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .work-grid { grid-template-columns: 1fr; } }
.work-card {
  display: block; text-decoration: none; background: #fff;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  transition: box-shadow .2s ease, transform .2s ease;
}
.work-card:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
/* .work-card sets display, which beats the browser's [hidden] rule, so the
   portfolio filter needs this to actually hide a card. */
.work-card[hidden] { display: none; }
.work-card img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; object-position: top; display: block; }
.work-card .cap { display: block; padding: 13px 16px; }
.work-card .cap span {
  display: block; font: 600 11px var(--font-body); letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.work-card .cap b { display: block; font: 700 15px var(--font-alt); color: var(--navy); margin-top: 2px; }

/* Cloud price groups */
.price-groups { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 48px; text-align: left; }
@media (max-width: 900px) { .price-groups { grid-template-columns: 1fr; max-width: 520px; margin-left: auto; margin-right: auto; } }
.pgroup { border: 1px solid var(--line); border-radius: var(--radius); padding: 26px 26px 22px; background: #fff; }
.pgroup .ic {
  width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  background: var(--tbg, var(--mist)); color: var(--tfg, var(--navy)); margin-bottom: 14px;
}
.pgroup .ic svg { width: 21px; height: 21px; }
.pgroup h3 { font-size: 17.5px; font-weight: 800; margin-bottom: 10px; }
.pgroup ul { list-style: none; margin: 0; padding: 0; }
.pgroup li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
  padding: 8.5px 0; border-top: 1px solid var(--line); font-size: 14px; color: var(--muted);
}
.pgroup li b { font-weight: 600; color: var(--navy); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.pgroup .foot { font-size: 12.5px; color: var(--muted); margin-top: 14px; line-height: 1.55; }
.hosting-line { margin-top: 28px; font-size: 14.5px; color: var(--muted); }
.hosting-line a { color: var(--navy); font-weight: 600; }

/* Two-up variant of the module grid. This is a CLASS, not an inline style:
   an inline grid-template-columns beats the media queries below and leaves the
   cards clipped on a phone, which overflow-x: clip then hides. Same mistake was
   made once on the About page. */
.mod-grid.two-up {
  grid-template-columns: repeat(2, 1fr);
  max-width: 900px; margin-left: auto; margin-right: auto;
}
@media (max-width: 700px) { .mod-grid.two-up { grid-template-columns: 1fr; } }

/* ---- Numbered steps (how a retainer works) ----
   The numbering is real here: it is a sequence, first to last. */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 44px; text-align: left; }
@media (max-width: 860px) { .steps { grid-template-columns: 1fr; max-width: 460px; margin-left: auto; margin-right: auto; } }
.step { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 26px 28px; }
.step .num {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  background: var(--navy); color: #fff; font: 800 15px var(--font-alt); margin-bottom: 14px;
}
.step b { display: block; font: 800 17px var(--font-alt); color: var(--navy); margin-bottom: 6px; }
.step .p { color: var(--muted); font-size: 15px; line-height: 1.65; }

/* Plain-spoken limits block */
.honest { max-width: 700px; margin: 0 auto; }
.honest h2 { font-size: clamp(1.4rem, 2.6vw, 1.8rem); margin-bottom: 14px; }
.honest p { color: var(--muted); font-size: 16.5px; line-height: 1.75; }

/* ---- Contact ---- */
.contact-body { padding-top: 46px; padding-bottom: 96px; }
.form-alert { max-width: 880px; margin: 0 auto 28px; border-radius: 12px; padding: 14px 20px; font-size: 15px; }
.form-alert.ok { background: #E7F7F0; color: #00693F; border: 1px solid #C4EBDC; }
.form-alert.bad { background: #FDEBEF; color: #A83A45; border: 1px solid #F5C6D0; }
.contact-grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: 48px; max-width: 880px; margin: 0 auto; }
@media (max-width: 760px) { .contact-grid { grid-template-columns: 1fr; } }
.w2-form label {
  display: block; font: 700 13px var(--font-body); letter-spacing: .04em;
  text-transform: uppercase; color: var(--navy); margin: 18px 0 6px;
}
.w2-form label:first-child { margin-top: 0; }
.w2-form input, .w2-form textarea {
  width: 100%; border: 1px solid var(--line); border-radius: 12px; padding: 12px 16px;
  font: 400 15.5px var(--font-body); color: var(--ink); background: #fff;
}
.w2-form input:focus, .w2-form textarea:focus {
  outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(30, 42, 59, .08);
}
.w2-form textarea { resize: vertical; }
.w2-form .btn { margin-top: 22px; }
.contact-aside h2 { font-size: 17px; font-weight: 800; margin-bottom: 16px; }
.contact-aside p { font-size: 15px; color: var(--muted); margin-bottom: 12px; }
.contact-aside p b {
  display: block; color: var(--navy); font: 700 12px var(--font-body);
  letter-spacing: .06em; text-transform: uppercase; margin-bottom: 2px;
}
.contact-aside a { color: var(--ink); }
.contact-aside .chat-note { margin-top: 18px; font-size: 13.5px; }

/* ---- About ---- */
.stats-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
@media (max-width: 760px) { .stats-strip { grid-template-columns: 1fr 1fr; } }
.stat-big { border: 1px solid var(--line); border-radius: var(--radius); padding: 22px 24px; text-align: center; background: #fff; }
.stat-big b { display: block; font: 800 30px var(--font-alt); color: var(--navy); font-variant-numeric: tabular-nums; }
.stat-big span { font-size: 13.5px; color: var(--muted); }
.team-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 44px; }
@media (max-width: 700px) { .team-grid { grid-template-columns: 1fr; } }
.team-card {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 30px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: #fff;
}
.team-card .face { margin: 0 0 12px; }
.team-card b { font: 800 17px var(--font-alt); color: var(--navy); }
.team-card span { font-size: 13.5px; color: var(--muted); text-align: center; }

/* ---- Comparison pages ---- */
.respect { max-width: 72ch; margin: 0 auto 40px; color: var(--muted); font-size: 16.5px; text-align: center; }
.vs-table { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; overflow-x: auto; background: #fff; }
.vs-table table { width: 100%; border-collapse: collapse; min-width: 560px; }
.vs-table th {
  font: 700 13px var(--font-body); letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); text-align: left; padding: 14px 20px; background: var(--mist);
}
.vs-table th.us { color: var(--jade-deep); }
.vs-table td { padding: 14px 20px; border-top: 1px solid var(--line); font-size: 14.5px; color: var(--muted); vertical-align: top; }
.vs-table td:first-child { font-weight: 600; color: var(--navy); width: 24%; }
.vs-table td.us { color: var(--navy); font-weight: 500; background: rgba(0, 175, 107, .05); }
.vs-note { font-size: 12.5px; color: var(--muted); margin-top: 12px; }
.vs-verdict { grid-template-columns: 1fr 1fr; max-width: 880px; margin-left: auto; margin-right: auto; }
@media (max-width: 760px) { .vs-verdict { grid-template-columns: 1fr; } }

/* ---- Portfolio ---- */
.pf-filters { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-bottom: 36px; }
.pf-filters button {
  border: 1px solid var(--line); background: #fff; border-radius: 999px;
  font: 600 14px var(--font-body); color: var(--muted); padding: 8px 18px; cursor: pointer;
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.pf-filters button:hover { color: var(--navy); border-color: var(--navy); }
.pf-filters button.on { background: var(--navy); border-color: var(--navy); color: #fff; }
.pf-grid { margin-top: 0; }

.pf-back { margin-bottom: 18px; }
.pf-back a { font: 600 14.5px var(--font-alt); color: var(--muted); text-decoration: none; }
.pf-back a:hover { color: var(--navy); }
.pf-meta { display: flex; gap: 14px; justify-content: center; align-items: center; flex-wrap: wrap; margin-top: 16px; font-size: 14.5px; color: var(--muted); }
.pf-meta b { color: var(--navy); font-weight: 600; }
.pf-chip {
  font: 600 12.5px var(--font-body); border-radius: 999px; padding: 5px 13px;
  background: var(--tbg, var(--mist)); color: var(--tfg, var(--navy));
}
.pf-gallery { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin-top: 44px; }
.pf-gallery.single { grid-template-columns: 1fr; max-width: 860px; margin-left: auto; margin-right: auto; }
@media (max-width: 760px) { .pf-gallery { grid-template-columns: 1fr; } }
.pf-gallery img, .pf-gallery video {
  width: 100%; display: block; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--mist);
}
.pf-story { display: grid; grid-template-columns: 1.6fr 1fr; gap: 48px; align-items: start; }
@media (max-width: 860px) { .pf-story { grid-template-columns: 1fr; gap: 32px; } }
.pf-story h2 { font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 800; margin-bottom: 14px; }
.pf-story p { color: var(--muted); font-size: 16px; line-height: 1.75; }
.pf-story p + p, .pf-client p + p { margin-top: 14px; }
.pf-client { border: 1px solid var(--line); border-radius: var(--radius); padding: 26px 28px; background: #fff; }
.pf-client img { max-width: 110px; height: auto; margin-bottom: 16px; }
.pf-client h3 { font-size: 16.5px; font-weight: 800; margin-bottom: 10px; }
.pf-client p { font-size: 14.5px; line-height: 1.7; }

/* ---- Legal prose ----
   The text is legacy HTML (h6 headings, .text-justify paragraphs, lists);
   these rules dress it in the W2 type scale without touching the source. */
.legal-prose { max-width: 76ch; margin: 0 auto; color: var(--ink); font-size: 15.5px; }
.legal-prose h6 {
  font: 800 19px var(--font-alt); color: var(--navy);
  margin: 40px 0 12px; letter-spacing: -.01em;
}
.legal-prose p { margin-bottom: 14px; line-height: 1.7; }
.legal-prose .text-justify { text-align: left; }
.legal-prose ul, .legal-prose ol { padding-left: 22px; margin: 0 0 16px; }
.legal-prose li { margin-bottom: 10px; line-height: 1.65; }
/* The summary items are a bold question plus its answer, so they need more air
   than a one-line bullet. The source used to open each one with a <br>, which
   pushed the text down a line and left the marker stranded above it; spacing is
   the stylesheet's job. Browsers without :has() simply keep the 10px above. */
.legal-prose li:has(> strong:first-child) { margin-bottom: 16px; }
.legal-prose a { color: var(--navy); text-decoration: underline; text-underline-offset: 2px; }
.legal-prose strong, .legal-prose b { color: var(--navy); font-weight: 600; }
.legal-prose address { font-style: normal; color: var(--muted); }
.legal-prose small { color: var(--muted); }
.legal-prose .mb-5 { margin-bottom: 32px; }
/* The legal text still carries utility classes from the retired template.
   The tag rules above already carry the layout; these are the few that had a
   visible job. .ps-0 is deliberately left undefined so the lists keep the
   indent their bullets need. */
.legal-prose .text-muted { color: var(--muted); }
.legal-prose .mt-2 { margin-top: 8px; }
.legal-prose .mt-0 { margin-top: 0; }
.legal-prose .mb-0 { margin-bottom: 0; }
.legal-prose .mb-2 { margin-bottom: 8px; }
.legal-prose .pb-0 { padding-bottom: 0; }

/* Wellness: compare links inside the navy fair block */
.compare-links { margin-top: 22px; font-size: 14.5px; color: #9AA6BC; display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }
.compare-links a { color: #fff; font-weight: 600; }

/* FAQ — one panel rather than a bare list, so it reads as a block of the
   design system like the cards around it. */
.faq {
  max-width: 760px; margin: 48px auto 0; text-align: left;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 4px 28px;
}
.faq details { border-bottom: 1px solid var(--line); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  cursor: pointer; list-style: none; display: flex; justify-content: space-between;
  align-items: center; gap: 18px; padding: 20px 0;
  font: 700 16.5px var(--font-alt); color: var(--navy);
  transition: color .2s ease;
}
.faq summary:hover { color: #000; }
.faq summary::-webkit-details-marker { display: none; }
/* A chevron that turns, rather than a plus that swaps character. */
.faq summary::after {
  content: ""; flex: none; width: 9px; height: 9px; margin-right: 5px;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .25s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.faq details[open] summary { color: var(--navy); }
.faq .a { padding: 0 0 22px; color: var(--muted); font-size: 15.5px; line-height: 1.7; max-width: 66ch; }
.faq-more { text-align: center; margin-top: 24px; font-size: 15px; color: var(--muted); }
.faq-more a { color: var(--navy); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }

/* ---- Footer ---- */
.w2-footer { border-top: 1px solid var(--line); padding: 64px 0 40px; }
.foot-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 28px; }
@media (max-width: 1000px) { .foot-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .foot-grid { grid-template-columns: repeat(2, 1fr); } }
.foot-col b {
  display: block; font: 700 12px var(--font-body); letter-spacing: .1em;
  text-transform: uppercase; color: var(--navy); margin-bottom: 14px;
}
.foot-col a {
  display: block; text-decoration: none; color: var(--muted); font-size: 14.5px; padding: 4.5px 0;
}
.foot-col a:hover { color: var(--navy); }
.foot-base {
  position: relative;
  margin-top: 52px; padding-top: 26px;
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
}
/* The rule above this row bleeds to the viewport edges, so it matches the one
   that opens the footer instead of stopping at the content column. */
.foot-base::before {
  content: ""; position: absolute; top: 0;
  left: calc(50% - 50vw); right: calc(50% - 50vw);
  border-top: 1px solid var(--line);
}
.foot-base span, .foot-base a { font-size: 13px; color: var(--muted); }
.foot-base .spacer { flex: 1; }
.foot-social { display: flex; gap: 14px; align-items: center; }
.foot-social a { display: block; color: var(--muted); transition: color .2s ease; }
.foot-social a:hover { color: var(--navy); }
.foot-social svg { width: 18px; height: 18px; display: block; }

/* ---- Motion ----
   Three layers, all quiet: an entrance sequence on the hero and page heads,
   an ambient brand-gradient glow behind them, and a scroll reveal that
   scripts opt into (w2.js sets data-reveal, so nothing hides without JS). */
@keyframes riseIn {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
.hero > *, .page-head > * { animation: riseIn .65s cubic-bezier(.2, .7, .2, 1) both; }
.hero > *:nth-child(1), .page-head > *:nth-child(1) { animation-delay: .05s; }
.hero > *:nth-child(2), .page-head > *:nth-child(2) { animation-delay: .15s; }
.hero > *:nth-child(3), .page-head > *:nth-child(3) { animation-delay: .25s; }
.hero > *:nth-child(4), .page-head > *:nth-child(4) { animation-delay: .35s; }
.hero > *:nth-child(5), .page-head > *:nth-child(5) { animation-delay: .45s; }
.mock-stage .mock { animation: riseIn .8s .5s cubic-bezier(.2, .7, .2, 1) both; }

/* ---- Hero backdrop ----------------------------------------------------------
   One backdrop element behind the hero and the page heads; the body class picks
   which treatment it wears. Change the default in scripts/w2.php ($w2_bg).
   Every variant is decorative only: z-index -1, no pointer events, and it stops
   moving under prefers-reduced-motion. */
.hero, .page-head { position: relative; }
.hero::before, .page-head::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  top: -60px; left: 50%; transform: translateX(-50%);
  width: min(920px, 94vw); height: 500px;
}

/* 1 · Pools — soft brand-coloured pools, drifting slowly. */
.bg-pools .hero::before, .bg-pools .page-head::before {
  background:
    radial-gradient(closest-side at 28% 42%, rgba(0, 47, 255, .15), transparent 72%),
    radial-gradient(closest-side at 70% 28%, rgba(171, 0, 255, .13), transparent 72%),
    radial-gradient(closest-side at 56% 72%, rgba(255, 19, 125, .11), transparent 72%);
  filter: blur(52px);
  animation: poolDrift 22s ease-in-out infinite alternate;
}
@keyframes poolDrift {
  from { transform: translateX(-52%); }
  to   { transform: translateX(-48%) translateY(14px); }
}

/* 2 · Pools + pointer — the same, with one pool trailing the mouse. */
.bg-pointer .hero::before, .bg-pointer .page-head::before {
  background:
    radial-gradient(42% 40% at var(--gx, 50%) var(--gy, 36%), rgba(171, 0, 255, .16), transparent 70%),
    radial-gradient(closest-side at 28% 42%, rgba(0, 47, 255, .15), transparent 72%),
    radial-gradient(closest-side at 70% 28%, rgba(171, 0, 255, .12), transparent 72%),
    radial-gradient(closest-side at 56% 72%, rgba(255, 19, 125, .11), transparent 72%);
  filter: blur(52px);
  animation: poolDrift 18s ease-in-out infinite alternate;
}

/* 3 · Aurora — two wide ribbons of brand colour, folding slowly. */
.bg-aurora .hero::before, .bg-aurora .page-head::before {
  width: min(1180px, 106vw); height: 560px; top: -110px;
  background:
    linear-gradient(102deg, transparent 12%, rgba(0, 47, 255, .16) 30%, rgba(171, 0, 255, .17) 48%, transparent 66%),
    linear-gradient(74deg, transparent 26%, rgba(255, 19, 125, .13) 48%, rgba(255, 133, 2, .11) 62%, transparent 80%);
  filter: blur(64px);
  animation: auroraFold 26s ease-in-out infinite alternate;
}
@keyframes auroraFold {
  from { transform: translateX(-51%) skewY(-2deg) scaleY(1); }
  to   { transform: translateX(-49%) skewY(2.5deg) scaleY(1.12); }
}

/* 4 · Dot grid — a precise field of dots. The grid never moves and never
   changes colour; the dots around the cursor simply come forward, darker in
   the same navy they rest in. Two layers share one geometry so their dots
   line up exactly: ::before is the resting grid with an edge fade, ::after
   is the same grid at more weight, revealed by a circular mask that w2.js
   parks on the cursor. Because the layers stack, the alphas add up: .20 at
   rest, about .55 under the cursor. */
.bg-dots .hero, .bg-dots .page-head { --dot-bleed: 140px; --dot-rise: 80px; }
.bg-dots .hero::before, .bg-dots .page-head::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  top: calc(-1 * var(--dot-rise));
  /* Bleed into the page's gutters, but never past the viewport. A flat
     -140px assumed there is always a gutter to bleed into; on a phone the
     content column IS the viewport, so it made the document 140px wider than
     the screen. body's overflow-x: clip hid that on desktop, but iOS Safari
     still laid the page out at the wider size and every screen showed the
     content pushed left with a dead strip down the right (Poyen, 2026-08-21).
     calc(50% - 50vw) is exactly the offset that reaches the viewport edge, so
     max() takes whichever bleed is smaller. The dots are masked to a soft
     ellipse well inside these edges, so nothing visible changes on desktop. */
  left: max(calc(-1 * var(--dot-bleed)), calc(50% - 50vw));
  right: max(calc(-1 * var(--dot-bleed)), calc(50% - 50vw));
  width: auto; height: 620px; transform: none;
  background-position: center top;
  background-size: var(--dot-tile) var(--dot-tile);
}
.bg-dots .hero::before, .bg-dots .page-head::before {
  background-image: radial-gradient(circle, rgba(30, 42, 59, .20) 1.1px, transparent 1.1px);
  -webkit-mask-image: radial-gradient(56% 60% at 50% 38%, #000 12%, transparent 72%);
          mask-image: radial-gradient(56% 60% at 50% 38%, #000 12%, transparent 72%);
}
/* The light itself is one fixed layer, so it keeps travelling with the cursor
   the whole way down the page rather than stopping with the hero. It belongs
   to the background: at z-index -1 it paints above the page's ground but
   BEHIND every card, panel and paragraph, so content always occludes it and
   the light is only ever seen in the open. It never takes a click. Its dots
   line up with the hero's resting grid because both are centred on the
   viewport, and w2.js keeps the vertical phase in step through --dot-phase as
   the page scrolls. */
.dot-light {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image: radial-gradient(circle, rgba(30, 42, 59, .22) 1.3px, transparent 1.3px);
  background-size: var(--dot-tile) var(--dot-tile);
  background-position: center var(--dot-phase, 0px);
  -webkit-mask-image: radial-gradient(circle 200px at var(--lx, 50%) var(--ly, -600px),
            #000 0%, rgba(0, 0, 0, .45) 55%, transparent 80%);
          mask-image: radial-gradient(circle 200px at var(--lx, 50%) var(--ly, -600px),
            #000 0%, rgba(0, 0, 0, .45) 55%, transparent 80%);
  opacity: 0; transition: opacity .45s ease;
}
.dot-light.lit { opacity: 1; }
/* Only the dot treatment has a light. */
body:not(.bg-dots) .dot-light { display: none; }

/* 5 · Rings — concentric contour lines spreading from behind the headline. */
.bg-rings .hero::before, .bg-rings .page-head::before {
  width: min(1180px, 104vw); height: 620px; top: -140px;
  background-image: repeating-radial-gradient(circle at 50% 34%,
    rgba(30, 42, 59, .10) 0 1px, transparent 1px 46px);
  -webkit-mask-image: radial-gradient(60% 60% at 50% 34%, #000 20%, transparent 74%);
  mask-image: radial-gradient(60% 60% at 50% 34%, #000 20%, transparent 74%);
  animation: ringBreathe 20s ease-in-out infinite alternate;
}
@keyframes ringBreathe {
  from { transform: translateX(-50%) scale(1); }
  to   { transform: translateX(-50%) scale(1.06); }
}

/* 6 · Wash — a single wide band of brand colour under the headline, no motion. */
.bg-wash .hero::before, .bg-wash .page-head::before {
  width: 100vw; height: 420px; top: -40px;
  background: linear-gradient(180deg,
    rgba(171, 0, 255, .07) 0%, rgba(0, 47, 255, .05) 42%, transparent 100%);
}

/* 7 · Clean — nothing behind the headline; the gradient word carries the colour. */
.bg-clean .hero::before, .bg-clean .page-head::before { display: none; }

[data-reveal] {
  opacity: 0; transform: translateY(22px);
  transition: opacity .6s cubic-bezier(.2, .7, .2, 1), transform .6s cubic-bezier(.2, .7, .2, 1);
}
[data-reveal].in { opacity: 1; transform: none; }

@keyframes evtPop {
  from { opacity: 0; transform: scale(.92) translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.evt { animation: evtPop .45s cubic-bezier(.2, .7, .2, 1) both; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rot, .plan.hero-plan, .plan .pop { animation: none; }
  .hero > *, .page-head > *, .mock-stage .mock, .evt, .callout { animation: none; }
  .hero::before, .page-head::before { animation: none !important; }
  .dot-light { display: none; }
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .btn, .fam, a.mod { transition: none; }
}
