/* Hand-written overrides on top of the Webflow export.
   Linked into every page by scripts/i18n.mjs, so a fresh export does not
   drop it the way edits to the generated stylesheet would be lost. */

/* Button sizing, site-wide.

   The export's CTA is .575rem/1.5rem of padding around 14px copy, which reads
   small against the rest of the type. The hero pair was enlarged on its own a
   while back; every main button matches it now - the section CTAs, the nav
   Contact Us, and the contact form's submit, which is an <input> and so sits
   outside the .button-3 rules. */
.button-3 {
  grid-column-gap: 1rem;
  grid-row-gap: 1rem;
  padding: .9rem 2.25rem;
}

.button-3 .paragraph {
  font-size: 1.125rem;
  line-height: 1.4;
}

.button-3 .button_icon-wrapper {
  width: 1.25rem;
  height: 1.25rem;
}

.button-4 {
  width: auto;
  min-height: 3rem;
  padding: .9rem 2.25rem;
  font-size: 1.125rem;
}

/* Keep them from crowding the viewport on phones. */
@media screen and (max-width: 479px) {
  .button-3 {
    padding: .75rem 1.5rem;
  }

  .button-3 .paragraph {
    font-size: 1rem;
  }

  .button-4 {
    padding: .75rem 1.5rem;
    font-size: 1rem;
  }
}

/* The top-bar links shipped at 16px against an 18px Contact Us label, so
   they read a size down from the button beside them. Match the button. */
.nav-link {
  font-size: 1.125rem;
}

/* The Contact pill shares .nav-right with the burger, and both outer columns
   (.nav-left / .nav-right) are flex: 1, so on narrow screens the pill was
   squeezed until its label wrapped onto two lines and overran the bar.
   It neither shrinks nor wraps now. Below 479px the export hides the pill
   outright, and everywhere above that the full label fits. */
.nav-right .button-3 {
  flex: none;
  white-space: nowrap;
}

/* The stylesheet has --red, --yellow and --black but no blue, while
   .button-2:hover already uses #2a01cc. Name it so the hover states below
   share one definition. */
:root {
  --blue: #2a01cc;
}

/* Button hover states, site-wide.
   The stock rules send each variant to the other's resting look (black turns
   yellow, yellow turns black), so on hover every button reads as its opposite.
   Send them somewhere distinct instead: yellow -> red, black -> blue. */

.button-3._1:hover {
  color: #f2f0eb;
  background-color: var(--red);
  border-color: var(--red);
}

.button-3:not(._1):hover {
  color: #f2f0eb;
  background-color: var(--blue);
  border-color: var(--blue);
}

/* Both hover colours are dark, so any black arrow inside a hovered button
   has to flip to white. Selecting on the asset name covers the outgoing icon
   as well as the one sliding in, and leaves buttons whose arrow is already
   white alone. */
.button-3:hover img[src*="black-arrow"] {
  filter: brightness(0) invert(1);
}

/* The contact form's Submit is .button-4, an <input> rather than an anchor,
   so it sits outside the .button-3 rules above. It is black at rest and the
   stock hover turns it yellow, same as the others. */
.button-4:hover {
  color: #f2f0eb;
  background-color: var(--blue);
  border-color: var(--blue);
}

/* The problem cards keep Webflow's fixed 350px height, which fits the copy
   and keeps all three equal. The hazard is the pairing of that fixed height
   with justify-content: flex-end and visible overflow: content taller than
   the box escapes upward, over the section above, rather than being clipped.
   Italian runs longer than English and hits it first.

   Clipping is the safer failure mode, and changes nothing while the content
   fits. */
/* The compound .black / .red selectors carry their own height at a higher
   specificity, so they have to be listed too or only the plain card resizes. */
.faq_question-card,
.faq_question-card.black,
.faq_question-card-c,
.faq_question-card-c.black,
.faq_question-card-red,
.faq_question-card-red.black,
.faq_question-card-red.red {
  overflow: hidden;
  /* 350px leaves the longest card (Italian, three lines plus a two-line stat)
     15px short, which shoves its graphic up out of alignment with the others.
     380 fits it with a little slack for future copy. */
  height: 380px;
}

