/* ============================================================
   Scroll cards — the shared block treatment for blend-technologies.com
   ------------------------------------------------------------
   Two shapes, one idea: a full-bleed block that closes into a rounded
   card, and a rounded card that opens to full bleed. Both are driven by
   a --sc-p that scroll-cards.js writes on the element itself, so a page
   can carry as many as it likes, and both are clip-path only — nothing
   here animates a property that would make the browser lay the page out
   again, and nothing inside either shape is scaled, moved or reflowed.

   Lifted out of the homepage's inline stylesheet unchanged so
   /how-it-works can use the same component. The values, the easing and
   the geometry are the homepage's; only the selectors are new.
   ============================================================ */
:root{
  --sc-inset:40px;--sc-round:36px;
}
/* Smaller margins and a tighter corner on a phone: 40px either side of a
   375px screen is a fifth of the width, and the card stops reading as a
   full-bleed block that has pulled in. */
@media (max-width:560px){
  :root{--sc-inset:24px;--sc-round:24px}
}
/* Defaults are the state each shape should hold with no JS at all, and
   the state reduced motion keeps: the hero already a card, every reveal
   already open. The handler never writes under reduced motion, so an
   inline value can never beat this. */
/* The component carries the tokens it needs. A page that does not define
   --sand or --muted-on-dark used to get white for both, because an
   undefined var() falls back to inheritance - which is how the use-cases
   closing band ended up with a white eyebrow and a white lead. */
:root{--hero-beige:#F4EFE5;--sand:#E7CFA3;--muted-on-dark:rgba(255,255,255,.72)}
.sc-hero{--sc-p:0}
.sc-reveal{--sc-p:0}
@media (prefers-reduced-motion:reduce){
  .sc-hero{--sc-p:1}
  .sc-reveal{--sc-p:1}
}

/* ---- The hero: full bleed at 0, a card at 1 --------------------------
   The hairline is two clips. The block's own background is the edge
   colour and the fill sits a pixel inside it, so the ring appears in the
   gap between them; both are scaled by --sc-p, which is what makes it
   fade in with the inset rather than drawing a line round the viewport
   at rest.

   There is no shadow, and that is not an oversight: clip-path clips an
   element's own box shadow away with its edge, so a real one would mean
   animating inset and border-radius on an unclipped box - the
   layout-triggering animation this whole thing exists to avoid. */
/* Height is a token because the homepage means something different by it.
   A full viewport is right there — the hero holds the product preview and
   fills it, 616px of content in 832px of hero. On /how-it-works and
   /use-cases the same rule gave 379px of content in the same 832px: 453px
   of nothing, with the next section starting one pixel below the fold.
   Flagged in the 2026-10-17 review as "almost an entire desktop screen on
   a heading, a description and buttons".

   So the default is shorter and the homepage opts back in. Both floors are
   still generous enough that the card has room to form. */
:root{--sc-hero-min:calc(72vh - var(--nav-h))}
@supports (height:100svh){ :root{--sc-hero-min:calc(72svh - var(--nav-h))} }
.sc-hero{position:relative;display:grid;align-content:safe center;overflow:hidden;
  min-height:var(--sc-hero-min);
  padding:40px 0 56px;
  background:transparent;
  clip-path:inset(
    calc(var(--sc-p) * var(--sc-inset)) calc(var(--sc-p) * var(--sc-inset))
    calc(var(--sc-p) * var(--sc-inset)) calc(var(--sc-p) * var(--sc-inset))
    round calc(var(--sc-p) * var(--sc-round)));}
/* The fill, a pixel inside the hairline. Deeper than --cream on purpose:
   against a white page #FAF8F2 was close enough that the card barely read
   as a separate surface. One token, because the nav has to match it
   exactly while the page is at the top. */
.sc-hero::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;background:var(--hero-tint,var(--hero-beige));
  clip-path:inset(
    calc(var(--sc-p) * (var(--sc-inset) + 1px)) calc(var(--sc-p) * (var(--sc-inset) + 1px))
    calc(var(--sc-p) * (var(--sc-inset) + 1px)) calc(var(--sc-p) * (var(--sc-inset) + 1px))
    round calc(var(--sc-p) * (var(--sc-round) - 1px)))}
