/* ===========================================================================
   Reviamo — shared stylesheet
   Page-agnostic chrome only. Page-specific systems stay inline on their page:
   index.html keeps .tl-* / .rotator / .mt-30days, about.html keeps its brand
   tick (.tick), to-do card (.todo-*) and highlighter (mark.hl). Loaded AFTER the Tailwind CDN tag, which injects its own <style>
   at runtime — so every rule here uses a custom class or an element selector
   and never tries to beat a Tailwind utility.
   =========================================================================== */

/* --------------------------------------------------------------------------
   0. Cal Sans, self-hosted
   The previous source, fonts.cdnfonts.com, returns HTTP 500 — the display font
   silently stopped loading for every visitor and headings fell back to Inter.
   This is the official file from github.com/calcom/font v1.0.0, SIL OFL-1.1
   (licence kept alongside it at assets/fonts/OFL.txt). Cal Sans ships a single
   cut, so the weight range covers every heading weight without faux-bolding.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Cal Sans';
  src: url('fonts/CalSans-SemiBold.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   1. Base
   -------------------------------------------------------------------------- */
html {
  scroll-behavior: smooth;
}

/* `clip` rather than `hidden`: both stop sideways scrolling, but `hidden` turns
   the element into a scroll container and silently breaks position:sticky in
   descendants. The explorer's chip row depends on sticky working. */
html,
body {
  overflow-x: clip;
}

/* The light page defaults live here so there is no flash before Tailwind's
   runtime pass. Dark pages override with .bg-midnight / .text-white, which win
   on specificity (0,1,0 beats an element selector's 0,0,1) regardless of order. */