/* Pin the graphic to the top of the card and hang the copy off it. The card
   is bottom-anchored on its own, which left each graphic at whatever height
   its text happened to leave it - 29px, 64px and 8px from the top across the
   three cards. Anchoring the graphic but letting the copy sit at the bottom
   only moved the problem: the card with a one-line stat started its title
   20px below the other two. Both are pinned to the top now, so the graphics
   line up and so do the titles; what varies is the space underneath. */
.faq_question-card > .div-block-31,
.faq_question-card-c > .div-block-31,
.faq_question-card-red > .div-block-31 {
  flex: 1 1 auto;
  flex-direction: column;
  justify-content: flex-start;
  display: flex;
}

/* The first line of each card is its title, but .body-large.text-weight-medium
   resolves to 16px/400 - smaller and lighter than the sentence beneath it, so
   it read as a label rather than a heading. */
.faq_question-card .column-large > .body-large,
.faq_question-card-c .column-large > .body-large,
.faq_question-card-red .column-large > .body-large {
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.25;
}

/* Graphic and title at the top, the rest of the copy at the foot of the card.
   The column takes the height the graphic leaves it, and auto margin on the
   line after the title hands all the slack to that one gap - so the titles
   stay level whatever the cards say, and the copy sits on the bottom edge
   rather than trailing off under the title. */
.faq_question-card .column-large,
.faq_question-card-c .column-large,
.faq_question-card-red .column-large {
  flex: 1 1 auto;
}

.faq_question-card .column-large > .body-large + *,
.faq_question-card-c .column-large > .body-large + *,
.faq_question-card-red .column-large > .body-large + * {
  margin-top: auto;
}

/* Hover transition for the problem cards.

   Webflow's interaction swaps the states by writing inline styles with no
   duration, so the graphic vanishes and the copy jumps in one frame. The
   graphic is hidden with display:none, which is a discrete property and
   cannot be transitioned at all.

   So the graphic drives the motion: display:none is overridden - which needs
   !important, since an inline style set from script wins over everything -
   and its height is animated to zero instead.

   The answer panel deliberately does NOT transition its height. It is a flex
   sibling, so it already grows into the space the graphic frees, one frame at
   a time, perfectly in step. Transitioning its height as well makes the
   percentage interpolation fight the flex layout: measured, it crawled to
   37px over a second and then snapped to 184. Only the fade is animated. */

.faq_answer-wrapper,
.faq_answer-wrapper-black,
.faq_answer-wrapper-red {
  /* Webflow tweens this opacity from script over about a second. Leaving that
     in place and adding a CSS transition stacks the two - measured, the copy
     was not fully readable until ~1.5s. Take the property over outright and
     drive it from :hover so it lands with the panel instead. */
  opacity: 0 !important;
  transition: opacity .2s ease .08s;
}

.faq_question-card .image-11,
.faq_question-card-c .image-black,
.faq_question-card-red .image-red {
  display: block !important;
  overflow: hidden;
  transition: height .4s cubic-bezier(.4, 0, .2, 1), opacity .25s ease;
}

/* Only above the breakpoint. Below it the panel is opened by tapping Read More
   and the card keeps its resting look under the pointer - a tablet or a narrow
   desktop window still fires :hover, and without this it collapsed the graphic
   while the panel, which the tap owns, stayed shut. */
@media screen and (min-width: 992px) {
  .faq_question-card:hover .faq_answer-wrapper,
  .faq_question-card-c:hover .faq_answer-wrapper-black,
  .faq_question-card-red:hover .faq_answer-wrapper-red {
    opacity: 1 !important;
  }

  .faq_question-card:hover .image-11,
  .faq_question-card-c:hover .image-black,
  .faq_question-card-red:hover .image-red {
    height: 0 !important;
    opacity: 0;
  }
}