/* The block's own height carries the space the padding used to. */
@media (max-width:960px){ .sc-hero{padding:32px 0 56px} }
@media (max-width:760px){ .sc-hero{padding:24px 0 48px} }
@media (max-width:560px){ .sc-hero{align-content:start;padding-top:34px} }
/* The content used to scale with the card: 6% over at rest, settling to
   its design size as the card formed, so the block and its contents moved
   as one thing. It cost more than it bought. A scaled layer rasterises
   its glyphs and resamples them, so every hero's type rendered 6% larger
   than its own spec and visibly softer than the identical component on a
   page with no hero card - a 12px eyebrow on /science reading at 12.7px
   and half a weight light beside the same 12px eyebrow on /use-cases.
   Reported as "not using the right font", which is what it looks like.
   The frame closes around fixed content now, and the type is the type. */
.sc-hero > .wrap{position:relative;z-index:1}

/* ---- A reveal: a card at 0, full bleed at 1 -------------------------
   The ink is a layer inside the block rather than the block's own
   background, because clipping the block would reveal the page behind
   it, and what belongs either side of a reveal is the ground it sits on.
   The block keeps that ground; the layer carries the ink. */
.sc-reveal{position:relative;overflow:hidden}
.sc-reveal::before{content:"";position:absolute;inset:0;z-index:0;background:var(--deep);
  clip-path:inset(
    calc((1 - var(--sc-p)) * var(--sc-inset)) calc((1 - var(--sc-p)) * var(--sc-inset))
    calc((1 - var(--sc-p)) * var(--sc-inset)) calc((1 - var(--sc-p)) * var(--sc-inset))
    round calc((1 - var(--sc-p)) * var(--sc-round)))}
.sc-reveal > .wrap{position:relative;z-index:1}
/* A pair that reads as one card: the upper half insets its top and sides
   and rounds only its top corners, the lower half insets its sides and
   bottom and rounds only its bottom corners, and neither insets the edge
   they share. Two clipped layers, one continuous shape. */
.sc-reveal--top::before{
  clip-path:inset(
    calc((1 - var(--sc-p)) * var(--sc-inset))
    calc((1 - var(--sc-p)) * var(--sc-inset))
    0
    calc((1 - var(--sc-p)) * var(--sc-inset))
    round calc((1 - var(--sc-p)) * var(--sc-round))
          calc((1 - var(--sc-p)) * var(--sc-round)) 0 0)}
/* The pair meets on a fractional pixel, and that showed as a pale hairline
   across the full width between the CTA and the footer. Not a border and not
   a gap — both measured zero. Two separately-composited layers whose shared
   edge lands mid-pixel (a closer ending at y=465.55) each anti-alias against
   whatever is behind them, and behind them is the page's light ground, so the
   two halves do not add back up to solid ink.

   One pixel of overlap removes the shared edge as a compositing boundary. It
   cannot be done by extending either ::before, because .sc-reveal carries
   overflow:hidden and clips its own layer back to the box; pulling the lower
   half up by a pixel works from outside that. Two identical inks overlapping
   by 1px is invisible in the card state as well as the full-bleed one. */
.sc-reveal--top{margin-bottom:-1px}

.sc-reveal--bottom::before{
  clip-path:inset(
    0
    calc((1 - var(--sc-p)) * var(--sc-inset))
    calc((1 - var(--sc-p)) * var(--sc-inset))
    calc((1 - var(--sc-p)) * var(--sc-inset))
    round 0 0 calc((1 - var(--sc-p)) * var(--sc-round))
              calc((1 - var(--sc-p)) * var(--sc-round)))}

/* ---- Clipped blocks need a gutter wider than their own inset --------
   The page gutter is 32px and the cards inset by 40, so wherever .wrap is
   not centred by its max-width the content crosses the card's edge and
   the first and last few pixels of every line sit on the ground outside
   it. On a reveal that is white text on beige, so they simply disappear.

   Static, not scaled by progress: padding is layout, and the card is at
   its deepest inset at rest, which is the case that has to fit. Above the
   width where the wrap's own centring already clears the card the gutter
   is left alone, so the desktop composition keeps its full width.

   The hero keeps a wider one further up than the reveals do. That began
   as headroom for the content scale, which is gone; it stays because the
   hero's inset is the deepest on the site and its first line is the one
   that must not graze the card's corner. */
