:root{
  --navy:#25225E;
  --navy-deep:#1A1845;
  --blue:#3D6FE0;
  --blue-soft:#EEF3FD;
  --teal:#0E8F8C;
  --ink:#171A2B;
  --body:#555C72;
  --line:#E4E9F2;
  /* the masthead outline: --blue-soft is the palette's light blue but at
     #EEF3FD it disappears as a 1px line on white. This is the same hue
     carried far enough to register without reading as a rule. */
  --line-blue:#CFDCF4;
  --tint:#F5F8FC;
  --white:#fff;
  --radius:14px;
  --gutter:20px;
  --shadow:0 1px 2px rgba(20,25,50,.04), 0 8px 24px rgba(20,25,50,.06);
  --band:linear-gradient(155deg, #EDF3FC 0%, #E8EEEC 52%, #F2EFE9 100%);
  --band-radius:28px;
  --band-inset:16px;
  --band-gap:16px;
  --sec-pad:44px;
}
*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
body{
  margin:0;background:var(--white);color:var(--ink);
  font-family:Inter,system-ui,-apple-system,sans-serif;
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none;}
img{max-width:100%;display:block;}
.wrap{max-width:1160px;margin:0 auto;padding:0 var(--gutter);}

/* ---------- every major section is a rounded panel on the page ---------- */
section, .stats, footer{
  background:var(--band);
  border-radius:var(--band-radius);
  margin:0 var(--band-inset) var(--band-gap);
  overflow:hidden;
}
section:first-of-type{margin-top:var(--band-gap);}
@media(min-width:900px){
  :root{--band-inset:28px;--band-gap:24px;--sec-pad:58px;}
}

/* ---------- vertical rhythm ----------
   One padding value top and bottom on every panel, and one gap between them.
   Before this the hero ran 64/76, the closing CTA 56/56 and the footer 46/30
   while the content sections ran 76/76, so the page had four different
   rhythms in it and the hero and footer were visibly lopsided.

   58px on desktop and 44px on mobile, down from 76 and 56. The gap between
   panels is unchanged at 24 and 16, so the ratio of padding to gap tightens
   but the rhythm stays one value throughout.

   The stats strip is deliberately not in this list. It is a four-number
   measure band, not a content section; its cells carry their own 26px and
   --sec-pad would turn four numbers into 250px of panel. */
.hero, section.band, .cta, footer{padding-top:var(--sec-pad);padding-bottom:var(--sec-pad);}

/* The masthead is sticky, so anchor targets have to clear it. This used to be
   three hard-coded numbers guessed from the header height at three
   breakpoints, which was wrong wherever the header did not match the guess —
   below about 350px the nav row wrapped, the header grew to 189.78px, and a
   fixed 151px dropped the heading behind it.

   nav.js publishes the header's real measured height as --header-h and keeps
   it current on resize, orientation change and whenever the nav panel opens
   or closes. The fallbacks are the desktop values, so with scripting off the
   behaviour is the old one rather than nothing. */
[id]{scroll-margin-top:calc(var(--header-h, 97px) + 24px);}
@media(max-width:959px){[id]{scroll-margin-top:calc(var(--header-h, 137px) + 24px);}}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;gap:8px;
  padding:14px 26px;border-radius:100px;
  font-size:15.5px;font-weight:600;letter-spacing:-.01em;
  border:1.5px solid transparent;transition:transform .12s ease, background .16s ease;
}
.btn:active{transform:translateY(1px);}
.btn-primary{background:var(--navy);color:#fff;}
.btn-primary:hover{background:var(--navy-deep);}
.btn-ghost{background:#fff;color:var(--navy);border-color:var(--line);}
.btn-ghost:hover{border-color:var(--navy);}
.btn-white{background:#fff;color:var(--navy);}

/* ---------- masthead ---------- */
/* Outlined on all four sides rather than underlined. The side and top
   strokes land on the viewport edges, which frames the band as an object
   instead of leaving it as a strip with a rule under it. */
header.top{
  position:sticky;top:0;z-index:50;
  background:rgba(255,255,255,.94);backdrop-filter:blur(10px);
  border:1px solid var(--line-blue);
}
/* Every section below the masthead is a panel inset from the viewport by
   --band-inset, holding a 1160px .wrap with a --gutter inside that. The
   masthead is not inset, so a plain .wrap put the logo --band-inset to the
   left of the heading beneath it at any width below 1160+2*inset, and the
   same distance left of the hero image's right edge.

   The masthead now aligns to the PANEL edge rather than to the content
   inside it. The panels are margin-inset by --band-inset and are otherwise
   full-bleed, so their outer edges sit at x = --band-inset and
   x = viewport - --band-inset at every width. Dropping .wrap's max-width
   and setting the horizontal padding to exactly --band-inset puts the
   masthead's content box on those same two lines.

   Note what this means above 1216px, where the panels are wider than the
   1160px .wrap inside them: the logo no longer lines up with the first
   heading. At 1440 the logo sits at x=28 and the heading at x=160. That is
   the panel edge, which is what was asked for, but it is a different target
   from the one this block used to describe.

   Vertical padding is per-breakpoint and deliberately odd-valued; it was set
   to absorb a 10% logo increase without the band moving. The band is now
   77px up to 700, 87px to 960 and 97px above — 9.5%, 10.7% and 11.9% of an
   812px-tall viewport, against a 20% ceiling. It used to be 126.59px on a
   phone and 189.78px at 320 with the nav row wrapped; the disclosure below
   is what bought that back. Anything added to this row eats into the same
   budget, so measure it.

   This all only holds if img/logo.* is trimmed tight to the artwork. The
   previous logo file carried white padding inside the image, so the box
   aligned to the pixel while the mark visibly sat inset from the heading
   below it. If you swap the logo again, trim it first — no CSS here can
   correct for empty pixels baked into the file. */
.top-in{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  max-width:none;
  /* minus the header's 1px border, which sits inside the band and would
     otherwise push the content box a pixel in from the panel line */
  padding:4.5px calc(var(--band-inset) - 1px);
  flex-wrap:wrap;
}
@media(max-width:699px){.top-in{gap:12px;}}
@media(min-width:700px){.top-in{padding-top:4px;padding-bottom:4px;}}
@media(min-width:960px){.top-in{padding-top:3.5px;padding-bottom:3.5px;}}
.brand{display:flex;align-items:center;gap:11px;}
/* the logo is a <picture>, which is inline by default and would sit on the text
   baseline and add descender space under the mark */
.brand picture{display:flex;}
nav.main{display:flex;gap:28px;font-size:14.5px;font-weight:500;color:var(--body);}
nav.main a:hover{color:var(--navy);}
.top .btn{padding:11px 20px;font-size:14.5px;}

/* No-JS fallback below 960: the links wrap to a row of their own, which is
   what the site did before the disclosure existed. Never hidden outright —
   a seven-page site with no reachable nav is worse than a tall header. */
nav.main{order:3;width:100%;gap:18px;font-size:13.5px;padding:2px 0 10px;overflow-x:auto;}
@media(min-width:960px){nav.main{order:0;width:auto;gap:28px;font-size:14.5px;padding:0;overflow:visible;}}
nav.main a[aria-current="page"]{color:var(--navy);font-weight:600;}

/* ---------- small-screen nav disclosure ----------
   That fallback row cost real height: two rows of links at 320px pushed the
   masthead to 189.78px, 23.4% of an iPhone X viewport, and the links were
   21.6px tall against a 44px touch target. A button and a panel fix both.

   Everything here is gated behind html.js-nav, which nav.js adds. If the
   script does not run, the rules above stand and the links are still there. */
.nav-toggle{
  display:none;
  flex:0 0 auto;width:46px;height:46px;padding:0;
  align-items:center;justify-content:center;
  background:#fff;color:var(--navy);
  border:1.5px solid var(--line);border-radius:12px;
  cursor:pointer;
}
.nav-toggle:hover{border-color:var(--navy);}
.nav-toggle:focus-visible{outline:2px solid var(--blue);outline-offset:2px;}
.nav-toggle svg{width:20px;height:20px;display:block;}
.nav-toggle .ico-close{display:none;}
header.top[data-nav-open] .nav-toggle .ico-open{display:none;}
header.top[data-nav-open] .nav-toggle .ico-close{display:block;}

@media(max-width:959px){
  html.js-nav .nav-toggle{display:inline-flex;margin-left:auto;}
  html.js-nav nav.main{display:none;}
  html.js-nav header.top[data-nav-open] nav.main{
    display:flex;flex-direction:column;order:4;width:100%;
    gap:0;padding:4px 0 8px;margin-top:5px;
    border-top:1px solid var(--line);
    font-size:16px;
    /* The panel is four 48px rows plus, under 400px, the CTA — around 295px.
       On a phone held sideways the viewport is about 375px tall, so the open
       header is most of the screen. Cap it and let it scroll.

       dvh, not vh. On iOS Safari 100vh is the height the viewport would have
       with the address bar retracted, which is taller than what you can
       actually see while it is showing — so a vh cap does not cap anything
       at the moment it matters. dvh tracks the visible height as the bar
       comes and goes. No other rule on this site sets a viewport height. */
    max-height:calc(100dvh - 140px);
    overflow-y:auto;
    overscroll-behavior:contain;
  }
  /* 48px rows: comfortably past the 44px target and tall enough that the
     four destinations do not read as a cramped list */
  html.js-nav header.top[data-nav-open] nav.main a{
    display:flex;align-items:center;min-height:48px;padding:0 2px;
  }
}

/* Aligning to the panel edge instead of the content edge gave the row back
   40px of width, so the threshold where the CTA has to move into the panel
   drops from 400px to 360px. Logo 137 + toggle 46 + CTA 107 + two 12px gaps
   is 314px, against 328px of content box at 360 and 343 at 375. At 320 there
   are only 288px, so there the CTA still moves into the panel and sits full
   width under the links. */
@media(max-width:359px){
  html.js-nav .top-in > .btn{display:none;}
  html.js-nav header.top[data-nav-open] .top-in > .btn{
    display:inline-flex;order:5;width:100%;justify-content:center;margin-top:6px;
  }
}

.logo{height:66px;width:auto;display:block;max-width:100%;}
@media(min-width:700px){.logo{height:77px;}}
@media(min-width:960px){.logo{height:88px;}}
footer .logo{height:66px;margin-bottom:8px;}
/* ---------- content images ----------
   The image files carry their own transparent rounded corners, so the CSS
   must not fight them:

   - contain, never cover, so nothing is cropped at any width;
   - transparent containers, so where contain letterboxes an image the
     section gradient shows through instead of a white panel appearing
     behind the rounded corners;
   - border-radius on the container as well as the file, so a future image
     with square corners still reads right;
   - overflow stays visible. The images are contained, so there is nothing
     to clip, and clipping would impose a second rounding at a different
     radius on top of the one baked into the file.

   Add any new image container to both selector lists. */
.hero-img,.fg-img,.shot,.band-img,.trio-item,.about-img{
  background:transparent;
  border-radius:20px;
  overflow:visible;
}
.hero-img img,.fg-img img,.shot img,.band-img img,.trio-item img,.about-img img{
  width:100%;height:100%;
  object-fit:contain;object-position:center;
  border-radius:20px;
}
/* No aspect-ratio on either photograph container. A fixed box plus contain is
   what produced the wide band of empty gradient beside both women: the hero
   photo is 1:1.89 and was sitting in a 4/5 box, so it was drawn 335px wide
   inside a 507px box at 1440 and 172px of the column was gradient. Letting
   the container take its height from the image means contain has nothing to
   letterbox and the picture fills its column exactly.

   This also stops the two 'How we work' photos fighting over one ratio —
   consultant.webp is 1000x1271 and howwework.webp is 1100x1650, so no single
   aspect-ratio could fit both without letterboxing one of them. */
.hero-img,.fg-img{aspect-ratio:auto;}

/* ---------- hero ---------- */
.hero{background:var(--band);}
.hero-grid{display:grid;gap:32px;align-items:center;}
.eyebrow{
  display:inline-block;background:#fff;border:1px solid var(--line);
  color:var(--teal);font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  padding:7px 14px;border-radius:100px;margin:0 0 18px;
}
h1{
  font-size:clamp(32px,6.4vw,52px);line-height:1.09;letter-spacing:-.032em;
  font-weight:800;margin:0 0 18px;
}
h1 em{font-style:normal;color:var(--blue);}
.hero p.lede{font-size:17.5px;line-height:1.62;color:var(--body);margin:0 0 26px;max-width:46ch;}
.hero-cta{display:flex;gap:12px;flex-wrap:wrap;}
@media(min-width:900px){
  /* 2.1fr/1fr with a 44px gap rather than 1.05fr/.95fr with 52px. The image
     column lands at 347px at 1440, against the 335px the photo was actually
     being drawn at before — so the empty band goes and the woman is the same
     size, not enlarged. Caps at 347px, well inside the 560px the 1000px
     source can carry. Text column is 729px at 1440 and 599px at 1024. */
  .hero-grid{grid-template-columns:2.1fr 1fr;gap:44px;}
}

/* text-only hero for the interior pages */
.hero-solo{max-width:780px;margin:0 auto;text-align:center;}
.hero-solo p.lede{margin-left:auto;margin-right:auto;}
/* on the pages whose hero has no button under it — products, about, privacy,
   terms — the lede's 26px bottom margin was trailing dead space inside the
   panel, on top of the section padding */
.hero-solo p.lede:last-child{margin-bottom:0;}
.hero-solo .hero-cta{justify-content:center;}

/* aspect-ratio utilities */
.r-16x10{aspect-ratio:16/10;} .r-4x3{aspect-ratio:4/3;} .r-3x2{aspect-ratio:3/2;}
.r-1x1{aspect-ratio:1/1;} .r-21x9{aspect-ratio:21/9;} .r-16x9{aspect-ratio:16/9;}

/* ---------- stats band ---------- */
.stats{border-top:0;border-bottom:0;}
.stats-grid{display:grid;grid-template-columns:1fr 1fr;}
.stat{padding:26px 16px;text-align:center;border-right:1px solid var(--line);border-bottom:1px solid var(--line);}
.stat:nth-child(2n){border-right:0;}
.stat b{display:block;font-size:clamp(26px,5vw,36px);font-weight:800;letter-spacing:-.03em;color:var(--navy);line-height:1.1;}
.stat span{display:block;font-size:13px;color:var(--body);margin-top:6px;font-weight:500;}
@media(min-width:820px){
  .stats-grid{grid-template-columns:repeat(4,1fr);}
  .stat{border-bottom:0;}
  .stat:nth-child(2n){border-right:1px solid var(--line);}
  .stat:last-child{border-right:0;}
}

/* ---------- section furniture ---------- */

section.tint{background:var(--band);}
.sec-head{max-width:640px;margin:0 0 34px;}
.sec-head h2{font-size:clamp(25px,4.6vw,36px);line-height:1.15;letter-spacing:-.028em;font-weight:800;margin:0 0 12px;}
.sec-head p{font-size:16.5px;line-height:1.65;color:var(--body);margin:0;}
.center{margin-left:auto;margin-right:auto;text-align:center;}


/* ---------- sector tiles ---------- */
/* Seven sectors, so a four-column grid would leave a hole in the second row.
   Flex with wrap instead: four across then three centred at desktop.

   min-width:0 matters. A flex item's automatic minimum size is its min-content
   width, and 'Manufacturing' set at 15.5px/700 is about 125px — wider than the
   107px of content a half-width card has at 375. That pushed its hypothetical
   size past half the row and broke the last three sectors onto lines of their
   own, full width, while the first four paired up correctly. min-width:0 stops
   one long word from dictating the wrap.

   One card per row below 560 rather than two: at 375 a half-width card leaves
   107px for the text and 'Banking, financial services and insurance' runs to
   four lines in it. */
.tiles{display:flex;flex-wrap:wrap;gap:12px;}
.tile{
  flex:1 1 100%;
  min-width:0;
  background:#fff;border:1px solid var(--line);border-radius:16px;
  padding:20px 18px;transition:border-color .16s ease, transform .16s ease;
}

/* One very low-saturation tint per sector, in the same order on both pages so
   a sector keeps its colour across the site. All seven sit between #EDF6F5
   and #FBF7EE — far enough apart to read as seven, close enough to white to
   read as one family alongside the section gradient. Contrast measured on
   every one: 15.5:1 or better for the title against --ink, 5.99:1 or better
   for the body against --body, versus 17.2:1 and 6.65:1 on plain white. AA
   wants 4.5:1. Borders and radius are untouched. */
.tile:nth-child(1){background:#FBF3F4;}  /* healthcare    — soft pink      */
.tile:nth-child(2){background:#EFF4FC;}  /* BFSI          — soft blue      */
.tile:nth-child(3){background:#EDF6F5;}  /* telecom       — soft turquoise */
.tile:nth-child(4){background:#F4F2FA;}  /* education     — soft purple    */
.tile:nth-child(5){background:#FBF7EE;}  /* retail        — soft amber     */
.tile:nth-child(6){background:#F8F3EE;}  /* manufacturing — soft clay      */
.tile:nth-child(7){background:#F1F6F1;}  /* IT & ITES     — soft green     */
.tile:hover{border-color:var(--blue);transform:translateY(-2px);}
.tile b{display:block;font-size:15.5px;font-weight:700;letter-spacing:-.015em;margin-bottom:5px;}
.tile span{font-size:13.5px;color:var(--body);line-height:1.55;display:block;}
@media(min-width:560px){.tile{flex:1 1 calc(50% - 6px);}}
@media(min-width:760px){.tiles{justify-content:center;} .tile{flex:0 1 calc(25% - 9px);}}

/* ---------- feature rows with ticks ---------- */
.feature-grid{display:grid;gap:34px;align-items:center;}
.ticks{list-style:none;margin:0;padding:0;display:grid;gap:22px;}
.ticks li{display:grid;grid-template-columns:26px 1fr;gap:14px;align-items:start;}
.tick{
  width:24px;height:24px;border-radius:50%;background:var(--blue-soft);
  display:grid;place-items:center;margin-top:2px;
}
.tick svg{width:12px;height:12px;}
.ticks b{display:block;font-size:16.5px;font-weight:700;letter-spacing:-.018em;margin-bottom:5px;}
.ticks p{margin:0;font-size:15px;line-height:1.62;color:var(--body);}
/* 2.2fr/1fr with a 48px gap rather than 1fr/1fr with 60px. Same reasoning as
   the hero: the image column lands at 335px at 1440, against 328px (index)
   and 353px (recruitment) that the photos were drawn at inside a 530px 1:1
   box. Neither is enlarged; the 200px of gradient around them is gone. */
@media(min-width:900px){.feature-grid{grid-template-columns:2.2fr 1fr;gap:48px;}}
@media(min-width:900px){.feature-grid.flip .fg-img{order:-1;}}

/* ---------- product cards ---------- */
.prod{display:grid;gap:20px;}
.prod-main{
  background:#fff;border:1px solid var(--line);border-radius:16px;
  overflow:hidden;box-shadow:var(--shadow);
}
.prod-body{padding:26px 22px 28px;}
.pill{
  display:inline-block;background:#E7F6F4;color:var(--teal);
  font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  padding:5px 12px;border-radius:100px;margin-bottom:14px;
}
.pill.soon{background:#F1F0FA;color:#6B62B8;}
.prod-body h3{font-size:24px;font-weight:800;letter-spacing:-.026em;margin:0 0 10px;}
.prod-body p{font-size:15.5px;line-height:1.65;color:var(--body);margin:0 0 14px;}
.prod-small{display:grid;gap:20px;}
.card{background:#fff;border:1px solid var(--line);border-radius:16px;padding:22px 20px;}
.card h4{font-size:17px;font-weight:700;letter-spacing:-.02em;margin:0 0 8px;}
.card p{font-size:14.5px;line-height:1.6;color:var(--body);margin:0;}
/* the StuckStock disclaimer, moved off the home page questions block.
   Sits under the card rather than inside it — it qualifies the product,
   it is not part of the pitch. */
.prod-note{margin:0 2px;font-size:14.5px;line-height:1.7;color:var(--body);max-width:78ch;}
.lnk{color:var(--blue);font-weight:600;font-size:15px;}
.lnk:hover{text-decoration:underline;}
@media(min-width:900px){.prod-small{grid-template-columns:1fr 1fr;}}

/* ---------- questions ----------
   Four cards, two up. A single column at a readable measure would have left
   the outer thirds of a full-width panel empty, and this section is the same
   width as every other one on the page. Two up fills it, and grid's default
   stretch makes the pair in each row exactly the same height, so there are no
   ragged edges and no holes in the block. */
.qa{display:grid;gap:14px;align-content:start;}

/* Uniform by construction: one padding, one radius, one gap, one type size
   for questions and one for answers. Single column, so every card is the
   same width and the block has flush left and right edges. */
.qa-item{
  background:#fff;border:1px solid var(--line);border-radius:16px;
  padding:24px 22px;
}
.qa-item h3{
  font-size:17.5px;font-weight:700;letter-spacing:-.02em;
  line-height:1.32;color:var(--ink);margin:0 0 9px;
}
.qa-item p{margin:0;font-size:15.5px;line-height:1.7;color:var(--body);}
@media(min-width:820px){.qa{grid-template-columns:1fr 1fr;gap:16px;}}
@media(min-width:900px){
  .qa-item{padding:28px 30px;}
  .qa-item h3{font-size:19px;}
}

/* card grids for the interior pages */
.cards-2,.cards-3{display:grid;gap:20px;}
@media(min-width:820px){.cards-2{grid-template-columns:1fr 1fr;}}
@media(min-width:900px){.cards-3{grid-template-columns:repeat(3,1fr);}}

/* ---------- screenshot gallery ---------- */
.shots{display:grid;gap:10px;padding:14px 14px 0;margin:0;background:transparent;align-items:start;}
.shot{margin:0;min-width:0;}
.shot-cap{margin:8px 2px 0;font-size:12.5px;line-height:1.45;color:#8892AA;}
@media(min-width:820px){
  /* Three auto rows. The two right-hand screenshots size themselves in rows 1
     and 2; the lead spans both and is stretched to fit, so its container is
     exactly row1 + gap + row2 tall. The caption sits in row 3 under the lead,
     outside that span, so it cannot eat into the height being matched.

     The lead image is sized by HEIGHT, not width: height:100% with width:auto
     makes it exactly as tall as its container and as wide as its own ratio
     requires, so top and bottom land on the right-hand column's top and
     bottom with nothing stretched and nothing cropped.

     It has to be positioned absolutely to do that. As a normal in-flow child
     its height:100% would resolve against an indefinite parent during grid
     intrinsic sizing, fall back to the image's natural 810px, and force the
     rows open. Out of flow it cannot contribute to row sizing at all.

     2.1fr/1fr is chosen so the height-driven image is always a little
     narrower than its column rather than a little wider — the exact ratio
     that would make width and height agree drifts from 2.06 at 1440 to 2.09
     at 820, because the 12px gap is a fixed term. Erring wide would overlap
     the right-hand column. */
  .shots{grid-template-columns:2.1fr 1fr;padding:20px 20px 0;gap:12px;}
  .shot-lead{grid-column:1;grid-row:1 / span 2;align-self:stretch;position:relative;}
  .shot-lead img{position:absolute;top:0;left:0;height:100%;width:auto;}
  .shot-cap{grid-column:1;grid-row:3;}
  .shot-a{grid-column:2;grid-row:1;}
  .shot-b{grid-column:2;grid-row:2;}
}

/* ---------- three-image row ----------
   Identical aspect-ratio boxes and 1fr columns, so all three are the same
   width and the same height with one gap value between them. The images are
   contained, so the one that is not 3:2 gets a thin transparent margin at
   the sides rather than being cropped to fit. */
.trio{display:grid;gap:16px;}
.trio-item{aspect-ratio:3/2;}
@media(min-width:820px){.trio{grid-template-columns:repeat(3,1fr);}}

/* ---------- wide image band ---------- */

/* ---------- long-form prose ---------- */
.longform{max-width:68ch;}
.longform p{font-size:17px;line-height:1.75;color:var(--body);margin:0 0 1.4em;}
.longform p:last-child{margin-bottom:0;}
.longform a{color:var(--blue);font-weight:600;}
.longform a:hover{text-decoration:underline;}
.longform h2{
  font-size:clamp(21px,3.4vw,26px);line-height:1.22;letter-spacing:-.024em;
  font-weight:800;color:var(--ink);margin:1.9em 0 .5em;
}
.longform h2:first-child{margin-top:0;}
.longform address{font-style:normal;font-size:17px;line-height:1.8;color:var(--body);}

/* ---------- about page: prose with a floated image ----------
   The old layout put two paragraphs in a grid column beside a tall image
   and dumped the other five full width underneath. The short column left a
   large void beside the image and the two halves read at different widths.

   Now it is one block. At desktop the image floats right out of the first
   paragraph, so the prose starts level with the top of the image, runs down
   its left, and reflows to the block's full width the moment it clears —
   no stranded paragraph, no void, one paragraph rhythm throughout.

   The measure is capped on the paragraphs, not on the block. Capping the
   block leaves the whole right side of the band empty at 1440; capping the
   lines keeps the reading width honest while the block still spans the
   section, so the float can sit against the right edge.

   66ch, not 78ch. ch is the width of a '0', which in Inter is wider than
   the average lowercase glyph, so 78ch renders at about 101 characters —
   well over the 90 the brief asks for. 66ch measures 87. */
.about-body{max-width:none;}
.about-body > p{
  max-width:66ch;
  hyphens:auto;
  -webkit-hyphens:auto;
  text-wrap:pretty;
}
/* Justified only from 900px up. Justification needs enough characters per line
   to distribute the slack invisibly. Beside the 46% float the measure runs
   about 55 characters at 1024 and 66 at 1440, which is comfortable — but only
   40 at 768, where justifying opened visible gaps between words in the opening
   paragraph even with hyphenation on. Below 900 it stays ragged-right.
   hyphens:auto is on at every width regardless: it is what stops the justified
   lines above 900 turning into rivers. */
@media(min-width:900px){.about-body > p{text-align:justify;}}
/* the closing paragraph must sit under the image, not alongside it, however
   the float happens to end */
.about-body > p:last-of-type{clear:right;}
.about-img{margin:0 0 22px;}
@media(max-width:699px){
  /* No float on a phone. Flex order slides the image in behind the opening
     paragraph while leaving it first in the source, which is what lets the
     float above sit level with the top of the text. Centred, so on the wider
     phones where 420px does not fill the column the margin reads as a
     centred portrait rather than as empty space beside it. */
  .about-body{display:flex;flex-direction:column;}
  .about-body > p{order:3;}
  .about-body > p:first-of-type{order:1;}
  .about-img{order:2;max-width:420px;margin-left:auto;margin-right:auto;}
}
@media(min-width:700px){
  /* Floating from 700 rather than 900. At 768 the stacked layout left about
     300px of empty band beside a capped portrait image; floating it puts
     text there instead. */
  .about-img{float:right;width:46%;margin:5px 0 24px 40px;}
}

.btn-lg{padding:17px 30px;font-size:clamp(14px,3.4vw,16.5px);}

/* ---------- closing CTA ---------- */
.cta{background:var(--navy);color:#fff;text-align:center;}
.cta h2{font-size:clamp(25px,4.8vw,38px);line-height:1.15;letter-spacing:-.03em;font-weight:800;margin:0 auto 14px;max-width:20ch;}
.cta p{font-size:16.5px;line-height:1.62;color:#C3C6E4;margin:0 auto 26px;max-width:52ch;}

/* ---------- footer ---------- */

.foot-grid{display:grid;gap:30px;}
.foot-col h5{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ink);margin:0 0 14px;}
.foot-col ul{list-style:none;margin:0;padding:0;display:grid;gap:9px;}
.foot-col a{font-size:14.5px;color:var(--body);}
.foot-col a:hover{color:var(--navy);}
.lnk{display:inline-flex;align-items:center;}

/* ---------- touch targets ----------
   Below the desktop breakpoint every link becomes at least 44px tall. The
   footer columns were the worst of it: 17px-tall inline links stacked 9px
   apart, which is a 17px target with 26px of pitch. The nav is handled by
   the disclosure above, at 48px a row.

   inline-flex rather than padding, so the target grows downward from the
   text box without the link boxes overlapping each other, and the list gap
   drops to 0 because the height now provides the separation.

   Links inside running prose are deliberately exempt. WCAG 2.2 excludes
   targets in a sentence for the obvious reason: you cannot make a word 44px
   tall without wrecking the line box around it. */
/* Width alone was the wrong gate. It covered phones and small tablets but
   left an iPad at 1024 portrait or 1366 landscape — a touch device by any
   measure — with 17px footer links and 23.2px nav links. pointer:coarse
   catches those, and any touch laptop, whatever the viewport width. A mouse
   at 960 or wider keeps the compact footer. */
@media(max-width:959px), (pointer:coarse){
  .foot-col ul{gap:0;}
  .foot-col li > a,
  .foot-bottom a,
  .lnk{
    display:inline-flex;align-items:center;min-height:44px;min-width:44px;
  }
  .foot-addr a{min-height:0;display:inline;}
  nav.main a{display:flex;align-items:center;justify-content:center;min-height:44px;min-width:44px;}
}
.foot-addr{font-size:14.5px;color:var(--body);font-style:normal;line-height:1.75;}
.foot-bottom{
  margin-top:34px;padding-top:20px;border-top:1px solid var(--line);
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  font-size:13.5px;color:#8892AA;
}
@media(min-width:820px){.foot-grid{grid-template-columns:1.4fr 1fr 1fr 1.2fr;gap:40px;}}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
  *,*::before,*::after{transition-duration:.01ms !important;animation-duration:.01ms !important;}
  .tile:hover{transform:none;}
  .btn:active{transform:none;}
}

/* ================================================================
   fear-to-hope.html — the constellation page
   ----------------------------------------------------------------
   A deliberately different room in the same house. It keeps its own
   warmer field (#F6F4EF) and a full-bleed stage rather than the
   site's inset gradient panels, and it is the only page that loads
   constellation.js.

   Everything here is scoped to body.mind, so none of it can reach
   any other page. The only class name that overlaps the site's own
   is .top, and on this page that is the site masthead, which is
   styled below rather than by the mockup's minimal version.
   ================================================================ */
body.mind{
  --field:#F6F4EF;
  --mind-ink:#141413;
  --mind-muted:#737268;
  --clay:#B5764A;
  --hair:#D8D4C9;
  background:var(--field);
  color:var(--mind-ink);
}

/* The site masthead, retinted. White at 94% read as a cold slab against the
   warmer field, so it takes the field's own colour at the same opacity and
   keeps the blur and the soft blue rule. */
body.mind header.top{
  background:color-mix(in srgb, var(--field) 94%, transparent);
  border-color:#DFDACD;
  z-index:60;
}

/* ---------- the stage ---------- */
/* Sticky under the masthead rather than at the viewport top, using the height
   nav.js publishes. The fallback matches the desktop band. */
body.mind .stage{
  position:sticky;
  top:var(--header-h,97px);
  height:calc(100svh - var(--header-h,97px));
  overflow:hidden;display:grid;place-items:center;
}
@supports not (height: 100svh){
  body.mind .stage{height:calc(100vh - var(--header-h,97px));}
}
body.mind .host{height:100vh;}

/* the two words */
body.mind .word{
  position:absolute;
  /* site navy rather than the near-black the mockup used. 13.00:1 against the
     #F6F4EF field — AA large needs 3:1 and AAA normal needs 7:1, so it clears
     both, and it ties the two words to the rest of the site. */
  color:var(--navy);
  font-weight:200;
  /* --wordScale is driven by constellation.js. If the words plus the
     standfirst cannot fit the stage at a given size, the words give way
     rather than the two colliding. 1 unless the fit says otherwise. */
  font-size:calc(clamp(46px,13.5vw,150px) * var(--wordScale,1));
  line-height:.92;
  letter-spacing:-.045em;
  white-space:nowrap;
  will-change:transform;
  user-select:none;
}
body.mind .w-a{transform:translate3d(calc(-50% + var(--ax,0px)), calc(-50% + var(--ay,0px)),0);left:50%;top:50%;margin-top:-.52em;}
body.mind .w-b{transform:translate3d(calc(-50% + var(--bx,0px)), calc(-50% + var(--by,0px)),0);left:50%;top:50%;margin-top:.52em;font-weight:300;}

body.mind .stand{
  /* top is written in pixels by constellation.js, measured from the bottom
     edge of YOU. The old margin-top:6.6em was 6.6 times the STANDFIRST's own
     size, which has nothing to do with how far down the words reach — so it
     put the text behind YOU from 768px up, by 51px at 1440. The percentage
     here is only what shows before the first measurement lands. */
  position:absolute;left:50%;top:var(--standTop,68%);
  transform:translate(-50%, var(--standShift,0px));
  width:min(38ch,84vw);text-align:center;
  font-size:14.5px;line-height:1.7;color:var(--mind-muted);
  opacity:var(--standOp,1);pointer-events:none;
}

body.mind .hint{
  position:absolute;left:50%;bottom:34px;transform:translateX(-50%);
  font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--mind-muted);
  opacity:var(--hintOp,1);display:flex;flex-direction:column;align-items:center;gap:9px;
  pointer-events:none;
}
body.mind .hint i{display:block;width:1px;height:26px;background:var(--hair);animation:mind-bob 1.6s ease-in-out infinite;}
@keyframes mind-bob{0%,100%{transform:translateY(-3px);opacity:.5;}50%{transform:translateY(4px);opacity:1;}}

/* ---------- constellation ---------- */
body.mind .canvas{
  position:absolute;inset:0;
  filter:blur(var(--canvasBlur,0px));
  transition:filter .28s ease;
}
body.mind .lines{position:absolute;inset:0;width:100%;height:100%;overflow:visible;}
body.mind .lines line{
  stroke-width:1;
  stroke-dasharray:1;stroke-dashoffset:1;
  vector-effect:non-scaling-stroke;
  opacity:0;
}
body.mind .node{
  position:absolute;
  transform:translate(-50%,-50%) scale(var(--s,1));
  background:none;border:0;padding:0;margin:0;cursor:pointer;
  font:inherit;color:inherit;text-align:left;
  opacity:0;will-change:transform,opacity;
  /* the dot is 11px but the target must not be. The label carries most of the
     height; min-width holds the narrow ones ("Is it costly?") above 44px. */
  min-width:44px;min-height:44px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
}
body.mind .node .dot{
  width:11px;height:11px;border-radius:50%;
  background:var(--c);margin:0 auto 9px;
  box-shadow:0 0 0 5px color-mix(in srgb, var(--c) 16%, transparent);
}
body.mind .node .lab{
  display:block;width:max-content;max-width:150px;
  font-size:12.5px;line-height:1.42;font-weight:500;color:var(--mind-ink);
  text-align:center;
}
body.mind .node .idx{
  display:block;font-size:9.5px;letter-spacing:.18em;color:var(--mind-muted);
  margin-bottom:3px;font-weight:600;
}
@media(max-width:560px){
  /* the box narrows and the label wraps to more lines; the 12.5px type is
     untouched, which is the constraint that matters */
  body.mind .node .lab{max-width:124px;}
}
body.mind .node:hover{--s:1.14;}
body.mind .node:focus-visible{outline:2px solid var(--mind-ink);outline-offset:8px;border-radius:6px;}
body.mind .speck{
  position:absolute;width:3px;height:3px;border-radius:50%;
  transform:translate(-50%,-50%);opacity:0;
}

/* ---------- answer sheet ---------- */
body.mind .sheet{
  position:fixed;inset:0;z-index:70;
  display:grid;place-items:center;padding:24px;
  background:color-mix(in srgb, var(--field) 62%, transparent);
  opacity:0;pointer-events:none;transition:opacity .26s ease;
}
body.mind .sheet[hidden]{display:none;}
body.mind .sheet.on{opacity:1;pointer-events:auto;}
body.mind .sheet-in{
  background:#fff;border:1px solid var(--hair);border-radius:18px;
  width:min(660px,100%);max-height:82vh;overflow:auto;
  padding:38px 34px 32px;position:relative;
  transform:translateY(10px);transition:transform .26s cubic-bezier(.19,1,.22,1);
  box-shadow:0 30px 70px rgba(20,20,19,.13);
}
body.mind .sheet.on .sheet-in{transform:none;}
body.mind .sheet-idx{font-size:10px;letter-spacing:.2em;font-weight:600;margin:0 0 14px;}
body.mind .sheet h2{font-size:clamp(23px,4vw,31px);line-height:1.18;letter-spacing:-.026em;font-weight:600;margin:0 0 18px;}
body.mind .sheet p{font-size:16px;line-height:1.72;color:#3F3E3A;margin:0 0 15px;}
body.mind .wrong{
  margin:22px 0 0;padding-top:16px;border-top:1px solid var(--hair);
  font-size:14.5px;line-height:1.65;color:var(--mind-muted);
}
body.mind .wrong > span:first-child{
  display:block;font-size:10px;letter-spacing:.18em;text-transform:uppercase;
  font-weight:700;color:var(--mind-ink);margin-bottom:7px;
}
body.mind .x{
  position:absolute;top:14px;right:14px;width:44px;height:44px;
  border:1px solid var(--hair);border-radius:50%;background:#fff;
  cursor:pointer;font-size:15px;line-height:1;color:var(--mind-muted);
}
body.mind .x:hover{color:var(--mind-ink);border-color:var(--mind-ink);}
body.mind .x:focus-visible{outline:2px solid var(--mind-ink);outline-offset:3px;}

/* ---------- after the sequence ---------- */
body.mind .after{padding:16vh 28px 12vh;text-align:center;background:var(--field);}
body.mind .after h2{
  font-weight:200;font-size:clamp(34px,7.5vw,74px);line-height:1;
  letter-spacing:-.045em;margin:0 0 22px;
}
body.mind .after p{font-size:15.5px;line-height:1.72;color:var(--mind-muted);margin:0 auto;max-width:44ch;}
body.mind .after a.back{
  display:inline-block;margin-top:30px;font-size:14px;font-weight:500;
  border-bottom:1px solid var(--hair);padding-bottom:2px;min-height:44px;
}
body.mind .after a.back:hover{border-bottom-color:var(--mind-ink);}

/* ---------- fallback ---------- */
body.mind .fallback{max-width:760px;margin:0 auto;padding:14vh 28px 10vh;}
body.mind .fallback h1{font-weight:200;font-size:clamp(40px,9vw,86px);line-height:.98;letter-spacing:-.045em;margin:0 0 20px;}
body.mind .fb-stand{font-size:16.5px;line-height:1.7;color:var(--mind-muted);max-width:46ch;margin:0 0 40px;}
body.mind .fb-q{padding:30px 0;border-top:1px solid var(--hair);}
body.mind .fb-idx{font-size:10px;letter-spacing:.2em;font-weight:600;margin:0 0 12px;}
body.mind .fb-q h2{font-size:22px;line-height:1.25;letter-spacing:-.02em;margin:0 0 12px;}
body.mind .fb-q p{font-size:16px;line-height:1.72;color:#3F3E3A;margin:0 0 13px;}
body.mind .fb-wrong{
  margin-top:18px;padding-top:14px;border-top:1px solid var(--hair);
  font-size:14.5px;line-height:1.65;color:var(--mind-muted);
}
body.mind .fb-wrong span{
  display:block;font-size:10px;letter-spacing:.18em;text-transform:uppercase;
  font-weight:700;color:var(--mind-ink);margin-bottom:7px;
}

/* The interactive stage only exists once constellation.js has said so. Default
   is the fallback, which is why no-JS and reduced-motion need no special case. */
body.mind .host, body.mind .after{display:none;}
body.mind.js .fallback{display:none;}
body.mind.js .host{display:block;}
body.mind.js .after{display:block;}
@media (prefers-reduced-motion:reduce){
  body.mind.js .fallback{display:block;}
  body.mind.js .host, body.mind.js .after{display:none;}
}

/* footer sits on the field rather than the site gradient, so the page ends in
   one colour */
body.mind footer{background:var(--field);border-top:1px solid var(--hair);}