/* The same disclosure on phones and tablets, where there is no hover to drive
   it. The Read More / Read Less links toggle .is-open on the card (see
   js/problem-cards.js), and these rules are the touch half of the hover pair
   above - including the !important, which is there to beat the same
   opacity: 0 !important, not a script this time.

   Scoped to the breakpoint so a card left open before a resize cannot hold
   itself open on the desktop layout, where hover owns the state.

   Below 992px the card is display:block, so the answer panel does not grow
   into the space the graphic frees the way it does in the flex layout - both
   halves animate their own max-height instead. 400px is an overshoot of the
   320px card, near enough that the ease still reads as one motion. */
@media screen and (max-width: 991px) {
  /* The card can outgrow its fixed height once a long answer is open. */
  .faq_question-card.problem-card,
  .faq_question-card-c.black.problem-card,
  .faq_question-card-red.red.problem-card {
    height: auto;
    min-height: 320px;
  }

  .problem-card .div-block-31 {
    max-height: 400px;
    overflow: hidden;
    transition: max-height .4s cubic-bezier(.4, 0, .2, 1), opacity .25s ease;
  }

  .problem-card.is-open .div-block-31 {
    opacity: 0;
    max-height: 0;
  }

  .problem-card .faq_answer-wrapper,
  .problem-card .faq_answer-wrapper-black,
  .problem-card .faq_answer-wrapper-red {
    height: auto;
    max-height: 0;
    transition: max-height .4s cubic-bezier(.4, 0, .2, 1), opacity .2s ease .08s;
  }

  .problem-card.is-open .faq_answer-wrapper,
  .problem-card.is-open .faq_answer-wrapper-black,
  .problem-card.is-open .faq_answer-wrapper-red {
    opacity: 1 !important;
    max-height: 400px;
  }
}

/* A pill inside a card reads as a second call to action competing with the
   section's own. This one only discloses the rest of the card, so it is set as
   a plain underlined link in the card's own colour, keeping the arrow and the
   slide the export's buttons have - the interaction that drove it lived on the
   Webflow button class, so it is restated here in CSS. */
.card-toggle {
  display: none;
}

@media screen and (max-width: 991px) {
  .card-toggle {
    grid-column-gap: .5rem;
    color: #f1eee9;
    cursor: pointer;
    align-self: flex-start;
    align-items: center;
    font-family: Geist, sans-serif;
    font-size: 1rem;
    font-weight: 500;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 4px;
    display: inline-flex;
  }

  .card-toggle .button_icon-1,
  .card-toggle .button-icon-2 {
    transition: transform .4s cubic-bezier(.39, .575, .565, 1);
  }

  .card-toggle .button_icon-1 {
    transform: translate(0%);
  }

  .card-toggle .button-icon-2 {
    transform: translate(-131%);
  }

  .card-toggle:hover .button_icon-1,
  .card-toggle:focus-visible .button_icon-1,
  .card-toggle:active .button_icon-1 {
    transform: translate(131%);
  }

  .card-toggle:hover .button-icon-2,
  .card-toggle:focus-visible .button-icon-2,
  .card-toggle:active .button-icon-2 {
    transform: translate(0%);
  }
}

/* The site is a light-only design, but nothing declared that, so a browser set
   to dark applied its own dark UA defaults. The visible symptom was the Lottie
   embed in the contact section: lottie.host's page leaves html/body
   transparent, and with no declared scheme Chromium painted the iframe's base
   canvas near-black instead of letting the animation composite over the
   section - a black square behind the shapes.

   color-scheme inherits, so declaring it once at the root reaches the iframe
   element and every form control with it. */
:root {
  color-scheme: light;
}

/* Sit the contact animation astride the card's top edge, rather than the third
   of it the Webflow export had peeking over.

   top: -30% measured against the card, so the overlap drifted with however the
   address wrapped. Pinning to the edge and pulling back half the animation's
   own height puts its centre on that edge whatever either one measures. It
   beats the export's 991px override by load order, and below 768px the export
   hides the animation outright. */
.code-embed-4 {
  top: 0;
  transform: translateY(-44%) rotate(180deg);
}