body {
  font-family: 'Inter', system-ui, sans-serif;
  background: #F7F7F5;
  color: #0F172A;
  -webkit-font-smoothing: antialiased;
  /* Body sits at 500, not 400, and every size carries slight negative
     tracking — both measured off attio.com, where it is what makes the text
     read as dense and deliberate rather than default. */
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* Branded text selection, the ramp.com move: the highlight is a brand colour
   instead of the browser's default blue, so even dragging over a paragraph
   shows the palette. Theirs is their full-strength green; ours is viola at a
   30% tint on white, light enough to keep dark type legible over it (12.2:1
   against midnight) and the same on light and dark sections, because the rule
   sets BOTH background and colour — a background-only rule would leave white
   type on a light lavender block in the footer. ::-moz-selection is a separate
   rule on purpose: an unknown pseudo-element in a selector list invalidates
   the whole list, so joining them with a comma would drop both. */
::selection {
  background: #D7D3FE;
  color: #0F172A;
}

::-moz-selection {
  background: #D7D3FE;
  color: #0F172A;
}

h1,
h2,
h3,
h4,
.font-display {
  font-family: 'Cal Sans', 'Inter', sans-serif;
  letter-spacing: -0.02em;
}

/* Visible focus ring for keyboard users on every interactive element. Several
   controls use focus:outline-none for their own focus style; :focus-visible
   only fires for keyboard focus, so this never fights a mouse click. */
:focus-visible {
  outline: 2px solid #7B6BFA;
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Active nav item. Set by site.js from <body data-page> + <a data-nav>, so the
   nav block stays byte-identical across pages. */
nav a[aria-current="page"] {
  color: #25206E;
  font-weight: 600;
}

.drawer-link[aria-current="page"] {
  background: rgba(123, 107, 250, .15);
  color: #0F172A;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   1a. Mobile drawer
   The panel is three rows (logo bar, scrolling middle, call button), sized to
   the visible viewport so the button is never hidden behind a phone's browser
   bar. Services is a disclosure: the toggle's aria-expanded drives everything,
   and the height animates through grid rows, which needs no measuring.
   -------------------------------------------------------------------------- */
.drawer-panel {
  height: 100%;
  height: 100dvh;
}

.drawer-scroll {
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.drawer-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 12px 14px;
  border-radius: 14px;
  font-size: 17px;
  font-weight: 500;
  line-height: 1.2;
  color: inherit;
  text-align: left;
  transition: background-color .2s ease;
}

.drawer-chevron {
  flex: none;
  color: #25206E;
  transition: transform .32s cubic-bezier(.16, 1, .3, 1);
}

.drawer-toggle[aria-expanded="true"] {
  background: rgba(123, 107, 250, .12);
  font-weight: 600;
}

.drawer-toggle[aria-expanded="true"] .drawer-chevron { transform: rotate(180deg); }

/* on a page that belongs to Services the closed toggle still shows where you are */
.drawer-toggle.is-current { font-weight: 600; }

.drawer-sub {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows .32s cubic-bezier(.16, 1, .3, 1), visibility 0s linear .32s;
}

.drawer-toggle[aria-expanded="true"] + .drawer-sub {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows .32s cubic-bezier(.16, 1, .3, 1), visibility 0s;
}

.drawer-sub-in { min-height: 0; overflow: hidden; }

.drawer-sub-box {
  margin: 6px 0 10px 14px;
  padding-left: 12px;
  border-left: 2px solid rgba(123, 107, 250, .35);
}

.drawer-label {
  padding: 14px 10px 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(15, 23, 42, .55);
}

.drawer-sublink {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 46px;
  padding: 6px 10px;
  border-radius: 12px;
  font-size: 15px;
  line-height: 1.25;
  color: rgba(15, 23, 42, .85);
  transition: background-color .2s ease;
}

.drawer-ico {
  flex: none;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: #EBE8FF;
  color: #25206E;
}

.drawer-sublink--all {
  font-weight: 600;
  color: #25206E;
}

.drawer-sublink[aria-current="page"] {
  background: rgba(123, 107, 250, .15);
  color: #0F172A;
  font-weight: 600;
}

.drawer-sublink[aria-current="page"] .drawer-ico { background: #25206E; color: #fff; }

/* clear of the iPhone home indicator */
.drawer-foot { padding-bottom: max(1.5rem, env(safe-area-inset-bottom)); }

@media (hover: hover) and (pointer: fine) {
  .drawer-link:hover,
  .drawer-sublink:hover { background: rgba(123, 107, 250, .15); }
}

.drawer-link:active,
.drawer-sublink:active { background: rgba(123, 107, 250, .2); }

/* the dark variant, for a page whose nav sits on a dark hero (unify_nav.py) */
.drawer-panel--dark .drawer-toggle[aria-expanded="true"],
.drawer-panel--dark .drawer-link[aria-current="page"],
.drawer-panel--dark .drawer-sublink[aria-current="page"] { background: rgba(255, 255, 255, .12); color: #fff; }
.drawer-panel--dark .drawer-chevron,
.drawer-panel--dark .drawer-sublink--all { color: #B3AAFF; }
.drawer-panel--dark .drawer-sublink { color: rgba(255, 255, 255, .8); }
.drawer-panel--dark .drawer-label { color: rgba(255, 255, 255, .5); }
.drawer-panel--dark .drawer-ico { background: rgba(255, 255, 255, .1); color: #D7D3FE; }
.drawer-panel--dark .drawer-sub-box { border-left-color: rgba(255, 255, 255, .15); }

@media (prefers-reduced-motion: reduce) {
  .drawer-sub,
  .drawer-toggle[aria-expanded="true"] + .drawer-sub,
  .drawer-chevron { transition: none; }
}

/* --------------------------------------------------------------------------
   1b. Background textures
   Pure CSS gradients rather than tiled PNGs: no extra request, no licence, they
   scale to any DPI, and the tint is a brand token rather than a baked-in grey.
   Keep them barely-there — they should register as paper, not as pattern.
   -------------------------------------------------------------------------- */
.tx-dots {
  background-image: radial-gradient(rgba(15, 23, 42, .08) 1px, transparent 1px);
  background-size: 22px 22px;
}

.tx-grid {
  background-image:
    linear-gradient(rgba(15, 23, 42, .045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(15, 23, 42, .045) 1px, transparent 1px);
  background-size: 46px 46px;
}

.tx-diag {
  background-image: repeating-linear-gradient(45deg,
      rgba(15, 23, 42, .035) 0 1px, transparent 1px 11px);
}

/* --------------------------------------------------------------------------
   1c. Brand imagery
   Layered backgrounds: a brand-colour scrim on top of the artwork, so text
   contrast is set here rather than depending on the image. Using
   background-image rather than an <img> keeps the artwork behind the content
   with no z-index or DOM restructuring. Paths are relative to this file.
   -------------------------------------------------------------------------- */
.img-hero {
  background-image:
    linear-gradient(100deg, #F7F7F5 0%, rgba(247, 247, 245, .94) 34%, rgba(247, 247, 245, .40) 100%),
    url('img/hero-ribbons.webp');
  background-size: cover, cover;
  background-position: center, right center;
  background-repeat: no-repeat;
}

/* On a phone the copy runs full width, so push the artwork below it and veil
   it top-down instead of left-right. */
@media (max-width: 639px) {
  .img-hero {
    background-image:
      linear-gradient(180deg, #F7F7F5 0%, rgba(247, 247, 245, .90) 42%, rgba(247, 247, 245, .55) 100%),
      url('img/hero-ribbons.webp');
    background-position: center, right bottom;
  }
}

.img-automation {
  background-image:
    linear-gradient(100deg, #25206E 0%, rgba(37, 32, 110, .93) 40%, rgba(37, 32, 110, .35) 100%),
    url('img/card-automation.webp');
  background-size: cover, cover;
  background-position: center, right center;
  background-repeat: no-repeat;
}

.img-boundary {
  background-image:
    linear-gradient(180deg, rgba(15, 23, 42, .90) 0%, rgba(15, 23, 42, .72) 40%, rgba(15, 23, 42, .96) 100%),
    url('img/card-boundary.webp');
  background-size: cover, cover;
  background-position: center, center top;
  background-repeat: no-repeat;
}

.img-cta {
  background-image:
    linear-gradient(180deg, rgba(15, 23, 42, .93) 0%, rgba(15, 23, 42, .78) 50%, rgba(15, 23, 42, .95) 100%),
    url('img/band-cta.webp');
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat;
}

/* On-dark variants for midnight / notte / viola surfaces */
.tx-dots-on-dark {
  background-image: radial-gradient(rgba(255, 255, 255, .10) 1px, transparent 1px);
  background-size: 22px 22px;
}

.tx-grid-on-dark {
  background-image:
    linear-gradient(rgba(255, 255, 255, .06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .06) 1px, transparent 1px);
  background-size: 46px 46px;
}

/* Fades a texture out towards the bottom so sections don't end on a hard edge.
   The texture moves into a pseudo-element: a mask on the element itself would
   fade the section's TEXT out too, which is exactly the bug this replaces. */
.tx-fade-b {
  position: relative;
  isolation: isolate;
  background-image: none;
}

.tx-fade-b::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
}

.tx-dots.tx-fade-b::before {
  background-image: radial-gradient(rgba(15, 23, 42, .08) 1px, transparent 1px);
  background-size: 22px 22px;
}

.tx-grid.tx-fade-b::before {
  background-image:
    linear-gradient(rgba(15, 23, 42, .045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(15, 23, 42, .045) 1px, transparent 1px);
  background-size: 46px 46px;
}

.tx-diag.tx-fade-b::before {
  background-image: repeating-linear-gradient(45deg,
      rgba(15, 23, 42, .035) 0 1px, transparent 1px 11px);
}

/* --------------------------------------------------------------------------
   2. Scroll-fill headings — each letter starts faded and gains full colour as
      the heading travels through the viewport. Fails safe: without JS the text
      stays faded but readable. Alignment comes from the parent (the homepage
      sections are left-aligned, the contact header is text-center).
   -------------------------------------------------------------------------- */
.scroll-fill .word {
  display: inline-block;
  white-space: nowrap;
}

.scroll-fill .ch {
  display: inline-block;
  color: rgba(15, 23, 42, 0.18);
  transition: color .25s ease;
}

.scroll-fill .ch.is-on {
  color: #0F172A;
}

.scroll-fill.scroll-fill--ondark .ch {
  color: rgba(255, 255, 255, 0.22);
}

.scroll-fill.scroll-fill--ondark .ch.is-on {
  color: #ffffff;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .scroll-fill .ch {
    color: #0F172A;
    transition: none;
  }

  .scroll-fill.scroll-fill--ondark .ch {
    color: #ffffff;
  }
}

/* --------------------------------------------------------------------------
   3. Brand marks
   -------------------------------------------------------------------------- */

/* Knock out baked-in white boxes in partner logos so they sit on Pietra. */
.trust-logo {
  mix-blend-mode: multiply;
}

/* Inline Reviamo logo inside a heading. The lowercase letters span ~50% of the
   image height, so 1.45em + a 0.30em nudge puts its baseline on the text's. */
.reviamo-inline {
  display: inline-block;
  height: 1.45em;
  width: auto;
  vertical-align: baseline;
  transform: translateY(0.30em);
  margin: 0 0.05em;
}

/* --------------------------------------------------------------------------
   4. Footer — midnight base with a violet glow rising from bottom-centre
   -------------------------------------------------------------------------- */
.footer-bg {
  background:
    radial-gradient(70% 80% at 50% 100%, rgba(123, 107, 250, 0.75) 0%, rgba(123, 107, 250, 0.40) 25%, rgba(37, 32, 110, 0.12) 55%, rgba(15, 23, 42, 0) 80%),
    linear-gradient(180deg, #0F172A 0%, #15123F 60%, #1F1A55 100%);
}

/* --------------------------------------------------------------------------
   5. Utilities
   -------------------------------------------------------------------------- */
.no-scrollbar::-webkit-scrollbar {
  display: none;
}

.no-scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

/* --------------------------------------------------------------------------
   5b. Marquee — infinite logo strip. Needs the content duplicated (set A + set
   B) so the -50% wrap is seamless.
   -------------------------------------------------------------------------- */
.marquee {
  display: flex;
  width: max-content;
  animation: marquee 38s linear infinite;
}

.marquee:hover {
  animation-play-state: paused;
}

@keyframes marquee {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .marquee {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   6. FAQ — native <details>, so it works with JS disabled
   -------------------------------------------------------------------------- */
.faq-item summary {
  list-style: none;
  cursor: pointer;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item[open] .faq-chevron {
  transform: rotate(180deg);
}

.faq-chevron {
  transition: transform .2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .faq-chevron {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   7. Process explorer — "See it before and after"
      State lives in hidden radio inputs, so switching works with JS disabled
      and is keyboard-navigable by default (arrow keys move between chips).
      The inputs must stay siblings of .px-chips and .px-panels for ~ to match.
      This component is also the template for the future solutions catalogue.
   -------------------------------------------------------------------------- */
/* Browsers give <fieldset> an implicit min-width:min-content, so it refuses to
   shrink below its widest unbroken line and drags the whole panel off the right
   edge on mobile — invisibly, because html/body clip the overflow. min-width:0
   is the fix; the grouping semantics are what the fieldset is here for. */
.px-explorer {
  min-width: 0;
}

.px-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* The row used to stick below the navbar so the process stayed switchable
   however far down the panel you had scrolled. It read as a second, unrelated
   navigation bar pinned under the real one — the utility was not worth that, so
   it scrolls with its section. The translucent background and blur are gone
   with it; the row now sits on the page like any other content. */
.px-chips {
  display: flex;
  gap: .5rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Bleed to the viewport edge on mobile so the row reads as scrollable. */
  margin-inline: -1.25rem;
  padding-inline: 1.25rem;
  padding-block: .625rem;
}

@media (min-width: 640px) {
  .px-chips {
    margin-inline: 0;
    padding-inline: 0;
    flex-wrap: wrap;
  }
}

.px-chip {
  scroll-snap-align: start;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  /* 44px minimum tap target */
  min-height: 44px;
  padding: 0 1.125rem;
  border-radius: 9999px;
  background: #fff;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .10);
  color: rgba(15, 23, 42, .70);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
}

.px-chip .px-dot {
  width: .5rem;
  height: .5rem;
  border-radius: 9999px;
  background: currentColor;
  opacity: .45;
  flex: none;
}

/* All six panels share one grid cell and crossfade. The previous version used
   display:none/block, which re-flowed the page on every switch — measured at a
   62px jump, and with auto-advance that fired every 9 seconds under the
   reader. The container now sits at the tallest panel's height and never
   moves. */
.px-panels {
  display: grid;
}

.px-panel {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(6px);
  transition: opacity .35s ease, transform .35s cubic-bezier(.2, .8, .2, 1), visibility .35s;
}


/* Selected chip + matching panel. One pair of rules per process. */
#px-1:checked~.px-chips [for="px-1"],
#px-2:checked~.px-chips [for="px-2"],
#px-3:checked~.px-chips [for="px-3"],
#px-4:checked~.px-chips [for="px-4"],
#px-5:checked~.px-chips [for="px-5"],
#px-6:checked~.px-chips [for="px-6"] {
  background: #25206E;
  color: #fff;
  box-shadow: inset 0 0 0 1px #25206E;
}

#px-1:checked~.px-chips [for="px-1"] .px-dot,
#px-2:checked~.px-chips [for="px-2"] .px-dot,
#px-3:checked~.px-chips [for="px-3"] .px-dot,
#px-4:checked~.px-chips [for="px-4"] .px-dot,
#px-5:checked~.px-chips [for="px-5"] .px-dot,
#px-6:checked~.px-chips [for="px-6"] .px-dot {
  background: #7B6BFA;
  opacity: 1;
}

#px-1:checked~.px-panels [data-px="1"],
#px-2:checked~.px-panels [data-px="2"],
#px-3:checked~.px-panels [data-px="3"],
#px-4:checked~.px-panels [data-px="4"],
#px-5:checked~.px-panels [data-px="5"],
#px-6:checked~.px-panels [data-px="6"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
}

/* Keyboard focus lands on the hidden input — surface it on its chip. */
#px-1:focus-visible~.px-chips [for="px-1"],
#px-2:focus-visible~.px-chips [for="px-2"],
#px-3:focus-visible~.px-chips [for="px-3"],
#px-4:focus-visible~.px-chips [for="px-4"],
#px-5:focus-visible~.px-chips [for="px-5"],
#px-6:focus-visible~.px-chips [for="px-6"] {
  outline: 2px solid #7B6BFA;
  outline-offset: 2px;
}

/* Step counters inside a panel */
.px-step {
  display: flex;
  align-items: flex-start;
  gap: .875rem;
}

.px-num {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'Cal Sans', 'Inter', sans-serif;
  font-size: 13px;
  line-height: 1;
}

/* FAQ sits between two dense sections and was the one plain stretch of page.
   A light silk band lifts it without competing with the questions. */
.img-faq {
  background-image:
    linear-gradient(180deg, #F7F7F5 0%, rgba(247, 247, 245, .90) 45%, rgba(247, 247, 245, .70) 100%),
    url('img/band-faq.webp');
  background-size: cover, cover;
  background-position: center, center bottom;
  background-repeat: no-repeat;
}

/* --------------------------------------------------------------------------
   8. Hover — enhancement only. Roughly 70% of visits are on a phone where
   none of this fires, so nothing here may be the only affordance for an
   action; it exists to make the page feel alive on a pointer device.
   -------------------------------------------------------------------------- */
.px-chip:hover {
  background: rgba(123, 107, 250, .10);
  color: #0F172A;
  box-shadow: inset 0 0 0 1px rgba(123, 107, 250, .45);
}

/* The selected chip's rules carry an id, so they already outrank the hover
   above and the active state survives being pointed at. */

.px-chip .px-dot {
  transition: opacity .18s ease, background-color .18s ease;
}

.px-chip:hover .px-dot {
  opacity: .8;
}

/* The explorer's outcome column lifts slightly when the panel is pointed at,
   so the "after" half reads as the payoff. */
.px-panel .px-after {
  transition: transform .3s cubic-bezier(.2, .8, .2, 1), box-shadow .3s ease;
}

.px-panel:hover .px-after {
  transform: translateY(-3px);
  box-shadow: 0 18px 36px -20px rgba(37, 32, 110, .55);
}

/* Anything that moves on hover stops moving when the visitor asked for less. */
@media (prefers-reduced-motion: reduce) {

  .px-panel .px-after,
  .px-chip,
  .px-chip .px-dot {
    transition: none;
  }

  .px-panel:hover .px-after {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   9. Sticky card stack
   Measured from clay.com: pure position:sticky, no JS and no GSAP driving it.
   Each card overlaps the next by 3rem (negative margin paid back as padding)
   so the page background never shows through the rounded top corner of the
   card sliding up behind it — opaque backgrounds do the occluding, no z-index
   needed. Desktop only: pinning cards on a phone fights the scroll, and Clay
   disables it below lg for the same reason.
   -------------------------------------------------------------------------- */
@media (min-width: 1024px) {
  .stack {
    border-radius: 40px;
    /* `clip`, not `hidden` — `hidden` would make this a scroll container and
       kill the sticky behaviour of its own children. */
    overflow: clip;
  }

  .stack > .stack-layer {
    position: sticky;
    /* clears the floating navbar */
    top: 92px;
  }

  .stack > .stack-layer > .stack-card {
    /* Each card needs to hold the viewport long enough to register as pinned;
       Clay's are ~771px. Without this they flick past. */
    min-height: 34rem;
    display: flex;
    align-items: center;
    margin-bottom: -3rem;
    padding-bottom: 3rem;
    border-radius: 40px 40px 0 0;
  }

  .stack > .stack-layer:last-child > .stack-card {
    margin-bottom: 0;
    border-radius: 40px;
  }
}

/* A flat UI panel built in DOM rather than shipped as a screenshot — crisp at
   any zoom, readable to screen readers, and a few hundred bytes instead of a
   few hundred kilobytes. */
.mock {
  /* attio.com's full five-step ramp. Blur and offset roughly double at each
     step while opacity climbs only .024 → .04, which is what makes it read as
     one soft elevation rather than a stack of separate shadows. An earlier
     version here had only three of the five and visibly jumped from a 6px blur
     straight to 28px. */
  box-shadow:
    rgba(11, 13, 24, .06) 0 0 0 1px,
    rgba(11, 13, 24, .024) 0 1px 2px,
    rgba(11, 13, 24, .03) 0 3px 6px,
    rgba(11, 13, 24, .035) 0 8px 14px,
    rgba(11, 13, 24, .04) 0 16px 28px;
}

/* --------------------------------------------------------------------------
   10. Unfolding arrow
   Lifted from cal.com, where it is their one memorable hover: the arrow sits
   folded as a stub, then the tail grows and the head slides right. Measured
   there at ~400ms settling with a 1.5% overshoot; their site drives it with JS
   inline styles because it is built in Framer — in plain CSS it is four rules.
   -------------------------------------------------------------------------- */
.arw-tail {
  transform: scaleX(.22);
  transform-origin: 5px 12px;
  transition: transform .4s cubic-bezier(.16, 1, .3, 1);
}

.arw-head {
  transform: translateX(-5px);
  transition: transform .4s cubic-bezier(.16, 1, .3, 1);
}

a:hover .arw-tail,
button:hover .arw-tail,
.group:hover .arw-tail {
  transform: scaleX(1);
}

a:hover .arw-head,
button:hover .arw-head,
.group:hover .arw-head {
  transform: translateX(0);
}

/* Keyboard users get it too. */
a:focus-visible .arw-tail,
button:focus-visible .arw-tail {
  transform: scaleX(1);
}

a:focus-visible .arw-head,
button:focus-visible .arw-head {
  transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {

  .arw-tail,
  .arw-head {
    transition: none;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   9b. The stack on mobile
   Pinning is impossible here: the cards measure 692–916px against a 667–812px
   viewport, so a card pinned at a fixed `top` would have its own bottom parked
   below the fold and out of reach. That is why clay.com disables the effect
   below desktop entirely.
   Instead of giving phones nothing — and roughly 70% of visits are phones —
   the cards keep the same overlap and rounded shoulders, and the outgoing card
   recedes as it leaves. That reads as a deck without depending on height.
   -------------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .stack {
    border-radius: 28px;
    overflow: clip;
  }

  .stack > .stack-layer > .stack-card {
    margin-bottom: -1.25rem;
    padding-bottom: calc(1.75rem + 1.25rem);
    border-radius: 28px 28px 0 0;
  }

  .stack > .stack-layer:last-child > .stack-card {
    margin-bottom: 0;
    border-radius: 28px;
  }

  /* Progressive enhancement: where scroll-driven animations exist, the card
     scales back and dims as it exits the top. Everywhere else the overlap
     alone still reads correctly. */
  @supports (animation-timeline: view()) {
    .stack > .stack-layer {
      transform-origin: 50% 0;
      animation: stack-recede linear both;
      animation-timeline: view();
      animation-range: exit-crossing 0% exit-crossing 100%;
    }

    .stack > .stack-layer:last-child {
      animation: none;
    }

    @keyframes stack-recede {
      to {
        transform: scale(.94);
        opacity: .55;
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .stack > .stack-layer {
      animation: none;
    }
  }
}

/* --------------------------------------------------------------------------
   11. Live mockups
   cal.com's fake product panels are not decoration — each one quietly cycles
   its own values every couple of seconds, and that, not hover, is what makes
   their page feel alive. These panels do the same: rows complete in sequence,
   bars fill on reveal.
   -------------------------------------------------------------------------- */
[data-row] {
  transition: opacity .35s ease;
  opacity: .45;
}

[data-row].is-done {
  opacity: 1;
}

.mock-dot {
  background: rgba(15, 23, 42, .18);
  transition: background-color .35s ease, box-shadow .35s ease;
}

[data-row].is-done[data-state="ok"] .mock-dot {
  background: #10b981;
}

[data-row].is-done[data-state="flag"] .mock-dot {
  background: #f59e0b;
  box-shadow: 0 0 0 3px rgba(245, 158, 11, .18);
}

[data-row].is-done[data-state="idle"] .mock-dot {
  background: rgba(15, 23, 42, .28);
}

.mock-bar {
  transition: width 1.1s cubic-bezier(.16, 1, .3, 1);
}

/* With motion turned down the panels simply render finished. */
@media (prefers-reduced-motion: reduce) {

  [data-row],
  .mock-dot,
  .mock-bar {
    transition: none;
  }

  [data-row] {
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
   12. FAQ open/close animation
   A native <details> snaps open. ::details-content is the one way to animate it
   without JavaScript; `interpolate-size` is what lets the height reach `auto`
   rather than a guessed pixel value. Browsers without it simply snap, as before.
   -------------------------------------------------------------------------- */
:root {
  interpolate-size: allow-keywords;
}

@supports selector(::details-content) {
  .faq-item::details-content {
    block-size: 0;
    overflow: hidden;
    transition:
      block-size .3s cubic-bezier(.2, .8, .2, 1),
      content-visibility .3s allow-discrete;
  }

  .faq-item[open]::details-content {
    block-size: auto;
  }

  @media (prefers-reduced-motion: reduce) {
    .faq-item::details-content {
      transition: none;
    }
  }
}

/* --------------------------------------------------------------------------
   13. Section eyebrow
   Measured off attio.com's section badges ("Build to scale", "Customer
   stories"): 24px tall, 8px radius, 6px of side padding, 14px/20px Inter at
   500 with -0.14px tracking, sentence case, no shadow and no bullet. The
   radius is the point — at 8px on a 24px box the corner is visibly a corner,
   where the old 9999px made a capsule, and a capsule reads as a status chip
   rather than a label. Their palette is a mid blue on a 95%-light tint of the
   same hue; these are those two colours rotated onto the Reviamo hue (247deg),
   keeping attio's saturation and lightness, which is why they sit at 7.8:1 on
   the tint without being tuned by eye.
   On 2026-10-22 the badge grew by a third (32px, 16px type at 600, 10px
   sides and radius) because at attio's size it read as small print next to
   our much bigger headings; the proportions are the same. At that size a long
   label no longer fits a narrow panel on a phone, and a badge that refuses to
   wrap widens its grid column past the screen, so it wraps instead: one line
   is still exactly 32px, a second line grows the badge.
   -------------------------------------------------------------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  max-width: 100%;
  padding: 4px .625rem;
  border-radius: 10px;
  background: #EBE8FF;
  font-size: 16px;
  line-height: 24px;
  font-weight: 600;
  letter-spacing: -0.16px;
  text-transform: none;
  color: #3624C2;
  /* Inside a `flex flex-col` card (the related-solution cards) an inline-flex
     child is blockified to flex and then stretched across the cross axis, which
     turned the badge into a full-width bar. `start` on both axes pins it in a
     flex or a grid parent and does nothing in normal flow. */
  align-self: start;
  justify-self: start;
}

/* On notte and midnight panels the tint has nothing to sit on, so the block
   becomes a lift of the surface itself and the type takes attio's dark-mode
   badge colour at our hue. */
.eyebrow--ondark {
  background: rgba(255, 255, 255, .12);
  color: #CEC8FF;
}

/* --------------------------------------------------------------------------
   13b. Stacking table
   The markup stays a real <table> with <th scope="row"> — that is what makes a
   single row readable as a self-contained fact, by a screen reader and by a
   retrieval engine alike. Below 640px it renders as labelled blocks instead:
   three columns on a 375px screen means an undiscoverable sideways scroll and
   two words per line, and mobile is most of the traffic. Each cell carries its
   column name in data-label, which the pseudo-element prints once stacked.
   -------------------------------------------------------------------------- */
@media (max-width: 639px) {
  .tbl-stack thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .tbl-stack,
  .tbl-stack tbody,
  .tbl-stack tr,
  .tbl-stack th,
  .tbl-stack td {
    display: block;
    width: auto;
    white-space: normal;
  }

  /* beats the min-width the wide layout needs */
  .tbl-stack {
    min-width: 0;
  }

  .tbl-stack tr {
    padding: 1.125rem 1.25rem;
  }

  .tbl-stack th[scope="row"] {
    padding: 0 0 .625rem;
    font-size: 15px;
  }

  .tbl-stack td {
    padding: 0;
  }

  .tbl-stack td + td {
    margin-top: .625rem;
  }

  .tbl-stack td::before {
    content: attr(data-label);
    display: block;
    margin-bottom: .125rem;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(15, 23, 42, .45);
  }
}

/* --------------------------------------------------------------------------
   13c. Scroll-tilt stage
   The aceternity "container scroll" effect, rebuilt without React or
   framer-motion: a card that starts pitched back and settles flat as the page
   scrolls, with the heading drifting up slightly faster. The original is a
   dark #222 slab with a grey bezel; here the frame is midnight and the screen
   is pietra, so it reads as the brand rather than as a borrowed component.

   The transform lives in custom properties set by site.js, so the CSS holds the
   resting state and the fallbacks: no JS, reduced motion, or a browser that
   never fires scroll, and the card simply sits flat and correct.
   -------------------------------------------------------------------------- */
.tilt-stage {
  perspective: 1400px;
  perspective-origin: 50% 0%;
}

.tilt-card {
  transform-origin: 50% 0%;
  transform: rotateX(var(--tilt-x, 0deg)) scale(var(--tilt-scale, 1));
  border-radius: 28px;
  background: #0F172A;
  padding: .5rem;
  box-shadow:
    0 9px 20px rgba(15, 23, 42, .10),
    0 37px 37px rgba(15, 23, 42, .07),
    0 84px 50px rgba(15, 23, 42, .04),
    0 149px 60px rgba(15, 23, 42, .02);
  will-change: transform;
}

@media (min-width: 640px) {
  .tilt-card {
    border-radius: 34px;
    padding: .75rem;
  }
}

.tilt-screen {
  border-radius: 20px;
  background: #F7F7F5;
  overflow: hidden;
}

@media (min-width: 640px) {
  .tilt-screen {
    border-radius: 26px;
  }
}

.tilt-head {
  transform: translateY(var(--tilt-head, 0));
  will-change: transform;
}

/* A visitor who asked the system for less movement gets none of this, and the
   card is upright rather than pitched — the resting state has to be the
   readable one, not the dramatic one. */
@media (prefers-reduced-motion: reduce) {

  .tilt-card,
  .tilt-head {
    transform: none;
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   13d. Catalogue detail overlay
   Measured off stripe.com's bento cards: the whole card is the trigger, not a
   32px icon (so the tap target is the card), and the scrim is a pale tint —
   theirs rgba(229,237,245,.9) — rather than the usual black wash, which is why
   it reads as light rather than modal.

   The state is :target, not JavaScript. That means the URL carries it, a detail
   can be linked to and shared, the browser's Back button closes it, and it
   works with JS switched off — none of which stripe's own version does, because
   theirs never touches the URL. site.js only adds Escape and focus handling.
   -------------------------------------------------------------------------- */
.cat-dialog {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  justify-items: center;
  align-content: start;
  padding: 1rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(235, 232, 255, .92);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity .25s ease,
    visibility .25s;
}

.cat-dialog:target {
  opacity: 1;
  visibility: visible;
}

/* A link covering the whole scrim: clicking off the panel closes it, and it is
   a real link so it works before JS loads. */
.cat-scrim {
  position: fixed;
  inset: 0;
}

.cat-panel {
  position: relative;
  z-index: 1;
  width: min(60rem, 100%);
  margin: clamp(1rem, 7vh, 5rem) 0 3rem;
  border-radius: 24px;
  background: #fff;
  box-shadow:
    rgba(28, 29, 31, .10) 0 0 0 1px,
    rgba(28, 29, 31, .04) 0 4px 8px -2px,
    rgba(28, 29, 31, .06) 0 16px 32px -8px,
    rgba(28, 29, 31, .08) 0 40px 72px -12px;
  transform: translateY(10px) scale(.99);
  transition: transform .25s cubic-bezier(.2, .8, .2, 1);
}

.cat-dialog:target .cat-panel {
  transform: none;
}

.cat-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: rgba(15, 23, 42, .045);
  color: #25206E;
  transition: background-color .3s ease-in-out;
}

.cat-close:hover,
.cat-close:focus-visible {
  background: rgba(123, 107, 250, .16);
  transition-duration: .05s;
}

/* Body scroll is locked by site.js while a dialog is open; without JS the
   overlay simply covers the page and scrolls itself. */
body.cat-open {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {

  .cat-dialog,
  .cat-panel {
    transition: none;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   13e. Card lift
   Replaces `hover:-translate-y-1 hover:shadow-xl hover:ring-midnight/20`, which
   had three faults, all of them measured against clerk.com:

   1. The translate moved the card 4px. In a grid that shimmers the gaps between
      neighbours and repaints the whole card; worse, it contradicts the shadow —
      `shadow-xl` reads as "lifted about 20px" while the transform says 4px.
      Clerk never translates a card and still reads as a lift, because the
      shadow alone carries it.
   2. The hover ring stacked a SECOND hairline on top of the one `ring-1`
      already draws. The fix is to raise the alpha of the layer that is already
      there, not to add another.
   3. `duration-300 hover:duration-50` only swapped speed. What actually stops
      the flicker when a cursor crosses between cards is a delay on the way OUT
      — 150ms here, 0 on hover. And 50ms in was too fast to read against a
      300ms exit: it snapped, then oozed. Both directions are 200ms now, which
      is what clerk uses on its cards.

   The layer STRUCTURE is identical in both states; only the values move. That
   is the whole discipline.
   -------------------------------------------------------------------------- */
.lift {
  box-shadow:
    rgba(15, 23, 42, .08) 0 0 0 1px,
    rgba(15, 23, 42, .04) 0 1px 2px 0,
    rgba(15, 23, 42, .04) 0 2px 6px -2px,
    rgba(15, 23, 42, .04) 0 6px 12px -4px;
  transition:
    background-color .2s cubic-bezier(.4, 0, .2, 1),
    box-shadow .2s cubic-bezier(.4, 0, .2, 1);
  transition-delay: .15s;
}

.lift:hover,
.lift:focus-visible,
.lift:focus-within {
  transition-delay: 0s;
  box-shadow:
    rgba(15, 23, 42, .14) 0 0 0 1px,
    rgba(15, 23, 42, .05) 0 2px 4px 0,
    rgba(15, 23, 42, .08) 0 6px 14px -4px,
    rgba(15, 23, 42, .10) 0 14px 26px -8px;
}

/* On the filled cards — notte, midnight, viola — a shadow in near-black is
   invisible against the fill, so those carry the lift in a wider, softer
   ambient layer instead of a hairline. */
.lift--solid {
  box-shadow:
    rgba(15, 23, 42, .10) 0 2px 8px -2px,
    rgba(15, 23, 42, .10) 0 8px 18px -6px;
}

.lift--solid:hover,
.lift--solid:focus-visible,
.lift--solid:focus-within {
  box-shadow:
    rgba(15, 23, 42, .14) 0 4px 12px -2px,
    rgba(15, 23, 42, .18) 0 18px 34px -10px;
}

@media (prefers-reduced-motion: reduce) {
  .lift {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   14. Section rule with crosshair end-caps
   The mechanism, measured off cal.com: a full-bleed 1px line, then an OPAQUE
   square the colour of the page background carrying the "+" as a background
   SVG, painted on top so it punches a hole through the line. The caps land on
   the container edges, so every rule reads as a crosshair on the page frame.
   -------------------------------------------------------------------------- */
.rule {
  position: relative;
  height: 32px;
}

.rule::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 15px;
  height: 1px;
  background: rgba(15, 23, 42, .07);
}

.rule-inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  height: 28px;
  margin: 0 auto;
  max-width: 80rem;
  padding: 0 1.25rem;
}

.rule-cap {
  flex: none;
  width: 24px;
  height: 24px;
  background-color: #F7F7F5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 5v14M5 12h14' fill='none' stroke='rgba(15,23,42,0.18)' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  background-size: 100% 100%;
}

.rule-line {
  flex: 1;
  height: 1px;
  background: rgba(15, 23, 42, .14);
}

/* --------------------------------------------------------------------------
   15. Countdown under the selected chip
   The explorer advances itself every 9s with nothing on screen saying so. This
   is attio's trick: an origin-left scaleX fill under the active chip that runs
   for exactly the dwell time, so the switch is announced rather than sprung.
   Only drawn while the carousel is actually running.
   -------------------------------------------------------------------------- */
.px-chip {
  position: relative;
  overflow: hidden;
}

.px-chip>* {
  position: relative;
  z-index: 1;
}

.px-chip::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .20);
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}

@keyframes px-countdown {
  from {
    transform: scaleX(0);
  }

  to {
    transform: scaleX(1);
  }
}

.px-explorer.is-auto #px-1:checked~.px-chips [for="px-1"]::after,
.px-explorer.is-auto #px-2:checked~.px-chips [for="px-2"]::after,
.px-explorer.is-auto #px-3:checked~.px-chips [for="px-3"]::after,
.px-explorer.is-auto #px-4:checked~.px-chips [for="px-4"]::after,
.px-explorer.is-auto #px-5:checked~.px-chips [for="px-5"]::after,
.px-explorer.is-auto #px-6:checked~.px-chips [for="px-6"]::after {
  animation: px-countdown 9s linear forwards;
}

@media (prefers-reduced-motion: reduce) {
  .px-chip::after {
    animation: none !important;
  }
}

/* A truncated row label is white-space:nowrap, which gives it a min-content
   width of the whole string. As a flex item that means it cannot shrink, and
   on a phone it drags its grid column past the viewport. min-width:0 lets the
   ellipsis actually happen. */
[data-row]>.flex-1 {
  min-width: 0;
}

/* --------------------------------------------------------------------------
   16. Services mega-menu
   Measured off attio.com's nav dropdown: a 16px-radius panel on a 95%-opaque
   white with backdrop-blur(24px), and a seven-step shadow whose first layer is
   a 1px ring drawn as a shadow rather than a border, so it costs no layout.
   Opacity climbs only .02 -> .06 across the ramp, which is why it reads as one
   soft elevation instead of a stack.
   -------------------------------------------------------------------------- */
/* Deliberately NOT the positioning context: centring the panel on the trigger
   pushed it off the left edge at 1024px and below, because the trigger sits
   left of centre. The panel anchors to the nav bar instead (which carries
   `relative`), so it is centred on a box that is always fully on screen. */
.mm {
  position: static;
}

.mm-trigger {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
}

.mm-chevron {
  transition: transform .2s cubic-bezier(.2, .8, .2, 1);
}

.mm[data-open] .mm-chevron {
  transform: rotate(180deg);
}

.mm-panel {
  position: absolute;
  top: 100%;
  left: 50%;
  z-index: 60;
  margin-top: .875rem;
  width: min(26rem, calc(100vw - 3rem));
  transform: translateX(-50%) translateY(-6px) scale(.985);
  transform-origin: top center;
  border-radius: 16px;
  /* Opaque, not glass. At 95% the page behind still came through: a sample of
     the open panel found 409 distinct shades where there should be one, the
     dominant white covering only 23% of it, and a ghost as dark as #CBCBCB —
     which is the h1 underneath, too large for a 24px blur to break up. The
     shadow ramp below is what separates the panel from the page; it does not
     need transparency to do that, and a menu has to be read, not admired.
     backdrop-filter goes with it: behind an opaque fill it paints nothing and
     only costs a compositing layer. */
  background: #fff;
  box-shadow:
    rgba(28, 29, 31, .10) 0 0 0 1px,
    rgba(28, 29, 31, .05) 0 1px 2px 0,
    rgba(28, 29, 31, .02) 0 2px 4px -1px,
    rgba(28, 29, 31, .03) 0 4px 8px -2px,
    rgba(28, 29, 31, .04) 0 8px 16px -4px,
    rgba(28, 29, 31, .05) 0 16px 32px -8px,
    rgba(28, 29, 31, .06) 0 32px 64px -8px;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity .18s ease,
    transform .18s cubic-bezier(.2, .8, .2, 1),
    visibility .18s;
}

/* Two groups — Capabilities and Solutions — need twice the panel. The width is
   still clamped to the viewport, and the menu only exists from 768px up
   (below that the drawer takes over), so the narrowest real case is two
   360px columns. */
.mm-panel--wide {
  width: min(46rem, calc(100vw - 3rem));
  display: grid;
  grid-template-columns: 1fr 1fr;
}

/* Full-width row across the bottom of the panel — the way attio hangs a
   "browse everything" link under its groups. Spans both columns. */
.mm-all {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin: 0 1rem 1rem;
  padding: .75rem 1rem;
  border-radius: 12px;
  background: rgba(15, 23, 42, .035);
  font-size: 14px;
  font-weight: 600;
  color: #25206E;
  transition: background-color .3s ease-in-out;
}

.mm-all:hover,
.mm-all:focus-visible {
  background: rgba(123, 107, 250, .14);
  transition-duration: .05s;
}

.mm-col--alt {
  border-left: 1px solid rgba(15, 23, 42, .08);
}

.mm[data-open] .mm-panel {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0) scale(1);
}

.mm-col {
  padding: 1rem;
}

.mm-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(15, 23, 42, .45);
  padding-inline: .5rem;
}

/* attio's signature: 300ms to fade out, 50ms to come in — hover snaps on and
   releases slowly. */
.mm-item {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: .5rem;
  border-radius: 12px;
  transition: background-color .3s ease-in-out;
}

.mm-item:hover,
.mm-item:focus-visible {
  background: rgba(15, 23, 42, .045);
  transition-duration: .05s;
}

.mm-plate {
  flex: none;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 13px;
  background: #F7F7F5;
  color: #25206E;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .08);
}

.mm-link {
  display: block;
  padding: .5rem;
  border-radius: 10px;
  font-size: 14px;
  color: rgba(15, 23, 42, .8);
  transition: background-color .3s ease-in-out, color .3s ease-in-out;
}

.mm-link:hover,
.mm-link:focus-visible {
  background: rgba(15, 23, 42, .045);
  color: #0F172A;
  transition-duration: .05s;
}

@media (prefers-reduced-motion: reduce) {

  .mm-panel,
  .mm-chevron,
  .mm-item,
  .mm-link {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Call time picker inside the contact forms (site.js 7b)
   A row of days that scrolls sideways on a phone, then the day's times as a
   grid of 44px tap targets. Pietra chips on the white form card, like the
   inputs above them; the chosen day is notte, the chosen time viola.
   -------------------------------------------------------------------------- */
.slot-picker {
  min-width: 0;
  margin-left: 0;
  margin-right: 0;
  padding: 0;
  border: 0;
}

.slot-picker legend { padding: 0; }

.slot-note {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.5;
  color: rgba(15, 23, 42, .7);
}

.slot-days {
  display: flex;
  /* width 0 + min-width 100%: the row fills the form but adds nothing to its
     intrinsic width. Without it fifteen day chips (about 1000px) widened the
     grid column holding the form, and the whole contact page with it. */
  width: 0;
  min-width: 100%;
  gap: 8px;
  margin-top: 12px;
  padding: 2px 2px 6px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.slot-days::-webkit-scrollbar { display: none; }

/* A mouse wheel cannot scroll sideways, so with a mouse the days wrap instead. */
@media (hover: hover) and (pointer: fine) {
  .slot-days {
    flex-wrap: wrap;
    overflow: visible;
  }
}

.slot-day {
  flex: none;
  width: 62px;
  padding: 9px 0 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  border-radius: 16px;
  background: #F7F7F5;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .1);
  color: #0F172A;
  scroll-snap-align: start;
  transition: background-color .2s ease, color .2s ease, box-shadow .2s ease;
}

.slot-day span {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(15, 23, 42, .6);
}

.slot-day strong {
  font-family: 'Cal Sans', 'Inter', sans-serif;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.15;
}

.slot-day[aria-pressed="true"] {
  background: #25206E;
  box-shadow: none;
  color: #fff;
}

.slot-day[aria-pressed="true"] span { color: rgba(255, 255, 255, .72); }

.slot-times {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px;
}

/* until a day is tapped there are no times to show */
.slot-times[hidden] { display: none; }

@media (min-width: 640px) {
  .slot-times { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

.slot-time {
  min-height: 44px;
  border-radius: 12px;
  background: #F7F7F5;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .1);
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #0F172A;
  transition: background-color .2s ease, box-shadow .2s ease;
}

.slot-time[aria-pressed="true"] {
  background: #7B6BFA;
  box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
  .slot-day:hover,
  .slot-time:hover { box-shadow: inset 0 0 0 1.5px #7B6BFA; }
  .slot-day[aria-pressed="true"]:hover,
  .slot-time[aria-pressed="true"]:hover { box-shadow: none; }
}

.slot-chosen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: 14px;
  background: #EBE8FF;
  font-size: 14px;
  line-height: 1.4;
  color: #25206E;
}

.slot-chosen[hidden] { display: none; }

.slot-chosen span { font-weight: 600; }

.slot-nowrap { white-space: nowrap; }

.slot-chosen button {
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .slot-day,
  .slot-time { transition: none; }
}

/* --------------------------------------------------------------------------
   Language switch (EN | IT) in the nav bar, every breakpoint. The current
   language is a filled notte pill; the other one is a link to the same page
   in that language. 36px tall on touch screens, a little slimmer with a mouse.
   -------------------------------------------------------------------------- */
.lang-switch {
  display: inline-flex;
  align-items: center;
  flex: none;
  padding: 3px;
  border-radius: 999px;
  background: rgba(15, 23, 42, .06);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  line-height: 1;
}

.lang-switch > * {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 34px;
  padding: 0 9px;
  border-radius: 999px;
}

.lang-switch .lang-on { background: #25206E; color: #fff; }
.lang-switch .lang-off { color: rgba(15, 23, 42, .7); transition: color .2s ease, background-color .2s ease; }

@media (hover: hover) and (pointer: fine) {
  .lang-switch > * { height: 30px; }
  .lang-switch .lang-off:hover { color: #25206E; background: #fff; }
}

/* The Italian-version hint: a small, dismissible bar for visitors whose browser
   speaks Italian but who landed on an English page (site.js 10). */
.lang-hint {
  position: fixed;
  z-index: 45;
  left: 12px;
  right: 12px;
  bottom: 84px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  max-width: 360px;
  padding: 10px 10px 10px 16px;
  border-radius: 16px;
  background: #25206E;
  color: #fff;
  box-shadow: 0 18px 40px -18px rgba(15, 23, 42, .6);
  font-size: 14px;
}

@media (min-width: 768px) {
  .lang-hint { left: 24px; right: auto; bottom: 24px; }
}

.lang-hint a { font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.lang-hint button { width: 32px; height: 32px; border-radius: 999px; font-size: 18px; line-height: 1; color: rgba(255, 255, 255, .8); }
.lang-hint[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Long button labels on a phone. Buttons carry whitespace-nowrap so a label
   never breaks on a desktop, but some Italian labels ("Prenoti una consulenza
   gratuita") are wider than a 375px column: unbroken they widened the form
   card and, through the grid, the whole page. Below 640px they may wrap.
   -------------------------------------------------------------------------- */
@media (max-width: 639px) {
  main a.whitespace-nowrap,
  main button.whitespace-nowrap,
  form [data-submit] {
    white-space: normal;
    text-align: center;
  }
}
