/* Tech Fly launch stylesheet.
   Responsive repairs for theme widgets that only had a desktop layout, plus the cookie
   banner and the hidden trap field of the forms. Loaded after the child style.css. */

/* ------------------------------------------------------------------ homepage project table, phones
   The theme scatters the cards at 25vw with random rotation and makes each one draggable.
   Below 768px that left eleven 97px slivers piled on the first screen, and on an upright
   tablet dragging cards fights with scrolling the page. On both, the same cards become one
   swipeable row; launch.js switches the dragging off there. */
@media (max-width: 767px), (max-width: 1024px) and (orientation: portrait) {
  /* the table's container is a full-height stage on desktop; on phones it wraps the row,
     with room underneath for the "View All" button the theme pins to its bottom edge */
  .e-con:has(> .elementor-widget-peshowcasetable),
  .e-con:has(> .e-con-inner > .elementor-widget-peshowcasetable) {
    min-height: 0 !important;
    padding-bottom: 84px !important;
  }
  /* "Drag & Arrange the projects." is not true on a phone, and it sat under the button */
  .e-con:has(> .elementor-widget-peshowcasetable) > .elementor-widget-petextwrapper,
  .e-con:has(> .e-con-inner > .elementor-widget-peshowcasetable) > .e-con-inner > .elementor-widget-petextwrapper {
    display: none !important;
  }
  .showcase-table {
    height: auto !important;
    overflow: visible !important;
  }
  .showcase-table .st-wrapper {
    display: flex;
    gap: 0;
    padding: 12px 17vw 30px;   /* side room, so the first and the last card can sit in the middle */
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .showcase-table .st-wrapper::-webkit-scrollbar { display: none; }
  .showcase-table .showcase-project {
    position: relative !important;
    top: auto !important;
    left: auto !important;
    flex: 0 0 66vw;
    width: 66vw !important;
    height: min(56vh, 102vw) !important;
    margin: 0 !important;
    padding: 12px !important;
    rotate: none !important;
    scroll-snap-align: center;
    touch-action: pan-x pan-y !important;
    cursor: auto !important;
    user-select: auto !important;
  }
  .showcase-table .showcase-project .project-image {
    flex: 1 1 auto;
    min-height: 0;
  }
  .showcase-table .showcase-project .project-meta {
    flex: 0 0 auto;
    align-items: center;
  }
  .showcase-table .showcase-project .meta-content { min-width: 0; }
  .showcase-table .showcase-project .project-title,
  .showcase-table .showcase-project .project-category {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .showcase-table .showcase-project .project-category { opacity: 0.68; }
}

/* The deck: the card in the middle faces you, its neighbours turn away, tuck in behind it and dim,
   like cards fanned on a table. Driven by the scroll position itself, so it follows the finger
   exactly. Browsers without scroll-driven animation, and visitors who asked for less motion,
   get the same row, flat. */
@media (max-width: 767px), (max-width: 1024px) and (orientation: portrait) {
  @supports not (animation-timeline: view()) {
    .showcase-table .showcase-project { transform: none !important; }
  }
  @media (prefers-reduced-motion: reduce) {
    .showcase-table .showcase-project { transform: none !important; }
  }
  @supports (animation-timeline: view()) {
    /* less motion asked for: nothing turns or slides, the neighbours only dim */
    @media (prefers-reduced-motion: reduce) {
      .showcase-table .showcase-project {
        animation: tf-deck-calm linear both;
        animation-timeline: view(inline);
      }
    }
    @media (prefers-reduced-motion: no-preference) {
      .showcase-table .st-wrapper { perspective: 1200px; }
      .showcase-table .showcase-project {
        animation: tf-deck linear both;
        animation-timeline: view(inline);
        transform-origin: center 62%;
        will-change: transform;
      }
    }
  }
}
@keyframes tf-deck-calm {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}
@keyframes tf-deck {
  0%   { transform: translateX(-20%) translateY(18px) rotateY(-30deg) rotateZ(3deg) scale(0.8); opacity: 0.5; z-index: 1; }
  50%  { transform: translateX(0%) translateY(0px) rotateY(0deg) rotateZ(0deg) scale(1); opacity: 1; z-index: 3; }
  100% { transform: translateX(20%) translateY(18px) rotateY(30deg) rotateZ(-3deg) scale(0.8); opacity: 0.5; z-index: 1; }
}

/* an upright tablet shows one card whole and most of the two beside it */
@media (min-width: 768px) and (max-width: 1024px) and (orientation: portrait) {
  .showcase-table .st-wrapper { padding: 14px 28vw 34px; }
  .showcase-table .showcase-project {
    flex: 0 0 44vw;
    width: 44vw !important;
    height: min(46vh, 60vw) !important;
    padding: 14px !important;
  }
}

/* ------------------------------------------------------------------ project videos fill their frames
   The theme sizes a project's video once, in pixels, when the page starts, and centres it.
   The homepage cards change size after that (launch.js, and every rotation of a phone), so the
   video is told to fill its frame by itself: on the cards, in the Work grid and at the top of a
   case study. The Remote terminal sits at the left of its recording, so its crop starts there
   instead of in the middle, where there is only dark screen. */
:is(.showcase-table .showcase-project, .portfolio--projects--wrapper .project--image, .project-featured-image) .pe-video.pe-self {
  width: 100%;
  height: 100%;   /* in the Work grid the frame's height used to come from the video's pixel size */
}
:is(.showcase-table .showcase-project, .portfolio--projects--wrapper .project--image, .project-featured-image) .pe-video.pe-self :is(.plyr, .plyr__video-wrapper) {
  width: 100% !important;
  height: 100% !important;
  transform: none !important;
}
:is(.showcase-table .showcase-project, .portfolio--projects--wrapper .project--image, .project-featured-image) .pe-video.pe-self video {
  display: block;
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
}
/* the still shown while a video loads is framed like the video itself */
:is(.showcase-table .showcase-project, .portfolio--projects--wrapper .project--image, .project-featured-image) .plyr__poster {
  background-size: cover;
  background-color: transparent;
}
:is(.project__image__12323, .featured__12323) video { object-position: 10.5% 100%; }
:is(.project__image__12323, .featured__12323) .plyr__poster { background-position: 10.5% 100%; }
/* An embedded player keeps the shape of its film, so in a taller frame it left a band of empty
   card under it. The player is centred and may not be smaller than the frame in either
   direction; its own aspect-ratio (set by the player) then makes it cover the frame. */
:is(.showcase-table .showcase-project, .portfolio--grid .project--image) .pe-video.pe-vimeo {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
:is(.showcase-table .showcase-project, .portfolio--grid .project--image) .pe-video.pe-vimeo .plyr {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  min-width: 0;
}
:is(.showcase-table .showcase-project, .portfolio--grid .project--image) .pe-video.pe-vimeo .plyr__video-wrapper {
  position: absolute !important;
  top: 50%;
  left: 50%;
  width: auto !important;
  height: auto !important;
  min-width: 100%;
  min-height: 100%;
  max-width: none;
  transform: translate(-50%, -50%) !important;
}
/* in a landscape frame there is room to come closer to the terminal window */
.showcase-table .showcase-project.tf-wide .project__image__12323 video,
.showcase-table .showcase-project.tf-wide .project__image__12323 .plyr__poster {
  transform: scale(1.3);
  transform-origin: 28% 100%;
}

/* ------------------------------------------------------------------ Work grid: every tile is a square
   Asked by Eni on 8 October: pictures and videos in the same square frame. The theme gave the
   grid rows a height (75vh) and let the frame take what the caption left, so a tile's shape
   depended on the screen, and a video's on its own pixels. The frame now has its own shape and
   the picture or the video is pinned to its four edges, at every width. */
.portfolio--grid div.portfolio--projects--wrapper {
  grid-auto-rows: auto !important;
}
.portfolio--grid .portfolio--project,
.portfolio--grid .portfolio--project > article,
.portfolio--grid .portfolio--project > article > a {
  height: auto !important;
}
.portfolio--grid .portfolio--project > article {
  display: block;
}
.portfolio--grid .portfolio--project .project--image {
  position: relative;
  flex: 0 0 auto;
  width: 100%;
  height: auto !important;
  aspect-ratio: 1 / 1;
}
.portfolio--grid .portfolio--project .project--image > img,
.portfolio--grid .portfolio--project .project--image > .pe-video {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
}
/* A picture with plain ground along its top and bottom edges is shown whole, and the square
   continues those two edges above and below it (launch.js reads them and supplies them).
   Anything else, a photograph for instance, fills the square. */
.portfolio--grid .portfolio--project .project--image.tf-whole {
  background:
    var(--tf-edge-top) top / 100% 51% no-repeat,
    var(--tf-edge-bottom) bottom / 100% 51% no-repeat;
}
.portfolio--grid .portfolio--project .project--image.tf-whole > img {
  object-fit: contain;
}
/* Nari Lunder's film is a wide strip of devices: the square shows the phone and the tablet,
   not the gap between the browser and the phone */
.portfolio--grid .project__image__12201 video { object-position: 70% 50%; }

/* ------------------------------------------------------------------ Work grid, phones and tablets
   The grid kept two columns at every width, with the title and the categories squeezed side
   by side under each tile and cut off. One column on phones, and the caption stacked. */
@media (max-width: 767px) {
  .portfolio--grid div.portfolio--projects--wrapper {
    grid-template-columns: minmax(0, 1fr) !important;
    row-gap: 34px !important;
  }
  .portfolio--projects--wrapper .project--tc {
    flex-direction: column !important;
    justify-content: flex-start !important;
    align-items: flex-start;
    gap: 2px;
  }
  .portfolio--projects--wrapper .project--tc .project--cat {
    font-size: 15px;
    line-height: 1.35;
    opacity: 0.66;
  }
}
@media (min-width: 768px) and (max-width: 1024px) {
  .portfolio--projects--wrapper .project--tc {
    flex-direction: column !important;
    justify-content: flex-start !important;
    align-items: flex-start;
    gap: 2px;
  }
  .portfolio--projects--wrapper .project--tc .project--cat {
    font-size: 16px;
    opacity: 0.66;
  }
}

/* ------------------------------------------------------------------ forms: the trap field
   Present for scripts, absent for people and for assistive technology (see inc/forms.php). */
.tf-form-trap {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ------------------------------------------------------------------ cookie banner
   A small card in the site's own vocabulary: the theme's two grounds, one hairline,
   pill buttons of equal weight. Colours follow the theme's light and dark switch. */
.tf-consent {
  position: fixed;
  z-index: 99990;
  left: 16px;
  bottom: 16px;
  width: min(420px, calc(100vw - 32px));
  padding: 18px 18px 16px;
  border: 1px solid color-mix(in srgb, var(--mainColor, #070707) 16%, transparent);
  border-radius: 22px;
  background: var(--mainBackground, #f0f0f0);
  color: var(--mainColor, #070707);
  font-size: 15px;
  line-height: 1.45;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.24s cubic-bezier(0.23, 1, 0.32, 1), transform 0.24s cubic-bezier(0.23, 1, 0.32, 1);
}
.tf-consent[hidden] { display: none; }
.tf-consent.is-open {
  opacity: 1;
  transform: none;
}
.tf-consent__text { margin: 0 0 14px; }
.tf-consent__text a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.tf-consent__actions {
  display: flex;
  gap: 8px;
}
.tf-consent__btn {
  flex: 1 1 0;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--mainColor, #070707);
  border-radius: 999px;
  background: transparent;
  color: var(--mainColor, #070707);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
.tf-consent__btn--yes {
  background: var(--mainColor, #070707);
  color: var(--mainBackground, #f0f0f0);
}
.tf-consent__btn:focus-visible,
.tf-consent__text a:focus-visible,
.tf-consent-open:focus-visible {
  outline: 2px solid var(--mainColor, #070707);
  outline-offset: 3px;
}
@media (hover: hover) and (pointer: fine) {
  .tf-consent__btn { transition: opacity 0.16s ease; }
  .tf-consent__btn:hover { opacity: 0.78; }
}
@media (max-width: 480px) {
  .tf-consent {
    left: 10px;
    bottom: 10px;
    width: calc(100vw - 20px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .tf-consent {
    transform: none;
    transition: opacity 0.2s ease;
  }
}

/* ------------------------------------------------------------------ case studies: "Visit Website"
   On the three oldest case studies the button is pinned to the bottom-right corner of the
   intro column and sat on the last line of text at every width. The column now leaves room. */
body.single-portfolio .e-con:has(> .elementor-widget-pebutton.elementor-absolute),
body.single-portfolio .e-con:has(> .e-con-inner > .elementor-widget-pebutton.elementor-absolute) {
  padding-bottom: 64px !important;
}

/* ------------------------------------------------------------------ 404 page
   The theme's 404 scatters a dozen absolutely placed words across a 1371px stage, so the
   page scrolled sideways on tablets and shrank to a thumbnail on phones. The words go
   (07-404.php replaces them with a plain message); nothing may widen the page. */
body.error404 .elementor-widget-petextwrapper.elementor-absolute {
  display: none !important;
}
body.error404 .elementor-location-single,
body.error404 .elementor-8864,
body.error404 main {
  max-width: 100vw;
  overflow-x: clip;
}

/* ------------------------------------------------------------------ case studies: whole mockups
   Five case studies gave every board a fixed height, and the widget then cover-crops the
   image to fit: at tablet width only a quarter to a half of each mockup was visible, and
   rows of phones lost their outer devices even on a desktop. A board is the work itself,
   so it is shown whole, at its own proportions, at every width. (Nari Lunder already was.) */
body.single-portfolio .elementor-widget-pesingleimage .single--image:not(.zoomed--image) {
  height: auto !important;
}
body.single-portfolio .elementor-widget-pesingleimage .single--image:not(.zoomed--image) img {
  height: auto !important;
  object-fit: contain !important;
}

/* ------------------------------------------------------------------ case studies: the hero image
   The hero is a 90vh box at every width. On a phone or an upright tablet that box is
   taller than it is wide, so a landscape mockup lost half of itself. Below 1025px the
   box takes the image's own 16:10 shape. Video heroes keep the full-height stage. */
@media (max-width: 1024px) {
  body.single-portfolio .project-featured-image.p--featured:not(:has(video)):not(:has(iframe)) {
    height: auto !important;
    aspect-ratio: 16 / 10;
  }
}


/* ================================================================== design pass, 8 October
   Asked for by Eni: liquid-glass cards and menu, corners as sharp as the logo's, forms in the
   coming-soon page's style. Everything hangs off the tokens below, so the whole site can be
   tuned from five lines. */
:root {
  --tf-r-card: 10px;   /* cards, panels, large images */
  --tf-r-media: 8px;   /* pictures and videos inside a card */
  --tf-r-ctl: 6px;     /* buttons, fields, small controls */
  --tf-glass-bg: rgba(228, 228, 228, 0.40);
  --tf-glass-rim: rgba(255, 255, 255, 0.78);
  --tf-glass-edge: rgba(7, 7, 7, 0.07);
  --tf-glass-shadow: 0 24px 46px -24px rgba(7, 7, 7, 0.30);
}
body.layout--switched {
  --tf-glass-bg: rgba(255, 255, 255, 0.07);
  --tf-glass-rim: rgba(255, 255, 255, 0.22);
  --tf-glass-edge: rgba(255, 255, 255, 0.07);
  --tf-glass-shadow: 0 24px 46px -24px rgba(0, 0, 0, 0.75);
}

/* ------------------------------------------------------------------ corners
   Circles stay circles (icons, the play button, the round text badge). */
.showcase-table .showcase-project,
.pe-testimonial,
.single-image,
.single-image img,
.single--image--wrapper,
.project-featured-image,
.project-featured-image img,
.portfolio--projects--wrapper .project--image {
  border-radius: var(--tf-r-card) !important;
}
.showcase-table .showcase-project .project-image,
.showcase-project .pe-video,
.pe-video,
.pe-client {
  border-radius: var(--tf-r-media) !important;
}
.pe--button--wrapper a,
.pb--marquee,
.pl--switch,
.pe--form .wpcf7-form-control:not([type="checkbox"]):not([type="radio"]),
.wpcf7 input.wpcf7-submit,
.portfolio--switcher,
.portfolio--switcher span,
.filters--button,
.pe--styled--popup,
.tf-consent__btn {
  border-radius: var(--tf-r-ctl) !important;
}
.tf-consent { border-radius: var(--tf-r-card); }

/* corners set inside the page builder, or by widgets the first pass missed (found by a sweep of
   all 22 pages, 8 October): brought to the same three sizes */
.elementor-element-804f5ba,   /* the next-project teaser under every case study */
.elementor-element-4a9e06f,   /* the film card on Home */
.elementor-element-3b99d2c,   /* the opening picture on Contact */
.elementor-element-508cca6,   /* "What happens next" on Contact */
.single-image.zoomed--image > div,
.pe-slide,
.pe-slide .slide-image,
.filter--cat--list {
  border-radius: var(--tf-r-card) !important;
}
.elementor-widget-pevideo > .elementor-widget-container,
.inner--image {
  border-radius: var(--tf-r-media) !important;
}
.filter--active,
.filter--cat,
.pe--switcher,
.ps--follower,
.ps--item,
body.single-portfolio .elementor-widget-peprojectfield > .elementor-widget-container {
  border-radius: var(--tf-r-ctl) !important;
}

/* ------------------------------------------------------------------ liquid glass
   Translucent, blurred, lit along the top edge. Used where something floats over
   something else: the project cards, the menu at the top of a page, the cookie banner. */
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .showcase-table .showcase-project,
  .tf-consent {
    background: var(--tf-glass-bg) !important;
    -webkit-backdrop-filter: blur(22px) saturate(175%);
    backdrop-filter: blur(22px) saturate(175%);
    border: 0 !important;
    box-shadow:
      inset 0 0 0 1px var(--tf-glass-edge),
      inset 0 1px 0 0 var(--tf-glass-rim),
      inset 1px 0 0 0 color-mix(in srgb, var(--tf-glass-rim) 35%, transparent),
      var(--tf-glass-shadow);
  }

  /* the menu: glass while the page is at the top, plain once it scrolls */
  @media (min-width: 1025px) {
    .site-header:not(.header--move) .elementor-widget-penavmenu.wd--show--on--top .main-navigation {
      margin: -11px -20px;
      padding: 11px 20px;
      border-radius: var(--tf-r-card);
      background: var(--tf-glass-bg);
      -webkit-backdrop-filter: blur(22px) saturate(175%);
      backdrop-filter: blur(22px) saturate(175%);
      box-shadow:
        inset 0 0 0 1px var(--tf-glass-edge),
        inset 0 1px 0 0 var(--tf-glass-rim),
        0 14px 30px -18px rgba(7, 7, 7, 0.22);
    }
    .site-header:not(.header--move) .wd--show--on--top .pe--button--wrapper a {
      background: var(--tf-glass-bg) !important;
      -webkit-backdrop-filter: blur(22px) saturate(175%);
      backdrop-filter: blur(22px) saturate(175%);
      box-shadow: inset 0 0 0 1px var(--tf-glass-edge), inset 0 1px 0 0 var(--tf-glass-rim);
    }
  }
}

/* ------------------------------------------------------------------ project table, tablet and desktop
   The stage is 100vh tall but starts 100px down the page (the section's top padding), so its
   last 100px sat below the first screen and the cards were centred on the wrong middle.
   The stage now ends where the screen ends; launch.js lays the cards out to fill it. */
@media (min-width: 1025px), (min-width: 768px) and (orientation: landscape) {
  .showcase-table {
    height: calc(100vh - 100px) !important;
    min-height: 420px;
  }
  /* signed in, the admin bar takes the top 32px of the screen */
  body.admin-bar .showcase-table { height: calc(100vh - 132px) !important; }
}
/* launch.js deals the cards into columns and gives each its width and height, so a column of
   two or three cards is exactly as tall as the stage. Captions keep to one line each. */
@media (min-width: 1025px), (min-width: 768px) and (orientation: landscape) {
  .showcase-table .showcase-project {
    width: var(--tf-card-w, 21.6vw) !important;
    height: var(--tf-card-h, 40vh) !important;
    padding: 12px !important;
  }
  .showcase-table .showcase-project .project-image {
    flex: 1 1 auto;
    min-height: 0;
  }
  .showcase-table .showcase-project .project-meta {
    flex: 0 0 auto;
    align-items: center;
    margin-top: 12px;
    padding-left: 6px;
  }
  .showcase-table .showcase-project .meta-content {
    flex: 1 1 auto;
    min-width: 0;
  }
  .showcase-table .showcase-project .project-title,
  .showcase-table .showcase-project .project-category {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .showcase-table .showcase-project .project-title {
    font-size: clamp(15px, calc(var(--tf-card-w, 300px) * 0.062), 19px);
    line-height: 1.3;
  }
  .showcase-table .showcase-project .project-category {
    font-size: clamp(12px, calc(var(--tf-card-w, 300px) * 0.047), 14px);
    line-height: 1.4;
    opacity: 0.68;
  }
  .showcase-table .showcase-project .project-icon i {
    font-size: 22px;
    padding: 6px;
  }
}

/* ------------------------------------------------------------------ forms, in the coming-soon page's style
   One panel on the theme's second ground, fields drawn with a single ink line, a solid ink
   button, errors in words under the field. Applies to every Contact Form 7 form on the site. */
.pe--form {
  padding: clamp(20px, 2.4vw, 36px);
  border-radius: var(--tf-r-card);
  background: var(--secondaryBackground, #dcdcdc);
}
.pe--form,
.pe--form .wpcf7,
.pe--form form.wpcf7-form {
  height: auto !important;   /* the theme gives the form a fixed height; the panel has to wrap what is in it */
  max-height: none !important;
}
.pe--form .wpcf7,
.pe--form form.wpcf7-form {
  margin: 0 !important;
  transform: none !important;
}
.pe--form form.wpcf7-form {
  display: grid !important;   /* the theme lays the form out as a flex row */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px !important;   /* the theme's gap is a percentage, which a grid of unknown height cannot size */
  align-items: start;
}
.pe--form form.wpcf7-form > br,
.pe--form form.wpcf7-form > p:empty { display: none; }   /* line breaks the form editor leaves between fields */
.pe--form form.wpcf7-form > p,
.pe--form .form--field p { margin: 0; }
.pe--form form.wpcf7-form > p { display: flow-root; }
.pe--form input.wpcf7-submit { float: none !important; position: static !important; }
.pe--form .form--field label br { display: none; }
.pe--form .form--field { float: none !important; margin: 0 !important; padding: 0 !important; width: auto !important; max-width: none !important; min-width: 0; }
.pe--form .form--field.field-100,
.pe--form form.wpcf7-form > :not(.form--field) { grid-column: 1 / -1; }
.pe--form .form--field label { display: block; }
.pe--form .wpcf7-form-control-wrap { display: block; }
.pe--form .wpcf7-form-control:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not(.wpcf7-acceptance):not(.wpcf7-checkbox) {
  width: 100%;
  margin: 0;
  padding: 16px 20px;
  border: 1px solid var(--mainColor, #070707) !important;
  background: transparent !important;
  color: var(--mainColor, #070707);
  font: inherit;
  line-height: 1.3;
  outline: 0;
  box-shadow: none;
}
.pe--form .wpcf7-form-control::placeholder { color: var(--secondaryColor, #858585); opacity: 1; }
.pe--form textarea.wpcf7-form-control { display: block; min-height: 132px; resize: vertical; }
.pe--form select.wpcf7-form-control {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px !important;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%) !important;
  background-position: calc(100% - 23px) 50%, calc(100% - 17px) 50% !important;
  background-size: 6px 6px, 6px 6px !important;
  background-repeat: no-repeat !important;
}
.pe--form .wpcf7-form-control:focus-visible {
  outline: 2px solid var(--mainColor, #070707);
  outline-offset: 2px;
}
.pe--form .wpcf7-not-valid { border-color: #b42318 !important; }
.pe--form .wpcf7-not-valid-tip { margin-top: 6px; font-size: 0.875rem; color: #b42318; }
body.layout--switched .pe--form .wpcf7-not-valid { border-color: #ff9b8a !important; }
body.layout--switched .pe--form .wpcf7-not-valid-tip { color: #ff9b8a; }

/* consent */
.pe--form .tf-form-consent { font-size: 0.875rem; line-height: 1.45; color: var(--secondaryColor, #5a5a5a); }
.pe--form .tf-form-consent .wpcf7-list-item { margin: 0; }
.pe--form .tf-form-consent label { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; }
.pe--form .tf-form-consent input[type="checkbox"] {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin: 1px 0 0;
  accent-color: var(--mainColor, #070707);
}
.pe--form .tf-form-consent a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

/* the button */
.pe--form input.wpcf7-submit {
  justify-self: start;
  min-height: 54px;
  padding: 0 30px;
  border: 0 !important;
  background: var(--mainColor, #070707) !important;
  color: var(--mainBackground, #f0f0f0) !important;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .pe--form input.wpcf7-submit { transition: opacity 0.16s ease; }
  .pe--form input.wpcf7-submit:hover { opacity: 0.82; }
}
.pe--form .wpcf7-spinner { display: none; }
.pe--form .wpcf7-response-output {
  grid-column: 1 / -1;
  margin: 4px 0 0 !important;
  padding: 14px 18px !important;
  border: 1px solid var(--mainColor, #070707) !important;
  border-radius: var(--tf-r-ctl);
  font-size: 0.9375rem;
}
.pe--form form.init .wpcf7-response-output:empty,
.pe--form .wpcf7-response-output:empty { display: none; }
@media (max-width: 600px) {
  .pe--form form.wpcf7-form { grid-template-columns: minmax(0, 1fr); }
  .pe--form input.wpcf7-submit { width: 100%; justify-self: stretch; }
}


/* ------------------------------------------------------------------ Clients page
   One tile per client, laid as a tight wall. Every logo is shown in greyscale on the theme's
   second ground, with the name under it. Under the pointer (or keyboard focus) the tile turns
   to the opposite ground: black with a white logo on the light theme, the reverse on the dark
   one. The whole tile is the link.

   Two switches drive it. --tf-flip is 1 while the tile is pointed at. --tf-on-dark says whether
   the logo currently sits on a dark ground: dark theme at rest, or light theme while flipped. */
body { --tf-dark-theme: 0; }
body.layout--switched { --tf-dark-theme: 1; }
.tf-clients {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.tf-client {
  --tf-flip: 0;
  --tf-on-dark: calc(var(--tf-flip) + var(--tf-dark-theme) - 2 * var(--tf-flip) * var(--tf-dark-theme));
  position: relative;
  min-width: 0;
  aspect-ratio: 4 / 3;
  border-radius: var(--tf-r-card);
  background-color: color-mix(in srgb, var(--mainColor, #070707) calc(var(--tf-flip) * 100%), var(--secondaryBackground, #dcdcdc));
  box-shadow: inset 0 0 0 1px var(--tf-glass-edge), inset 0 1px 0 0 var(--tf-glass-rim);
  overflow: hidden;
  transition: background-color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .tf-client:hover { --tf-flip: 1; }
}
.tf-client:has(:focus-visible) { --tf-flip: 1; }
.tf-client__link {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 18px 18px 40px;
  color: color-mix(in srgb, var(--mainBackground, #f0f0f0) calc(var(--tf-flip) * 100%), var(--mainColor, #070707));
  text-decoration: none;
  transition: color 0.2s ease;
}
.tf-client__logo {
  display: grid;
  grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  place-items: center;
  width: 100%;
  height: 100%;
  min-height: 0;
}
.tf-client__logo img {
  grid-area: 1 / 1;
  max-width: 68%;
  max-height: 100%;
  object-fit: contain;
  filter: grayscale(1);
  transition: opacity 0.2s ease, filter 0.2s ease;
}
/* a client with two logo files: the one drawn for the ground it is on */
.tf-client.has-dark-logo .is-light { opacity: calc(1 - var(--tf-on-dark)); }
.tf-client.has-dark-logo .is-dark { opacity: var(--tf-on-dark); }
/* a client with one logo file: the same file, turned white on a dark ground */
.tf-client:not(.has-dark-logo) .is-light {
  filter: grayscale(1) brightness(calc(1 - var(--tf-on-dark))) invert(var(--tf-on-dark));
}
.tf-client__logo--name {
  padding: 0 6px;
  font-size: clamp(18px, 1.5vw, 26px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-align: center;
}
.tf-client__name {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 13px;
  overflow: hidden;
  font-size: 13px;
  line-height: 1.2;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: color-mix(in srgb, var(--mainBackground, #f0f0f0) calc(var(--tf-flip) * 100%), var(--secondaryColor, #858585));
  transition: color 0.2s ease;
}
.tf-client__case {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 5px 9px;
  border-radius: var(--tf-r-ctl);
  background-color: color-mix(in srgb, var(--mainBackground, #f0f0f0) calc(var(--tf-flip) * 100%), var(--mainColor, #070707));
  color: color-mix(in srgb, var(--mainColor, #070707) calc(var(--tf-flip) * 100%), var(--mainBackground, #f0f0f0));
  font-size: 12px;
  line-height: 1;
  text-decoration: none;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.tf-client__link:focus-visible,
.tf-client__case:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--mainBackground, #f0f0f0) calc(var(--tf-flip) * 100%), var(--mainColor, #070707));
  outline-offset: -4px;
}
@media (max-width: 1024px) { .tf-clients { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 600px) {
  .tf-clients { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .tf-client__link { padding: 14px 12px 34px; }
  .tf-client__name { left: 12px; right: 12px; bottom: 10px; font-size: 12px; }
}

/* the logo strip on Home shows its logos the way the Clients wall does: in greyscale */
.pe--clients .pe-client img { filter: grayscale(1); }

/* The strip's tiles were 350 by 300, a quarter of a desktop screen each, and nearly a whole phone
   screen (asked by Eni, 9 October: smaller logos, slower strip). The speed is set in launch.js. */
.elementor .pe--clients.pe--clients--carousel .pe--clients--wrapper > div { width: 210px; height: 170px; padding: 0 16px; box-sizing: border-box; }
@media (max-width: 767px) {
  .elementor .pe--clients.pe--clients--carousel .pe--clients--wrapper > div { width: 150px; height: 120px; padding: 0 10px; }
}

/* A Vimeo film waits for its player until it is near the screen (launch.js). Its box had no height
   until then and pushed the page down when the player arrived; it keeps the film's place now. */
.elementor-widget-pevideo .pe-video.pe-vimeo:not(:has(.plyr)) { aspect-ratio: 16 / 9; }

/* The page is on screen before the scripts have run (front.php, "the first screen"). An icon is a
   word drawn by a font ("arrow_outward"), and that font is 126 KB. Until launch.js has fetched it,
   after the first paint, an icon is an empty square of its final size, set in an ordinary font so
   that the icon font is not asked for. Eight seconds at the latest it shows whatever happens. */
html:not(.tf-icons) .material-icons {
  font-family: sans-serif; width: 1em; overflow: hidden; visibility: hidden;
  animation: tf-icons-anyway 0s linear 8s forwards;
}
@keyframes tf-icons-anyway { to { visibility: visible; font-family: 'Material Icons'; } }

/* text for screen readers only (launch.js puts the sentence of a split, animated paragraph here) */
.tf-sr {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ------------------------------------------------------------------ header: the light/dark switch
   It belongs to the top of the page. Once the page scrolled it stayed where it was and sat over
   the content, so it leaves with the menu and comes back at the top (asked by Eni, 8 October). */
.site-header .elementor-widget-pelayoutswitcher {
  transition: opacity 0.2s ease, visibility 0.2s ease;
}
.site-header.header--move .elementor-widget-pelayoutswitcher {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* the "Visit Website" button that inc/front.php prints under a case study's opening lines */
.tf-visit { margin-top: 22px; }

/* footer: privacy policy and cookie settings */
.tf-footer-links { display: inline-flex; flex-wrap: wrap; gap: 6px 18px; }
.tf-footer-links a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

/* ------------------------------------------------------------------ case-study devices
   Each case study opens differently. These are the small pieces the page builder has no widget for. */

/* a price list of facts, label left, value right, a dotted leader between (Cafe e Gelato) */
.tf-ledger { margin: 0; }
.tf-ledger div {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 15px 0;
  border-top: 1px solid rgba(126, 126, 126, 0.34);
}
.tf-ledger div:last-child { border-bottom: 1px solid rgba(126, 126, 126, 0.34); }
.tf-ledger dt { flex: 0 0 auto; color: var(--secondaryColor, #858585); }
.tf-ledger dd {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  gap: 12px;
  min-width: 0;
  margin: 0;
  text-align: right;
}
.tf-ledger dd::before {
  content: "";
  flex: 1 1 24px;
  min-width: 24px;
  border-bottom: 2px dotted currentColor;
  opacity: 0.32;
  transform: translateY(-4px);
}
.tf-ledger dd span { flex: 0 1 auto; }

/* a text column that stays in view while its boards scroll past (first used on a case study since removed) */
@media (min-width: 1025px) {
  .tf-sticky { position: sticky !important; top: 110px; align-self: flex-start; }
}

/* a command line as a heading (Remote) */
.tf-cmd {
  margin: 0;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: clamp(18px, 1.7vw, 28px);
  line-height: 1.3;
  color: var(--mainColor, #070707);
  overflow-wrap: anywhere;
}
.tf-cmd__p { color: var(--secondaryColor, #858585); }

/* the client's own menu word above a margin note (AE Tech 360) */
.tf-tag {
  display: inline-block;
  margin: 0;
  padding: 3px 9px 4px;
  border: 1px solid currentColor;
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: 0.02em;
  opacity: 0.72;
}

/* an outlined text tile in a two-column grid of boards, and the client's own terms as a strip
   of tiles (Sprint Energy) */
.tf-tile { border: 1px solid rgba(126, 126, 126, 0.34); }
.tf-chain {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.tf-chain li {
  padding: 58px 16px 14px;
  border: 1px solid rgba(126, 126, 126, 0.34);
  font-size: 20px;
  line-height: 1.15;
  letter-spacing: -0.01em;
}
@media (max-width: 1024px) {
  .tf-chain { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
  .tf-chain { grid-template-columns: repeat(2, 1fr); }
  .tf-chain li { padding-top: 34px; font-size: 17px; }
}

/* Eurpharma's case study (make_case.py, "label" and "leaflet"): it opens with the client and the
   work as the label of a pack, ruled into cells, and tells the rest as one text in leaflet columns,
   each part opened by a bold run-in heading. Both belong to that project alone. */
.tf-label {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 2fr);
  border: 1px solid rgba(126, 126, 126, 0.34);
  border-radius: var(--tf-r-card);
}
.tf-label p { margin: 0; }
.tf-label__name {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 60px;
  padding: 26px 28px 24px;
  border-right: 1px solid rgba(126, 126, 126, 0.34);
}
.tf-label__who { font-size: clamp(30px, 3.4vw, 52px); line-height: 1.04; letter-spacing: -0.02em; }
.tf-label__what { color: var(--secondaryColor, #5e5e5e); font-size: 17px; line-height: 1.35; }
.tf-label__facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 0; }
.tf-label__facts > div { padding: 22px 26px 24px; border-bottom: 1px solid rgba(126, 126, 126, 0.34); }
.tf-label__facts > div:nth-child(odd) { border-right: 1px solid rgba(126, 126, 126, 0.34); }
.tf-label__facts > div:nth-last-child(-n + 2) { border-bottom: 0; }
.tf-label__facts dt { margin: 0 0 10px; color: var(--secondaryColor, #5e5e5e); font-size: 14px; line-height: 1.2; font-weight: 400; }
.tf-label__facts dd { margin: 0; font-size: 19px; line-height: 1.35; }
.tf-label__sw { display: inline-flex; align-items: center; gap: 9px; margin-right: 22px; white-space: nowrap; }
.tf-label__sw i { width: 22px; height: 22px; border-radius: 3px; box-shadow: inset 0 0 0 1px rgba(7, 7, 7, 0.12); }
.tf-leaflet { columns: 3; column-gap: 44px; column-rule: 1px solid rgba(126, 126, 126, 0.34); }
.tf-leaflet p { margin: 0 0 18px; break-inside: avoid; font-size: 17px; line-height: 1.5; }
.tf-leaflet p:last-child { margin-bottom: 0; }
.tf-leaflet strong { font-weight: 600; }
@media (max-width: 1024px) {
  .tf-label { grid-template-columns: 1fr; }
  .tf-label__name { gap: 28px; border-right: 0; border-bottom: 1px solid rgba(126, 126, 126, 0.34); }
  .tf-leaflet { columns: 2; column-gap: 32px; }
}
@media (max-width: 600px) {
  .tf-label__name { padding: 20px 18px; }
  .tf-label__facts > div { padding: 16px 18px 18px; }
  .tf-label__facts dd { font-size: 17px; }
  .tf-leaflet { columns: 1; }
}

/* Radiant Dent's case study (make_case.py, "tongues" and "thread"): it opens with one line of the
   client's site in each of its five languages, and its chapters hang on a line that runs down the
   left of the page, a square node at each title. Both belong to that project alone. */
.tf-tongues { margin: 0; padding: 0; list-style: none; border-top: 1px solid rgba(126, 126, 126, 0.34); }
.tf-tongues li {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  align-items: baseline;
  gap: 0 18px;
  padding: 15px 0 18px;
  border-bottom: 1px solid rgba(126, 126, 126, 0.34);
}
.tf-tongues span { color: var(--secondaryColor, #5e5e5e); font-size: 14px; line-height: 1; }
.tf-tongues p { margin: 0; font-size: clamp(24px, 4.3vw, 62px); line-height: 1.08; letter-spacing: -0.02em; }
/* the line stands in from the screen edge, so its node starts where the rules of the opening start */
.elementor .tf-thread {
  --tf-thread-in: 46px;
  --tf-thread-at: 15px;
  background: linear-gradient(rgba(126, 126, 126, 0.5), rgba(126, 126, 126, 0.5)) var(--tf-thread-at) 0 / 1px 100% no-repeat;
}
.tf-thread__t {
  position: relative;
  margin: 0 0 12px;
  font-size: clamp(24px, 2.5vw, 38px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  font-weight: 400;
}
.tf-thread__t::before {
  content: "";
  position: absolute;
  top: 0.42em;
  left: calc(var(--tf-thread-at) - var(--tf-thread-in) - 5px);
  width: 11px;
  height: 11px;
  background: var(--mainColor, #070707);
}
.tf-thread__x { max-width: 64ch; margin: 0; }
@media (max-width: 767px) {
  .elementor .tf-thread { --tf-thread-in: 30px; }
  .tf-tongues li { grid-template-columns: 34px minmax(0, 1fr); gap: 0 10px; padding: 12px 0 14px; }
  .tf-tongues span { font-size: 12px; }
}

/* GTE Trade's case study (make_case.py, "picks" and "spec"): it opens with one statement in which the
   five things made are chips that jump to their chapters, and each chapter is set like a line of the
   client's catalogue, a title and a short text on the left and a table of particulars on the right.
   Both belong to that project alone. */
.tf-picks {
  max-width: 25em;
  margin: 0;
  font-size: clamp(25px, 3.5vw, 52px);
  line-height: 1.34;
  letter-spacing: -0.02em;
}
.tf-picks span { white-space: nowrap; }
.tf-picks a,
.tf-picks a:link,
.tf-picks a:visited,
.tf-picks a:hover {
  color: var(--mainColor, #070707) !important;
}
.tf-picks a {
  display: inline-block;
  padding: 0 0.34em 0.04em 0.3em;
  border-radius: var(--tf-r-ctl);
  background: var(--tf-glass-bg);
  box-shadow: inset 0 0 0 1px var(--tf-glass-edge), inset 0 1px 0 0 var(--tf-glass-rim);
  line-height: 1.16;
  text-decoration: none;
  transition: background-color 0.2s ease;
}
.tf-picks a::before {
  content: "";
  display: inline-block;
  width: 0.22em;
  height: 0.22em;
  margin-right: 0.3em;
  vertical-align: 0.2em;
  background: currentColor;
}
@media (hover: hover) and (pointer: fine) {
  .tf-picks a:hover { background: color-mix(in srgb, var(--mainColor, #070707) 10%, var(--tf-glass-bg)); }
}
.tf-picks a:focus-visible { outline: 2px solid var(--mainColor, #070707); outline-offset: 2px; }
.tf-spec {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: 26px 72px;
  align-items: start;
  padding-top: 24px;
  border-top: 1px solid rgba(126, 126, 126, 0.5);
  scroll-margin-top: 104px;
}
.tf-spec__t {
  display: flex;
  align-items: center;
  gap: 0.36em;
  margin: 0 0 14px;
  font-size: clamp(26px, 2.9vw, 44px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  font-weight: 400;
}
.tf-spec__t::before {
  content: "";
  flex: none;
  width: 0.24em;
  height: 0.24em;
  background: currentColor;
}
.tf-spec__x { max-width: 48ch; margin: 0; }
.tf-spec__rows { margin: 0; }
.tf-spec__rows div {
  display: grid;
  grid-template-columns: 9.4em minmax(0, 1fr);
  gap: 0 18px;
  align-items: baseline;
  padding: 11px 0 12px;
  border-bottom: 1px solid rgba(126, 126, 126, 0.34);
}
.tf-spec__rows div:first-child { padding-top: 4px; }
.tf-spec__rows dt { color: var(--secondaryColor, #5e5e5e); font-size: 14px; line-height: 1.4; }
.tf-spec__rows dd { margin: 0; font-size: 16px; line-height: 1.4; }
@media (max-width: 1024px) {
  .tf-spec { grid-template-columns: 1fr; }
}
@media (max-width: 767px) {
  .tf-spec { scroll-margin-top: 84px; }
  .tf-spec__rows div { grid-template-columns: 7em minmax(0, 1fr); gap: 0 12px; }
  .tf-spec__rows dt { font-size: 13px; }
  .tf-spec__rows dd { font-size: 15px; }
}

/* Birra Tirana's case study (make_case.py, "fold" and "then"): it opens with the old sitemap folding into
   the new one, a curve from each old page to the page it became (a list below 1025px, where the drawing
   would be too small to read), and each chapter is a before and a now side by side under its title.
   Both belong to that project alone. */
.tf-fold { margin: 0; }
.tf-fold__map { display: block; width: 100%; height: auto; overflow: visible; font-family: inherit; }
.tf-fold__map .h { fill: var(--secondaryColor, #5e5e5e); font-size: 15px; }
.tf-fold__map .l { fill: var(--secondaryColor, #5e5e5e); font-size: 16px; }
.tf-fold__map .r { fill: var(--mainColor, #070707); font-size: 30px; letter-spacing: -0.02em; }
.tf-fold__map rect { fill: var(--mainColor, #070707); }
.tf-fold__lines path { fill: none; stroke: var(--mainColor, #070707); stroke-opacity: 0.3; stroke-width: 1; vector-effect: non-scaling-stroke; }
.tf-fold__list { display: none; margin: 0; padding: 0; list-style: none; border-top: 1px solid rgba(126, 126, 126, 0.34); }
.tf-fold__list li { padding: 12px 0 13px; border-bottom: 1px solid rgba(126, 126, 126, 0.34); }
.tf-fold__list b { display: block; font-size: 22px; line-height: 1.2; font-weight: 400; letter-spacing: -0.01em; }
.tf-fold__list span { display: block; margin-top: 3px; color: var(--secondaryColor, #5e5e5e); font-size: 14px; line-height: 1.45; }
.tf-fold__cap { max-width: 62ch; margin: 26px 0 0; color: var(--secondaryColor, #5e5e5e); font-size: 15px; line-height: 1.5; }
.tf-then {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 3fr) minmax(0, 5fr);
  gap: 22px 48px;
  align-items: start;
  padding-top: 24px;
  border-top: 1px solid rgba(126, 126, 126, 0.5);
}
.tf-then__t { margin: 0; font-size: clamp(26px, 2.7vw, 42px); line-height: 1.08; letter-spacing: -0.02em; font-weight: 400; }
.tf-then p { margin: 0; }
.tf-then__k { margin: 0 0 8px !important; font-size: 13px; line-height: 1.2; letter-spacing: 0.02em; color: var(--secondaryColor, #5e5e5e); }
.tf-then__was p:last-child { color: var(--secondaryColor, #5e5e5e); font-size: 15px; line-height: 1.5; }
.tf-then__now p:last-child { font-size: 17px; line-height: 1.5; max-width: 52ch; }
.tf-then__now .tf-then__k::after { content: " \2192"; }
@media (max-width: 1024px) {
  .tf-fold__map { display: none; }
  .tf-fold__list { display: block; }
  .tf-fold__cap { margin-top: 18px; }
  .tf-then { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
  .tf-then__t { grid-column: 1 / -1; }
}
@media (max-width: 767px) {
  .tf-then { grid-template-columns: 1fr; gap: 16px; }
}

/* Consilîum's case study (make_case.py, "wordmark" and "lead"): it opens with the client's own wordmark,
   drawn line by line when it comes into view (launch.js arms it), with notes pointing at its details;
   each chapter opens with one sentence whose last words fade, as on the client's site, and its account
   is set off to the right. Both belong to that project alone. */
.tf-mark { margin: 0; }
.tf-mark__art { position: relative; width: min(100%, 940px); margin: 0 auto; }
.tf-mark__svg { display: block; width: 100%; height: auto; overflow: visible; }
.tf-mark__line { position: absolute; width: 1px; background: color-mix(in srgb, var(--mainColor, #070707) 30%, transparent); }
.tf-mark__note {
  position: absolute;
  top: calc(100% + 46px);
  width: 15em;
  margin: 0;
  transform: translateX(-10px);
  color: var(--secondaryColor, #5e5e5e);
  font-size: 15px;
  line-height: 1.45;
}
.tf-mark__note.is-up { top: auto; bottom: calc(100% + 46px); }
.tf-mark.is-armed .wm-s,
.tf-mark.is-armed .wm-acc { stroke-dasharray: 1; stroke-dashoffset: 1; }
.tf-mark.is-armed .tf-mark__tag,
.tf-mark.is-armed .tf-mark__line,
.tf-mark.is-armed .tf-mark__note { opacity: 0; }
.tf-mark.is-in .wm-s,
.tf-mark.is-in .wm-acc { animation: tf-mark-draw 0.9s cubic-bezier(0.65, 0, 0.35, 1) forwards; animation-delay: calc(var(--i, 0) * 0.11s); }
.tf-mark.is-in .wm-acc { animation-delay: 1.05s; }
.tf-mark.is-in .tf-mark__tag { animation: tf-mark-show 0.6s ease 1.25s forwards; }
.tf-mark.is-in .tf-mark__line,
.tf-mark.is-in .tf-mark__note { animation: tf-mark-show 0.5s ease 1.6s forwards; }
@keyframes tf-mark-draw { to { stroke-dashoffset: 0; } }
@keyframes tf-mark-show { to { opacity: 1; } }
.tf-lead {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 22px 24px;
  padding-top: 24px;
  border-top: 1px solid rgba(126, 126, 126, 0.5);
}
.tf-lead__t {
  grid-column: 1 / 10;
  margin: 0;
  font-size: clamp(28px, 3.4vw, 52px);
  line-height: 1.12;
  letter-spacing: -0.02em;
  font-weight: 300;
}
.tf-lead__t span { color: color-mix(in srgb, var(--mainColor, #070707) 34%, transparent); }
.tf-lead__x { grid-column: 7 / 13; max-width: 52ch; margin: 0; }
@media (max-width: 1024px) {
  .tf-lead__t { grid-column: 1 / -1; }
  .tf-lead__x { grid-column: 4 / 13; }
}
@media (max-width: 767px) {
  .tf-mark__art { padding-bottom: 0; }
  .tf-mark__line { display: none; }
  .tf-mark__note,
  .tf-mark__note.is-up { position: static; width: auto; margin: 0; padding: 12px 0 0 16px; transform: none; font-size: 14px; }
  .tf-mark__note::before { content: ""; float: left; width: 6px; height: 6px; margin: 7px 0 0 -16px; background: currentColor; }
  .tf-mark__svg { margin-bottom: 18px; }
  .tf-lead { grid-template-columns: 1fr; gap: 16px; }
  .tf-lead__t, .tf-lead__x { grid-column: 1 / -1; }
}
@media (prefers-reduced-motion: reduce) {
  .tf-mark.is-armed .wm-s, .tf-mark.is-armed .wm-acc { stroke-dashoffset: 0; }
  .tf-mark.is-armed .tf-mark__tag, .tf-mark.is-armed .tf-mark__line, .tf-mark.is-armed .tf-mark__note { opacity: 1; }
}

/* Amazona's case study (make_case.py, "watermark" and "sticker"): it opens with one statement in front of
   the big faint words the client's site sets behind its sections (learn, fun, care, in its own colours),
   and each chapter title sits on a tilted coloured label, as the site sets "fun" in its first headline.
   Both belong to that project alone. */
.tf-wm { display: grid; align-items: center; padding: clamp(24px, 4vw, 60px) 0; overflow-x: clip; }
.tf-wm > * { grid-area: 1 / 1; }
.tf-wm__words {
  display: flex;
  flex-direction: column;
  margin: 0;
  pointer-events: none;
  user-select: none;
}
.tf-wm__words span {
  display: block;
  color: color-mix(in srgb, var(--c) 20%, transparent);
  font-size: clamp(84px, 16vw, 250px);
  line-height: 0.86;
  font-weight: 700;
  letter-spacing: -0.04em;
  white-space: nowrap;
}
.tf-wm__words span:nth-child(2) { text-align: right; }
.tf-wm__words span:nth-child(3) { padding-left: 18%; }
.tf-wm__t {
  position: relative;
  align-self: center;
  max-width: 24em;
  margin: 0;
  font-size: clamp(25px, 3.1vw, 46px);
  line-height: 1.22;
  letter-spacing: -0.015em;
}
.tf-sticker {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: 22px 48px;
  align-items: start;
  padding-top: 26px;
  border-top: 1px solid rgba(126, 126, 126, 0.5);
}
.tf-sticker__t {
  justify-self: start;
  margin: 4px 0 0 4px;
  padding: 0.16em 0.62em 0.24em;
  border-radius: 999px;
  background: var(--c);
  color: #2B2B2B;
  font-size: clamp(22px, 2.3vw, 34px);
  line-height: 1.15;
  letter-spacing: -0.01em;
  font-weight: 500;
  transform: rotate(var(--r, -3deg));
}
.tf-sticker__x { max-width: 56ch; margin: 0; }
@media (max-width: 767px) {
  .tf-wm__words span:nth-child(3) { padding-left: 6%; }
  .tf-sticker { grid-template-columns: 1fr; gap: 18px; }
}

/* Kazazi's case study (make_case.py, "memo" and "noted"): it opens as a memo, the way an adviser writes to a
   client (To, From, Subject, Date over a double rule, then the brief), and each chapter is written like an
   opinion, its numbered notes in a narrow column beside the text. Both belong to that project alone. */
.tf-memo { max-width: 1040px; }
.tf-memo__head { margin: 0 0 30px; padding-bottom: 14px; border-bottom: 3px double rgba(126, 126, 126, 0.55); }
.tf-memo__head div { display: grid; grid-template-columns: 7.5em minmax(0, 1fr); gap: 0 16px; padding: 5px 0; }
.tf-memo__head dt { color: var(--secondaryColor, #5e5e5e); font-size: 14px; line-height: 1.6; }
.tf-memo__head dd { margin: 0; font-size: 17px; line-height: 1.5; }
.tf-memo__body { margin: 0; font-size: clamp(24px, 2.8vw, 40px); line-height: 1.26; letter-spacing: -0.015em; }
.tf-noted {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 18px 24px;
  align-items: start;
  padding-top: 24px;
  border-top: 1px solid rgba(126, 126, 126, 0.5);
}
.tf-noted__t { grid-column: 1 / 4; margin: 0; font-size: clamp(26px, 2.6vw, 40px); line-height: 1.08; letter-spacing: -0.02em; font-weight: 400; }
.tf-noted__x { grid-column: 4 / 9; margin: 0; }
.tf-noted__x sup { font-size: 0.68em; line-height: 0; margin-left: 1px; color: var(--secondaryColor, #5e5e5e); }
.tf-noted__n {
  grid-column: 9 / 13;
  margin: 4px 0 0;
  padding: 12px 0 0 1.3em;
  border-top: 1px solid rgba(126, 126, 126, 0.34);
  color: var(--secondaryColor, #5e5e5e);
  font-size: 14px;
  line-height: 1.5;
}
.tf-noted__n li { margin: 0 0 8px; padding-left: 2px; }
.tf-noted__n li::marker { font-size: 12px; }
@media (max-width: 1024px) {
  .tf-noted__t { grid-column: 1 / -1; }
  .tf-noted__x { grid-column: 1 / 8; }
  .tf-noted__n { grid-column: 8 / 13; }
}
@media (max-width: 767px) {
  .tf-memo__head div { grid-template-columns: 5.6em minmax(0, 1fr); }
  .tf-memo__head dd { font-size: 15px; }
  .tf-noted { grid-template-columns: 1fr; gap: 14px; }
  .tf-noted__t, .tf-noted__x, .tf-noted__n { grid-column: 1 / -1; }
}

/* AE Tech 360's 2026 case study (make_case.py, "changelog" and "figure"): the redesign opens as release
   notes (Added, Changed, Fixed, Removed), and each chapter is led by one figure from the work, its label
   under it and the account beside it. Both belong to that project alone. */
.tf-log__site { margin: 0; font-size: clamp(40px, 6vw, 92px); line-height: 1; letter-spacing: -0.035em; font-weight: 300; }
.tf-log__when { margin: 12px 0 0; color: var(--secondaryColor, #5e5e5e); font-size: 15px; }
.tf-log__groups { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 34px 56px; margin-top: 48px; }
.tf-log__g { padding-top: 14px; border-top: 1px solid rgba(126, 126, 126, 0.5); }
.tf-log__k { margin: 0 0 12px; font-size: 15px; line-height: 1.3; font-weight: 500; letter-spacing: 0.01em; }
.tf-log__g ul { margin: 0; padding: 0; list-style: none; }
.tf-log__g li { position: relative; margin: 0 0 8px; padding-left: 18px; font-size: 16px; line-height: 1.45; }
.tf-log__g li::before { content: ""; position: absolute; left: 0; top: 0.62em; width: 7px; height: 1px; background: currentColor; }
.tf-fig {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 18px 24px;
  align-items: start;
  padding-top: 24px;
  border-top: 1px solid rgba(126, 126, 126, 0.5);
}
.tf-fig__n { grid-column: 1 / 6; margin: 0; font-size: clamp(54px, 7vw, 112px); line-height: 0.95; letter-spacing: -0.045em; font-weight: 300; }
.tf-fig__n span { display: block; max-width: 20em; margin-top: 12px; color: var(--secondaryColor, #5e5e5e); font-size: 14px; line-height: 1.4; letter-spacing: 0; }
.tf-fig__a { grid-column: 7 / 13; }
.tf-fig__t { margin: 0 0 12px; font-size: clamp(24px, 2.4vw, 36px); line-height: 1.1; letter-spacing: -0.02em; font-weight: 400; }
.tf-fig__x { max-width: 52ch; margin: 0; }
@media (max-width: 1024px) {
  .tf-fig__n { grid-column: 1 / 6; }
  .tf-fig__a { grid-column: 6 / 13; }
}
@media (max-width: 767px) {
  .tf-log__groups { grid-template-columns: 1fr; gap: 26px; margin-top: 34px; }
  .tf-fig { grid-template-columns: 1fr; gap: 14px; }
  .tf-fig__n, .tf-fig__a { grid-column: 1 / -1; }
}

/* the theme recolours visited and hovered links; the case-study chip keeps its own ink,
   which is the opposite of its tile's ground (see the Clients page above) */
.tf-client__case,
.tf-client__case:link,
.tf-client__case:visited,
.tf-client__case:hover {
  color: color-mix(in srgb, var(--mainColor, #070707) calc(var(--tf-flip) * 100%), var(--mainBackground, #f0f0f0)) !important;
}
/* the same for the tile's own link, whose ink the theme would otherwise change once visited */
.tf-client__link,
.tf-client__link:link,
.tf-client__link:visited,
.tf-client__link:hover {
  color: color-mix(in srgb, var(--mainBackground, #f0f0f0) calc(var(--tf-flip) * 100%), var(--mainColor, #070707)) !important;
}

/* ------------------------------------------------------------------ privacy policy
   A plain page of text: one readable column, headings sized for reading, the table as ruled rows. */
.tf-policy {
  max-width: 760px;
  margin: 0 auto;
  padding: 150px 16px 110px;
}
.tf-policy h1 {
  margin: 0 0 14px;
  font-size: clamp(40px, 5vw, 64px);
  line-height: 1.05;
  letter-spacing: -0.02em;
}
.tf-policy h2 {
  margin: 46px 0 10px;
  font-size: 26px;
  line-height: 1.25;
  letter-spacing: -0.01em;
}
.tf-policy p {
  margin: 0 0 14px;
  font-size: 17px;
  line-height: 1.65;
}
.tf-policy em { color: var(--secondaryColor, #858585); }
.tf-policy a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.tf-policy code { font-size: 0.92em; }
.tf-policy-table {
  width: 100%;
  margin: 18px 0 8px;
  border-collapse: collapse;
  font-size: 15px;
  line-height: 1.5;
}
.tf-policy-table th,
.tf-policy-table td {
  padding: 12px 16px 12px 0;
  border-top: 1px solid rgba(126, 126, 126, 0.34);
  text-align: left;
  vertical-align: top;
}
.tf-policy-table th { font-weight: 500; color: var(--secondaryColor, #858585); }
@media (max-width: 600px) {
  .tf-policy { padding-top: 120px; }
  .tf-policy-table thead { display: none; }
  .tf-policy-table tr { display: block; padding: 12px 0; border-top: 1px solid rgba(126, 126, 126, 0.34); }
  .tf-policy-table td { display: block; padding: 2px 0; border: 0; }
  .tf-policy-table td:first-child { font-weight: 500; }
}

/* The case-study title is a real h1 (inc/front.php). These repeat, for the h1, the type each hero
   template gave its paragraph, so the title keeps its size, case and spacing. */
.elementor-6855 .elementor-element.elementor-element-6d893c3 .text-wrapper h1 {
  clear: none;
  font-weight: normal;
  text-transform: uppercase;
  letter-spacing: -4px;
}
.elementor-4914 .elementor-element.elementor-element-0db13c7 .text-wrapper h1 {
  clear: none;
  font-size: 150px;
  letter-spacing: -5px;
}
@media (max-width: 767px) {
  .elementor-6855 .elementor-element.elementor-element-6d893c3 .text-wrapper h1 { font-size: 50px; letter-spacing: -2px; }
  .elementor-4914 .elementor-element.elementor-element-0db13c7 .text-wrapper h1 { font-size: 70px; letter-spacing: -2px; }
}

/* tablets (768 to 1024): a case-study title is set at 101px in a column 283px wide and ran over
   the text beside it on eleven of thirteen projects. In that range the title takes the full line,
   at a size that fits the longest title, and the two columns follow below it side by side. */
@media (min-width: 768px) and (max-width: 1024px) {
  .elementor-6855 .elementor-element.elementor-element-51ad634 { flex-wrap: wrap; }
  .elementor-6855 .elementor-element.elementor-element-938043c { width: 100%; }
  .elementor-6855 .elementor-element.elementor-element-dfc6df8,
  .elementor-6855 .elementor-element.elementor-element-7bd924d { width: calc(50% - 10px); }
  .elementor-6855 .elementor-element.elementor-element-6d893c3 .text-wrapper h1 { font-size: 9.4vw; letter-spacing: -0.035em; }
}

/* The project cards of the home table are scattered by the theme and then dealt into place by
   launch.js. Seen from outside that was a jump (layout shift 0.5 on a desktop). On the screens
   where they are dealt, the cards stay out of sight until they are in place; if the script never
   runs they show after four seconds anyway. */
@media (min-width: 1025px), (min-width: 768px) and (orientation: landscape) {
  .showcase-table:not([data-tf-arranged]) .showcase-project { visibility: hidden; }
  /* the four seconds count from the moment the theme's script has run: the page is on screen before that now */
  html:not(.first--load) .showcase-table:not([data-tf-arranged]) .showcase-project {
    animation: tf-cards-anyway 0s linear 4s forwards;
  }
}
@keyframes tf-cards-anyway { to { visibility: visible; } }

/* ------------------------------------------------------------------ home: the opening
   The headline, the sentence under it and the service links open the page; the project table
   follows (Eni, 9 October). They are plain text with an entrance that needs no script, so they are
   on screen with the first paint, and the headline is the largest thing in it. The entrance only
   moves the text: a headline that starts invisible is not counted as painted until it shows, and a
   blur made its first frame arrive late. Layout: launch/apply/28-home-hero.php. */
:root { --tf-quiet: #5e5e5e; }
body.layout--switched { --tf-quiet: #9b9b9b; }
.elementor .tf-hero { padding: 6px 22.5px 46px; }
.tf-hero__title h1 { animation: tf-hero-in 0.9s cubic-bezier(0.23, 1, 0.32, 1) both; }
.tf-hero__row {
  display: grid; grid-template-columns: minmax(0, 46ch) minmax(0, 1fr); gap: 28px 64px;
  align-items: end; margin-top: 30px;
}
.tf-hero__lead { color: var(--tf-quiet); animation: tf-hero-in 0.9s cubic-bezier(0.23, 1, 0.32, 1) 0.06s both; }
.tf-hero__services { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin: 0; padding: 0; list-style: none; }
.tf-hero__services li { animation: tf-hero-in 0.7s cubic-bezier(0.23, 1, 0.32, 1) both; animation-delay: calc(0.14s + var(--i, 0) * 0.05s); }
.tf-hero__services a {
  display: inline-flex; align-items: center; gap: 9px; padding: 11px 15px 11px 13px;
  border-radius: var(--tf-r-ctl); color: var(--mainColor, #070707); font-size: 15px; line-height: 1;
  text-decoration: none; white-space: nowrap; background: var(--tf-glass-bg);
  box-shadow: inset 0 0 0 1px var(--tf-glass-edge), inset 0 1px 0 0 var(--tf-glass-rim);
  transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
.tf-hero__services svg { flex: none; }
.tf-hero__services .tf-hero__all { padding-left: 15px; background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mainColor, #070707) 22%, transparent); }
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .tf-hero__services a { -webkit-backdrop-filter: blur(18px) saturate(170%); backdrop-filter: blur(18px) saturate(170%); }
}
@media (hover: hover) and (pointer: fine) {
  .tf-hero__services a:hover { background: color-mix(in srgb, var(--mainColor, #070707) 9%, var(--tf-glass-bg)); }
}
.tf-hero__services a:focus-visible { outline: 2px solid var(--mainColor, #070707); outline-offset: 2px; }
@keyframes tf-hero-in { from { transform: translateY(20px); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .tf-hero__title h1, .tf-hero__lead, .tf-hero__services li { animation: none; }
}
@media (max-width: 1024px) {
  .tf-hero__row { grid-template-columns: minmax(0, 1fr); }
  .tf-hero__services { justify-content: flex-start; }
}
@media (max-width: 767px) {
  .elementor .tf-hero { padding: 0 10px 34px; }
  .tf-hero__row { margin-top: 20px; gap: 20px; }
  .tf-hero__services a { padding: 10px 12px 10px 11px; font-size: 14px; }
}

/* ------------------------------------------------------------------ secondary text
   The theme's grey for secondary text is #858585 in both layouts. On the dark grounds that reads
   well (5 to 1). On the light ones (#F0F0F0, #DCDCDC) it is 3.2 and 2.7 to 1, under the 4.5 that
   small text needs, so the light layout gets a darker grey. Same selectors as the theme's own
   light set. Paragraphs that carried the grey as their own colour now use this variable too
   (launch/apply/29-grey-text.php). */
:root body.layout--switched .header--switched,
:root { --secondaryColor: #5e5e5e; }

/* ------------------------------------------------------------------ home: below the first screen
   Until the theme's script has run, the sections under the opening are not laid out or drawn:
   they are below the screen, and on desktop the project cards stay hidden until they are dealt
   anyway. The first paint then only has the header and the opening to work out; the rest follows
   the moment the scripts start. Without scripts everything shows (a noscript rule in the head,
   and after-paint.js lifts this after nine seconds whatever happens). */
html.first--load body.home .tf-hero ~ .e-con,
html.first--load body.home main .elementor > .e-con.e-parent ~ .e-con.e-parent,
html.first--load body.home .site-footer { content-visibility: hidden; }

/* ------------------------------------------------------------------ the font, before it arrives
   The page is drawn before Inter has come from Google Fonts. Body text then fell back to Arial,
   and headings, whose rule names Inter alone, to the browser's serif: a first screen in Times
   that re-set itself a moment later, moving the menu and re-wrapping the lines. This stand-in is
   the visitor's own Arial (Roboto on Android) stretched to Inter's width and line metrics, so the
   change to Inter moves nothing. The selectors repeat the theme's own, one step more specific. */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial"), local("Roboto"), local("Helvetica Neue"), local("Helvetica");
  ascent-override: 90.49%; descent-override: 22.56%; line-gap-override: 0%; size-adjust: 107.06%;
}
html body,
html #page h1, html #page h2, html #page h3, html #page h4, html #page h5, html #page h6 {
  font-family: Inter, "Inter Fallback", Arial, Helvetica, sans-serif;
}

/* ------------------------------------------------------------------ Clients: the wall on a phone
   On phones the page builder lets a column container wrap, and Chrome then gives the wall's
   widget the height of one row of tiles instead of all of them (each tile takes its height from
   its width). The page ended after the first row and the footer was drawn over the rest. */
.elementor-element-tfcl008,
.e-con:has(> .elementor-widget-shortcode > .elementor-shortcode > .tf-clients) { --flex-wrap: nowrap; flex-wrap: nowrap; }

/* ------------------------------------------------------------------ the menu on phones and tablets
   The full-screen menu also carries a featured project (a film, its categories, its name). Beside
   the links there is no room for it under 1025px: it lay over them in pieces. It shows on desktop only. */
@media (max-width: 1024px) {
  .site--menu .elementor-widget-pesingleproject { display: none !important; }
}
/* On desktop the featured project waited for a scroll-triggered entrance that never comes inside a
   fixed menu (it stayed invisible, or came half-way after a page change). It is simply there. */
.site--menu .pe--single--project { opacity: 1 !important; visibility: visible !important; transform: none !important; }
/* The open menu is dark in both layouts: in the light one the header kept its dark logo over it. */
body:not(.layout--switched) .site-header:has(.menu--toggle.active) .main__logo,
body:not(.layout--switched) .site-header:has(.menu--toggle.active) .sticky__main__logo { display: none !important; }
body:not(.layout--switched) .site-header:has(.menu--toggle.active) .secondary__logo,
body:not(.layout--switched) .site-header:has(.menu--toggle.active) .sticky__secondary__logo { display: block !important; }
/* The featured project in the desktop menu: its categories lay over the picture as a grey pill with
   white text on it. Picture, name, then the categories as a quiet line; the site's own corners. */
.site--menu .pe--single--project { display: flex; flex-direction: column; gap: 12px; }
.site--menu .pe--single--project .thmb { overflow: hidden; }
.site--menu .pe--single--project .thmb,
.site--menu .pe--single--project .thmb .pe-video,
.site--menu .pe--single--project .thmb video,
.site--menu .pe--single--project .thmb img { border-radius: var(--tf-r-media) !important; }
.site--menu .pe--single--project .post-details { order: 2; margin: 0 !important; padding: 0 !important; }
.site--menu .pe--single--project .post-meta {
  order: 3; position: static !important; inset: auto !important; transform: none !important;
  width: auto !important; height: auto !important; margin: -6px 0 0 !important; padding: 0 !important;
  background: none !important; border-radius: 0 !important;
}
.site--menu .pe--single--project .post-categories {
  padding: 0 !important; background: none !important; border-radius: 0 !important;
  color: #9b9b9b !important; font-size: 14px; line-height: 1.4;
}

/* a picture with its own phone or tablet version (front.php, techfly_art_directed): the wrapper is
   not a box of its own, so every rule written for the picture still reaches it */
picture.tf-art { display: contents; }
/* the phone and tablet versions carry their title at the top: when the frame crops them, it crops the bottom */
@media (max-width: 1024px) { picture.tf-art img { object-position: center top !important; } }

/* ------------------------------------------------------------------ Inter, from this site
   The text font came from Google Fonts: a stylesheet from one of Google's servers, then the file
   from another, two connections before the real letters could show (and every visitor's address
   went to Google). The same two files are served from here now: Latin, which every page needs,
   and Latin Extended, which a browser only fetches when a page has such a letter. front.php takes
   the Google links out of the page and preloads the Latin file. Same weight (400) as before. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/inter-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/inter-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ------------------------------------------------------------------ the AI assistant
   The button is the site's own (inc/chatbot.php): the two sparks the site uses for AI, on the same
   glass as the cards. The plugin's round launcher is hidden; its window takes the site's colours,
   corners and typeface through the theme's own variables, in the light and the dark layout. */
.tf-chat-launch {
  position: fixed;
  z-index: 99970; /* under the cookie banner */
  right: 16px;
  bottom: 16px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 48px;
  margin: 0;
  padding: 0 16px 0 13px;
  border: 1px solid color-mix(in srgb, var(--mainColor, #070707) 16%, transparent);
  border-radius: var(--tf-r-ctl);
  background: var(--mainBackground, #f0f0f0);
  color: var(--mainColor, #070707);
  font: inherit;
  font-size: 15px;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  transition: transform 0.16s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.16s ease;
}
.tf-chat-launch[hidden] { display: none; }
.tf-chat-launch svg { flex: none; }
.tf-chat-launch:active { transform: scale(0.97); }
.tf-chat-launch:focus-visible { outline: 2px solid var(--mainColor, #070707); outline-offset: 3px; }
.tf-chat-launch.is-loading { cursor: progress; }
.tf-chat-launch.is-loading svg { animation: tf-chat-wait 0.9s ease-in-out infinite alternate; }
.tf-chat-launch.is-open { opacity: 0; visibility: hidden; pointer-events: none; }
@keyframes tf-chat-wait { from { opacity: 1; } to { opacity: 0.25; } }
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .tf-chat-launch {
    border: 0;
    background: var(--tf-glass-bg);
    -webkit-backdrop-filter: blur(22px) saturate(175%);
    backdrop-filter: blur(22px) saturate(175%);
    box-shadow:
      inset 0 0 0 1px var(--tf-glass-edge),
      inset 0 1px 0 0 var(--tf-glass-rim),
      var(--tf-glass-shadow);
  }
}
@media (max-width: 767px) {
  .tf-chat-launch { right: 10px; bottom: 10px; width: 48px; padding: 0; justify-content: center; }
  .tf-chat-launch span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
@media (prefers-reduced-motion: reduce) {
  .tf-chat-launch { transition: opacity 0.16s ease; }
  .tf-chat-launch:active { transform: none; }
  .tf-chat-launch.is-loading svg { animation: none; opacity: 0.5; }
}

.tf-chat .mwai-trigger { display: none !important; }
.tf-chat .mwai-timeless-theme {
  --mwai-fontFamily: Inter, "Inter Fallback", Arial, Helvetica, sans-serif;
  --mwai-fontSize: 15px;
  --mwai-borderRadius: var(--tf-r-card);
  --mwai-borderColor: color-mix(in srgb, var(--mainColor, #070707) 16%, transparent);
  --mwai-fontColor: var(--mainColor, #070707);
  --mwai-linkColor: var(--mainColor, #070707);
  --mwai-accentColor: var(--mainColor, #070707);
  --mwai-bubbleColor: var(--mainColor, #070707);
  --mwai-backgroundPrimaryColor: var(--mainBackground, #f0f0f0);
  --mwai-conversationsBackgroundColor: var(--mainBackground, #f0f0f0);
  --mwai-backgroundHeaderColor: var(--mainColor, #070707);
  --mwai-headerColor: var(--mainBackground, #f0f0f0);
  --mwai-backgroundUserColor: var(--mainColor, #070707);
  --mwai-backgroundAiColor: color-mix(in srgb, var(--mainColor, #070707) 7%, var(--mainBackground, #f0f0f0));
  --mwai-backgroundAiSecondaryColor: color-mix(in srgb, var(--mainColor, #070707) 14%, var(--mainBackground, #f0f0f0));
  --mwai-width: 380px;
  --mwai-maxHeight: 52vh;
  --mwai-headerHeight: 64px;
}
/* the window's head: the two sparks in place of the plugin's speech bubble, in the head's own ink */
.tf-chat .mwai-header .mwai-avatar { display: flex; align-items: center; justify-content: center; width: 40px; height: auto; }
.tf-chat .mwai-header .mwai-avatar img { display: none; }
.tf-chat .mwai-header .mwai-avatar::before {
  content: "";
  width: 30px;
  height: 30px;
  background: var(--mwai-headerColor);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.4' stroke-linejoin='miter'%3E%3Cpath d='M10 4.5c.5 4.2 2.8 6.5 7 7-4.2.5-6.5 2.8-7 7-.5-4.2-2.8-6.5-7-7 4.2-.5 6.5-2.8 7-7z'/%3E%3Cpath d='M18.5 2.5c.2 1.8 1.2 2.8 3 3-1.8.2-2.8 1.2-3 3-.2-1.8-1.2-2.8-3-3 1.8-.2 2.8-1.2 3-3z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.4' stroke-linejoin='miter'%3E%3Cpath d='M10 4.5c.5 4.2 2.8 6.5 7 7-4.2.5-6.5 2.8-7 7-.5-4.2-2.8-6.5-7-7 4.2-.5 6.5-2.8 7-7z'/%3E%3Cpath d='M18.5 2.5c.2 1.8 1.2 2.8 3 3-1.8.2-2.8 1.2-3 3-.2-1.8-1.2-2.8-3-3 1.8-.2 2.8-1.2 3-3z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.tf-chat .mwai-window-box { box-shadow: 0 0 0 1px var(--mwai-borderColor), var(--tf-glass-shadow); }
.tf-chat .mwai-gdpr-buttons button {
  min-height: 44px;
  border: 0;
  border-radius: var(--tf-r-ctl);
  background: var(--mainColor, #070707);
  color: var(--mainBackground, #f0f0f0);
  font: inherit;
  cursor: pointer;
}
.tf-chat .mwai-input-submit { border-radius: var(--tf-r-ctl); }
.tf-chat .mwai-reply.mwai-user,
.tf-chat .mwai-reply.mwai-user * { color: var(--mainBackground, #f0f0f0); }
.tf-chat .mwai-compliance { font-size: 12px; line-height: 1.4; }
.tf-chat .mwai-compliance a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.tf-chat .mwai-header,
.tf-chat .mwai-header .mwai-name,
.tf-chat .mwai-header .mwai-name *,
.tf-chat .mwai-header .mwai-buttons * { color: var(--mwai-headerColor); }
.tf-chat .mwai-mobile-header-close,
.tf-chat .mwai-mobile-header-close svg { color: var(--mwai-headerColor); stroke: currentColor; }

/* the head carries the Tech Fly mark (the white one on the dark head, the dark one on the light head) */
.tf-chat .mwai-header .mwai-avatar::before {
  width: 28px;
  height: 31px;
  background: url("/wp-content/uploads/2026/02/sticky_logo_white.svg") center / contain no-repeat;
  -webkit-mask: none;
  mask: none;
}
body.layout--switched .tf-chat .mwai-header .mwai-avatar::before { background-image: url("/wp-content/uploads/2026/02/sticky_logo_black.svg"); }

/* phones: the chat fills the screen and its head is a plain bar; the mark goes there too */
.tf-chat .mwai-mobile-header-title { display: flex; align-items: center; gap: 10px; }
.tf-chat .mwai-mobile-header-title::before { content: ""; flex: none; width: 20px; height: 22px; background: url("/wp-content/uploads/2026/02/sticky_logo_white.svg") center / contain no-repeat; }
body.layout--switched .tf-chat .mwai-mobile-header-title::before { background-image: url("/wp-content/uploads/2026/02/sticky_logo_black.svg"); }

/* the offer and the form under the conversation (inc/chatbot.php, techfly_chat_contact_html()) */
.tf-chat .tf-chat-contact {
  margin-top: 4px;
  padding: 14px;
  border: 1px solid var(--mwai-borderColor);
  border-radius: var(--tf-r-card);
  background: var(--mwai-backgroundAiColor);
  color: var(--mwai-fontColor);
  font-size: 14px;
  line-height: 1.45;
}
.tf-chat .tf-chat-contact p { margin: 0; }
.tf-chat .tf-chat-contact__ask { font-weight: 500; }
.tf-chat .tf-chat-contact [hidden] { display: none !important; }
.tf-chat .tf-chat-contact__open,
.tf-chat .tf-chat-contact__send {
  width: 100%;
  min-height: 44px;
  margin-top: 10px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--tf-r-ctl);
  background: var(--mainColor, #070707);
  color: var(--mainBackground, #f0f0f0);
  font: inherit;
  cursor: pointer;
  transition: opacity 0.16s ease;
}
.tf-chat .tf-chat-contact__send[disabled] { opacity: 0.55; cursor: progress; }
.tf-chat .tf-chat-contact__form { display: grid; gap: 10px; margin-top: 10px; }
.tf-chat .tf-chat-contact__form label { display: grid; gap: 4px; margin: 0; font-size: 13px; }
.tf-chat .tf-chat-contact__form input[type="text"],
.tf-chat .tf-chat-contact__form input[type="email"],
.tf-chat .tf-chat-contact__form textarea {
  width: 100%;
  min-height: 42px;
  margin: 0;
  padding: 9px 11px;
  border: 1px solid color-mix(in srgb, var(--mainColor, #070707) 28%, transparent);
  border-radius: var(--tf-r-ctl);
  background: var(--mainBackground, #f0f0f0);
  color: var(--mainColor, #070707);
  font: inherit;
  font-size: 16px; /* smaller, and a phone zooms the page when the field is tapped */
  line-height: 1.35;
  box-shadow: none;
}
.tf-chat .tf-chat-contact__form textarea { resize: vertical; }
.tf-chat .tf-chat-contact__form input:focus-visible,
.tf-chat .tf-chat-contact__form textarea:focus-visible,
.tf-chat .tf-chat-contact button:focus-visible { outline: 2px solid var(--mainColor, #070707); outline-offset: 2px; }
.tf-chat .tf-chat-contact__form .tf-chat-contact__agree { display: flex; align-items: flex-start; gap: 8px; }
.tf-chat .tf-chat-contact__agree input { flex: none; width: 18px; height: 18px; margin: 1px 0 0; accent-color: var(--mainColor, #070707); }
.tf-chat .tf-chat-contact__agree a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.tf-chat .tf-chat-contact__trap { position: absolute !important; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.tf-chat .tf-chat-contact__note:empty { display: none; }
.tf-chat .tf-chat-contact__note { font-size: 13px; }
.tf-chat .tf-chat-contact__done { font-weight: 500; }

/* ------------------------------------------------------------------ the hero's line
   Eni, 10 October: "add more graphic details to hero banner". A knot that unravels into a straight
   line and ends in a full stop: the headline, drawn. It sits in the space the headline leaves free
   (beside its second line; on phones beside its first) and is sized in the headline's own unit, so
   it keeps its place at every width and in the stand-in font. One image and two plain strips, used
   as a mask over the headline's ink: no markup, no request, light and dark for free. It is drawn in
   once, left to right. The shape comes from launch/tools/hero-knot.py. */
.tf-hero__title {
  position: relative;
  --tf-knot: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 170 100' fill='none' stroke='%23000' stroke-width='2.4' stroke-linejoin='round'%3E%3Cpath d='M44.7 80.9C46.3 80.7 51.6 81.6 54.4 79.9C57.2 78.2 59.8 74.8 61.5 70.7C63.3 66.6 64.4 60.9 64.7 55.6C65 50.2 64.5 43.8 63.2 38.6C62 33.5 59.8 28.2 57.2 24.6C54.7 21.1 51.3 18.4 47.9 17.5C44.6 16.6 40.7 17.3 37.2 19.2C33.7 21.2 30.1 25 27.2 29.2C24.2 33.4 21.5 39.3 19.7 44.5C17.9 49.8 16.7 56 16.4 60.9C16 65.8 16.4 70.6 17.5 73.8C18.6 76.9 20.6 79.1 22.8 79.8C25.1 80.4 28.1 79.5 31.1 77.6C34 75.7 37.5 72.1 40.6 68.3C43.6 64.5 46.8 59.3 49.4 54.7C51.9 50.1 54.3 44.8 55.9 40.7C57.6 36.6 58.7 32.6 59.1 30C59.6 27.4 59.4 25.7 58.7 25.2C57.9 24.7 56.5 25.6 54.8 27.2C53.1 28.8 50.8 31.8 48.5 34.9C46.2 38.1 43.5 42.3 41.1 46.1C38.6 49.9 36 54.3 33.8 57.7C31.6 61.2 29.5 64.5 28 66.8C26.5 69 25.2 70.6 24.6 71.2C23.9 71.7 23.7 71.2 24 69.9C24.3 68.7 25.2 66.2 26.3 63.5C27.5 60.8 29.3 57.1 31.1 53.6C33 50.1 35.4 46 37.6 42.6C39.9 39.3 42.4 35.8 44.6 33.4C46.9 31 49.2 29.1 51 28.4C52.8 27.6 54.5 27.8 55.6 28.9C56.7 30.1 57.4 32.4 57.5 35.2C57.6 38.1 57.1 42.1 56.1 46C55.1 49.8 53.5 54.6 51.6 58.5C49.6 62.4 47.1 66.6 44.5 69.5C41.9 72.4 38.8 74.8 36.1 75.8C33.3 76.8 30.2 76.7 27.8 75.4C25.4 74.1 23 71.3 21.4 67.9C19.8 64.5 18.6 59.6 18.2 54.9C17.8 50.2 18.1 44.5 19.1 39.8C20.1 35 21.9 30 24.1 26.6C26.4 23.2 29.4 20.4 32.5 19.4C35.6 18.3 39.3 18.6 42.7 20.3C46.1 21.9 49.8 25.4 52.7 29.4C55.7 33.4 58.6 39.1 60.6 44.5C62.6 49.8 64 56.2 64.6 61.3C65.2 66.5 64.9 71.8 64 75.3C63 78.9 61.1 81.6 58.7 82.5C56.4 83.4 53.2 82.8 49.9 80.8C46.7 78.9 42.8 75.1 39.4 70.9C35.9 66.6 32.1 60.8 29.1 55.5C26.1 50.2 23.2 43.9 21.2 39C19.2 34.1 17.7 29.2 17 26.1C16.4 22.9 16.6 20.6 17.4 20C18.2 19.3 19.9 20.2 21.9 22.1C23.9 24 26.7 27.6 29.5 31.5C32.3 35.4 35.7 40.6 38.7 45.2C41.7 49.9 44.9 55.2 47.5 59.4C50.2 63.6 52.7 67.6 54.4 70.2C56.2 72.8 57.6 74.6 58.3 75.1C59 75.5 59 74.7 58.5 73.1C58 71.5 56.8 68.5 55.4 65.3C54 62 52 57.5 50.3 53.8C48.7 50.1 46.8 45.9 45.6 43.1C44.3 40.3 43.3 38 43 36.9C42.7 35.7 43 35.8 43.8 36.4C44.6 36.9 46.2 38.6 47.9 40.1C49.6 41.6 51.9 43.8 54 45.3C56.1 46.8 58.6 48.3 60.6 49.2C62.5 50.1 64.5 50.5 65.9 50.8C67.3 51 68.4 50.6 69.1 50.5C69.8 50.3 68.8 51.5 70 50C71.2 48.5 74.2 43.1 76.4 41.3C78.5 39.5 80.6 38.9 82.8 39.1C84.9 39.4 87 41.2 89.1 42.8C91.2 44.5 93.4 47.1 95.5 48.8C97.6 50.6 99.8 52.4 101.9 53.4C104 54.4 106.1 54.7 108.2 54.7C110.4 54.7 112.5 53.9 114.6 53.3C116.8 52.6 118.9 51.6 121 50.9C123.1 50.2 125.2 49.5 127.4 49.1C129.5 48.8 131.6 48.7 133.8 48.7C135.9 48.7 138 49 140.1 49.1C142.2 49.3 144.4 49.6 146.5 49.8C148.6 49.9 150.8 50 152.9 50.1C155 50.1 157.1 50.1 159.2 50.1C161.4 50.1 163.5 50 165.6 50C167.8 50 170.9 50 172 50'/%3E%3C/svg%3E");
}
.tf-hero__title::after {
  --tf-line: calc(7.8vw * 1.2); /* one line of the headline */
  content: "";
  position: absolute;
  top: var(--tf-line);
  left: 59vw;
  right: 0;
  height: var(--tf-line);
  background: currentColor;
  pointer-events: none;
  -webkit-mask:
    var(--tf-knot) left center / auto 100% no-repeat,
    linear-gradient(#000, #000) right center / calc(100% - var(--tf-line) * 1.69) calc(var(--tf-line) * 0.024) no-repeat,
    linear-gradient(#000, #000) right center / calc(var(--tf-line) * 0.09) calc(var(--tf-line) * 0.09) no-repeat;
  mask:
    var(--tf-knot) left center / auto 100% no-repeat,
    linear-gradient(#000, #000) right center / calc(100% - var(--tf-line) * 1.69) calc(var(--tf-line) * 0.024) no-repeat,
    linear-gradient(#000, #000) right center / calc(var(--tf-line) * 0.09) calc(var(--tf-line) * 0.09) no-repeat;
  animation: tf-hero-line 1.5s cubic-bezier(0.23, 1, 0.32, 1) 0.4s both;
}
@keyframes tf-hero-line { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@media (max-width: 767px) {
  .tf-hero__title::after { --tf-line: calc(12.5vw * 1.2); top: 0; left: 63vw; }
}
@media (prefers-reduced-motion: reduce) {
  .tf-hero__title::after { animation: none; }
}