/* Use-case slides alternate yellow and red. The export paints its red ones
   through .green, and its other colour modifiers are mislabelled the same way
   (.yellow and .red both paint #202028), so this names the one in use for what
   it actually does.

   The yellow half is not free to recolour: the pipelines, process automation
   and CRM drawings are inked only in #202028 and red, so they read on a light
   card and nowhere else. */
.header-slide-content.is-red {
  background-color: var(--red);
}

/* The slide copy is all marked .black, but nothing in the export makes that
   class paint anything: .body-medium sets the light brand colour and .black
   never overrides it, so the category line came out light even on yellow.
   Colour the copy from the card instead. */
.header-slide-content .black {
  color: var(--black);
}

.header-slide-content.is-red .black {
  color: var(--brand-color);
}

/* "WHAT YOU CAN BUILD" - the one eyebrow sitting on the dark section. It
   showed for a moment and then vanished.

   .heading-15.small fills its text with a clipped gradient: text-fill-color
   transparent, background-clip text. Compared with the eyebrow above the case
   cards - same class, same gradient, renders fine - the one structural
   difference is that this heading's wrapper is animated as well as the heading
   itself. Webflow leaves transform-style: preserve-3d on both, so the clipped
   text ends up inside a nested 3D rendering context, and Firefox stops
   painting it once the slide settles.

   Flatten both. The slide and the fade are untouched, since those animate
   transform and opacity, not transform-style. */
.header-section .div-block-6,
.header-section .div-block-6 .heading-15 {
  transform-style: flat !important;
}

/* The use-case slider arrows. The export pulls them 24px back over the slide,
   which lands them on the active card - on its copy, not its margin, since the
   active card is drawn larger than its slide and overhangs it by 10px a side.

   Out far enough to clear the card with a little air. There is only a 20px
   gutter between cards, so an arrow cannot be clear of everything: past the
   active card they sit over the dimmed card peeking in behind, which is
   decorative and not being read. */
/* Narrow enough and the card fills the screen edge to edge, so there is no
   outside left to move to. Below 560px the arrows drop into the band under the
   card instead, where they cover nothing - the export left them centred on the
   card and half off screen, and at 393px the left one was past the edge
   entirely with 6px of the right one showing.

   Webflow centres them with inset 0 and margin auto, so restoring that is what
   the wider rule does, with the horizontal pull folded into the same
   shorthand. */
.header-slider-button {
  top: auto;
  bottom: 6px;
  margin: 0;
}

@media screen and (min-width: 560px) {
  .header-slider-button {
    top: 0;
    bottom: 0;
    margin: auto -68px auto 0;
  }

  .header-slider-button.left {
    margin: auto 0 auto -68px;
  }
}

/* ---- Case studies ------------------------------------------------------ */

/* The four case studies are written into the page as the export dialogs.
   They are never shown now - js/case-studies.js reads the copy out of them and
   presents it in the drawer below - but they stay in the markup because the
   Italian dictionary is keyed by the English text inside them. */
.case-modal {
  display: none;
}

/* The detail drawer.

   The header band is the card colour, so the panel arrives as the card you
   clicked. The copy is not: a whole case study set on full-strength blue or
   red is tiring to read, so the body is dark on paper and the card colour
   comes back deepened - --tone - for the section labels and the ✓ marks,
   where it has to hold up against a light background.

   --band-ink is per case rather than one off-white, because red needs pure
   white to clear 4.5:1 and yellow needs the near-black. */
.case-detail {
  --paper: #faf8f5;
  --ink: #202028;
  --band: #202028;
  --band-ink: var(--brand-color);
  --tone: #33333d;
}