@media (max-width:1263px){
  .sc-reveal > .wrap{padding-inline:calc(var(--sc-inset) + 20px)}
}
@media (max-width:1299px){
  .sc-hero > .wrap{padding-inline:calc(var(--sc-inset) + 24px)}
}
@media (max-width:560px){
  .sc-hero > .wrap{padding-inline:calc(var(--sc-inset) + 16px)}
  .sc-reveal > .wrap{padding-inline:calc(var(--sc-inset) + 12px)}
}

/* ---- What sits on a dark reveal ---------------------------------------
   The reveal paints a near-black card behind a section that is otherwise
   cream, so everything inside it has to switch colour with it. These were
   written inline on the homepage; they are here so a second page using the
   component gets them too. The homepage's own copies are declared after
   this file and carry identical values, so nothing moves there.

   Scoped to .sc-reveal, not to .closer, because it is the dark card that
   makes the text white - a .closer without one would be unreadable. */
.sc-reveal{position:relative;overflow:hidden;color:var(--white)}
.sc-reveal > .wrap{position:relative;z-index:1}
.sc-reveal .h1,
.sc-reveal .h2{color:var(--white)}
.sc-reveal .lead{color:var(--muted-on-dark)}
.sc-reveal .eyebrow{color:var(--sand)}
.sc-reveal .btn-ghost{color:var(--white);border-color:rgba(255,255,255,.34);background:transparent}
.sc-reveal .btn-ghost:hover{border-color:var(--white);background:rgba(255,255,255,.08)}

/* ---- The scroll cue --------------------------------------------------
   A target at the bottom of a hero, for the readers who do not know the
   page continues. It fades on the same progression as the card it sits
   in, so it is gone by the time the hero has closed a sixth of the way
   and back when the page returns to the top. */
.sc-cue{position:absolute;left:50%;transform:translateX(-50%);z-index:2;
  bottom:calc(32px + env(safe-area-inset-bottom, 0px));
  width:44px;height:44px;display:grid;place-items:center;border-radius:50%;
  background:transparent;border:1px solid rgba(107,107,107,.4);color:var(--muted);
  cursor:pointer;-webkit-appearance:none;appearance:none;padding:0;
  opacity:clamp(0, calc((.15 - var(--sc-p, 0)) * 6.6667), 1);
  transition:border-color .18s ease,opacity .12s linear}
.sc-cue:hover{border-color:var(--muted)}
.sc-cue:focus-visible{outline:2px solid var(--gold-active);outline-offset:3px}
/* Out of the tab order and out of reach once it has faded, rather than an
   invisible button sitting over the page. */
.sc-hero.is-cue-gone .sc-cue{visibility:hidden}
.sc-cue svg{width:16px;height:16px;display:block;animation:sc-cue-drift 2s ease-in-out infinite}
/* The ring: one expansion every 2.5s, behind the border it starts from. */
.sc-cue::after{content:"";position:absolute;inset:-1px;border-radius:50%;
  border:1px solid rgba(107,107,107,.4);animation:sc-cue-ring 2.5s ease-out infinite;
  pointer-events:none}
@keyframes sc-cue-drift{0%,100%{transform:translateY(0)}50%{transform:translateY(4px)}}
@keyframes sc-cue-ring{
  0%{transform:scale(1);opacity:.5}
  70%{transform:scale(1.45);opacity:0}
  100%{transform:scale(1.45);opacity:0}
}
/* Only where the hero is two columns with the cards beside the copy.
   Below 1200 they stack under it, the block runs taller than the viewport,
   and a circle 32px above its bottom edge lands on the cards instead of
   under them. Same breakpoint as the hero grid itself. */
/* The homepage hero puts its cards to the right of the type, and below
   1200 they stack under it and the cue lands on top of them. The centred
   heroes have nothing there, so they keep theirs at every width. */
@media (max-width:1199px){.sc-cue--desktop{display:none}}
@media (prefers-reduced-motion:reduce){
  .sc-cue{opacity:1}
  .sc-cue svg{animation:none}
  .sc-cue::after{display:none}
}