.case-detail[data-case="1"] { --band: #00f;     --band-ink: var(--brand-color); --tone: #2a01cc; }
.case-detail[data-case="2"] { --band: #ffde9f;  --band-ink: var(--black);       --tone: #7a5c10; }
.case-detail[data-case="3"] { --band: #e50037;  --band-ink: #fff;               --tone: #b00029; }
.case-detail[data-case="4"] { --band: #202028;  --band-ink: var(--brand-color); --tone: #33333d; }

.case-backdrop {
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  background-color: #20202899;
  transition: opacity .35s ease;
  position: fixed;
  inset: 0;
}

.case-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* visibility rides along with the slide so the panel is not a tab stop while
   it is off screen: it flips to visible as the transform starts and back only
   once it has finished. */
.case-detail {
  z-index: 1001;
  color: var(--ink);
  visibility: hidden;
  background-color: var(--paper);
  flex-direction: column;
  width: min(34rem, 100%);
  transition: transform .45s cubic-bezier(.32, .72, 0, 1), visibility .45s;
  display: flex;
  position: fixed;
  inset: 0 0 0 auto;
  transform: translateX(101%);
  box-shadow: -1.5rem 0 3rem #00000033;
}

.case-detail.is-open {
  visibility: visible;
  transform: none;
}

/* The navbar sits at z-index 999, so the page has to be covered above it. */
html.case-detail-open {
  overflow: hidden;
}

.case-detail__head {
  grid-column-gap: 1rem;
  color: var(--band-ink);
  background-color: var(--band);
  align-items: flex-start;
  padding: 2rem;
  display: flex;
}

.case-detail__mark {
  object-fit: contain;
  flex: none;
  width: 3.25rem;
  height: 3.25rem;
}

.case-detail__heading {
  min-width: 0;
}

.case-detail__title {
  margin: 0 0 .35rem;
  font-family: Geist, sans-serif;
  font-size: 1.35rem;
  font-weight: 500;
  line-height: 1.2;
}

.case-detail__kicker {
  letter-spacing: .08em;
  text-transform: uppercase;
  margin: 0;
  font-size: .7rem;
  font-weight: 500;
}

.case-detail__close {
  color: inherit;
  cursor: pointer;
  background: none;
  border: 0;
  flex: none;
  margin-left: auto;
  padding: .25rem;
  font-size: 1.1rem;
  line-height: 1;
}

.case-detail__body {
  padding: 1.75rem 2rem 3rem;
  overflow-y: auto;
}

/* Challenge / Solution / Results / Timeline, each set as what it is rather
   than as another run of the same paragraph. */
.case-detail__section + .case-detail__section {
  border-top: 1px solid #20202824;
  margin-top: 1.4rem;
  padding-top: 1.4rem;
}

.case-detail__section h3 {
  color: var(--tone);
  letter-spacing: .1em;
  text-transform: uppercase;
  margin: 0 0 .7rem;
  font-family: Geist, sans-serif;
  font-size: .7rem;
  font-weight: 600;
}

.case-detail__prose p {
  margin: 0 0 .7rem;
  font-size: .95rem;
  line-height: 1.6;
}

.case-detail__prose p:last-child {
  margin-bottom: 0;
}

.case-detail__checks {
  grid-row-gap: .6rem;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
}

.case-detail__checks li {
  padding-left: 1.5rem;
  font-size: .9rem;
  line-height: 1.5;
  position: relative;
}

.case-detail__checks li:before {
  content: "✓";
  color: var(--tone);
  position: absolute;
  left: 0;
}

/* "Traditional approach / With Uranion" - the pair is the point, so they sit
   one under the other rather than flung to opposite edges. */
.case-detail__rows {
  grid-row-gap: .9rem;
  flex-direction: column;
  display: flex;
}

.case-detail__row {
  flex-direction: column;
  display: flex;
}

.case-detail__row-key {
  opacity: .65;
  font-size: .8rem;
}

.case-detail__row-val {
  font-size: .95rem;
  font-weight: 500;
}

@media screen and (max-width: 767px) {
  .case-detail {
    width: 100%;
  }

  .case-detail__head,
  .case-detail__body {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .case-detail,
  .case-backdrop {
    transition-duration: .01ms;
  }
}

/* The page behind them: the intro was a sticky column beside a single file of
   cards, which left half the page empty once there were four. Intro across the
   top, cards two up underneath. */
.case-study-section #w-node-_528fe450-1291-cc5c-a7f6-8bd43acc146f-dc012de8 {
  grid-template-columns: 1fr;
}

.case-study-section .content-div.sticky {
  position: static;
  max-width: 44rem;
}

/* An empty 60px section sat between the navbar and the intro, on top of the
   section's own 60px of padding. The navbar is in flow, not fixed, so it was
   never clearing anything. */
.section-13 {
  display: none;
}

/* Same vanishing eyebrow as "WHAT YOU CAN BUILD" above: the wrapper and the
   heading are both animated, so IX2's preserve-3d nests and the clipped
   gradient stops being painted once the slide settles. Same fix. */
.case-study-section .content-div.sticky,
.case-study-section .content-div.sticky .heading-15 {
  transform-style: flat !important;
}

.case-study-section .content-stack-list {
  grid-column-gap: 1.5rem;
  grid-row-gap: 1.5rem;
  grid-template-columns: 1fr 1fr;
  display: grid;
}

/* The cards were one sticky column that stacked on itself as you scrolled.
   Two abreast, the two columns stick at the same offset and ride over each
   other, so they go back to sitting in the grid. */
.case-study-section .content-stack-list .stack-card {
  position: static;
  top: auto;
}

/* .column-large adds 20px on top of the card's own 24px of padding, so the
   logo sat 44px from the top edge and 24px from the left. Even it up. */
.case-study-section .stack-card .column-large {
  padding-top: 0;
}

/* The cards arrive as they are scrolled to, and lift under the cursor. The
   class is added from script only when the visitor has not asked for less
   motion, so with reduced motion the cards are simply there. */
.case-study-section .stack-card {
  transition: opacity .6s ease, transform .4s cubic-bezier(.4, 0, .2, 1),
              box-shadow .3s ease;
}

.case-study-section .stack-card.will-rise {
  opacity: 0;
  transform: translateY(20px);
}

.case-study-section .stack-card.will-rise.has-risen {
  opacity: 1;
  transform: none;
}

.case-study-section .stack-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 1rem 2rem #2020281f;
}

.case-study-section .stack-card .link {
  transition: opacity .2s ease;
}

.case-study-section .stack-card:hover .link {
  opacity: .75;
}

@media screen and (max-width: 767px) {
  .case-study-section .content-stack-list {
    grid-template-columns: 1fr;
  }

  .case-modal .div-block-2 {
    padding: 1.75rem 1.25rem;
  }
}

/* The values mosaic on About. It was six tiles nested three stacks deep, two
   of which - Stateful Architecture and Zero Rebuild Penalty - claimed
   node-level recalculation and an 80-95% saving on iterations, which is the
   old platform pitch rather than what we sell. Both are gone.

   The four that remain are direct children of the section now, so its own two
   columns lay them out 2x2. Equal rows, since the tiles carry no images and
   would otherwise ladder with the length of their copy. */
.section-2 {
  grid-auto-rows: 1fr;
}

.section-2 > .w-layout-cell {
  flex-direction: column;
  justify-content: center;
  min-height: 11rem;
  padding: 2rem 1.75rem;
  display: flex;
}

/* Our Mission was near-black on red: its heading carries no colour class at
   all, and .text-color-white is one of the export's mislabelled classes - it
   paints var(--black). White rather than the warm off-white, which only
   reaches 4.1:1 on this red. */
.section-2 .cell-6 .heading-style-h5-2,
.section-2 .cell-6 .text-size-small-4 {
  color: #fff;
}

/* Real-Time Adaptability carries order: -9999 below 767px, which used to pull
   it to the top of the two-tile stack it was nested in. Flattened into one
   grid that same rule threw it in front of all four, so the phone layout
   opened on it. The tiles stack in the order they are written now.

   By id, because that is how the export writes it and a class selector loses
   to it. */
@media screen and (max-width: 767px) {
  #w-node-_8bfcb0d5-bf4b-e739-146c-e50d2319c0cf-5913f023 {
    order: 0;
  }
}
