/* ============================================================================
   Hallie — landing
   Layout copied from dub.co/home, measured on the live page: every section
   wraps its content in a 1080 px box with 1px side borders, and the horizontal
   rules run the full width of the viewport. That crossing is the whole grid.
   ========================================================================== */

@font-face {
  font-family: 'Instrument Sans';
  src: url('../fonts/instrument-sans-latin-wght-normal.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  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;
}

:root {
  interpolate-size: allow-keywords;
  --ink: #171717;
  --ink-strong: #0a0a0a;
  --body: #525252;
  --muted: #737373;
  --faint: #a3a3a3;
  --line: #e5e5e5;
  --hairline: #f0f0f0;
  --panel: #fafafa;
  --page: #ffffff;

  --accent: #00a63e;          /* the SaaS accent — never carries text */
  --accent-ink: #008236;      /* filled buttons on light: 4.95:1 with white */
  --accent-bright: #2ec26b;   /* on the near-black block */
  --accent-200: #86efac;
  --accent-400: #4ade80;
  --accent-900: #052e16;

  --dark: #080a09;
  --dark-line: #2a2a2a;
  --dark-field: #101211;

  --grid-width: 1080px;
  --gutter: 24px;

  /* The single curve dub uses for every entrance on the page. */
  --ease: cubic-bezier(.16, 1, .3, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.77, 0, .175, 1);

  --radius: 8px;
  --radius-lg: 12px;
  --shadow-card: 0 24px 60px -34px rgba(10, 10, 10, .26);
}

@keyframes slide-up-fade {
  from { opacity: 0; transform: translateY(var(--offset, 2px)); }
  to { opacity: 1; transform: none; }
}
@keyframes slide-left-fade {
  from { opacity: 0; transform: translateX(var(--offset, 2px)); }
  to { opacity: 1; transform: none; }
}
/* Same movement without the opacity: where an element's opacity carries state
   afterwards, animating it and holding the result with `fill: both` would pin it
   for good — an animation outranks a normal declaration. */
@keyframes slide-left {
  from { transform: translateX(var(--offset, 2px)); }
  to { transform: none; }
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* the sticky header must not sit on the heading an anchor lands on */
  scroll-padding-top: 88px;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }

a { color: inherit; text-decoration: none; }

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }

:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 18px;
  background: var(--page);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 500;
}
.skip:focus { left: 12px; top: 12px; }

/* --- the repeated frame ------------------------------------------------- */

.band { border-top: 1px solid var(--line); background: var(--page); }
.band--tint { background: var(--panel); }
.band--dark { background: var(--dark); }

.frame {
  width: 100%;
  max-width: var(--grid-width);
  margin: 0 auto;
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
}
.band--dark .frame { border-color: var(--dark-line); }

.pad { padding: 48px var(--gutter); }

/* --- type --------------------------------------------------------------- */

.eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
  color: var(--ink-strong);
}
.eyebrow i {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex: none;
  border: 1px solid rgba(0, 0, 0, .05);
  border-radius: 4px;
  color: var(--accent-900);
  filter: drop-shadow(0 1px 2px rgba(10, 10, 10, .18));
}
.eyebrow i svg { width: 10px; height: 10px; }

h2.title {
  margin-top: 20px;
  font-size: 30px;
  line-height: 32px;
  letter-spacing: -.024em;
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
}

.lede {
  margin-top: 20px;
  max-width: 576px;
  font-size: 16px;
  line-height: 25px;
  color: var(--muted);
  text-wrap: pretty;
}

/* --- buttons ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 38px;
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 160ms var(--ease-out), background-color 160ms ease, border-color 160ms ease;
}
.btn svg { width: 13px; height: 13px; flex: none; }
.btn:active { transform: scale(.97); }

.btn--primary { background: var(--accent-ink); border-color: var(--accent-ink); color: #fff; }
.btn--ghost { background: var(--page); border-color: var(--line); color: #262626; }
.btn--bright { background: var(--accent-bright); color: var(--ink-strong); font-weight: 600; }

@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover { background: #016630; border-color: #016630; }
  .btn--ghost:hover { background: var(--panel); }
  .btn--bright:hover { background: #34d17a; }
}

/* --- nav ---------------------------------------------------------------- */

.nav { position: sticky; top: 0; z-index: 50; }
/* The backdrop is its own layer, transparent until the page moves — animating a
   layer's opacity costs nothing, animating the header's background repaints it. */
.nav::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .88);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  opacity: 0;
  transition: opacity 200ms ease;
}
.nav[data-stuck]::before { opacity: 1; }

.nav__inner {
  position: relative;
  display: flex;
  align-items: center;
  height: 56px;
  max-width: var(--grid-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.nav__inner > .brand { flex: 0 0 auto; }
.nav__end { flex: 0 0 auto; justify-content: flex-end; }
.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.02em;
}
.brand svg { width: 22px; height: 22px; }

.nav__links {
  position: relative;
  display: none;
  gap: 4px;
  font-size: 14px;
  font-weight: 500;
  color: var(--body);
}
.nav__links a { position: relative; z-index: 1; padding: 6px 10px; border-radius: var(--radius); transition: color 160ms ease, background-color 160ms ease; }
@media (hover: hover) { .nav__links a:hover { color: var(--ink); } }

/* One element slides between the links instead of each link lighting up.
   Position rides `transform`; the width is animated too rather than scaled,
   because scaling would stretch the caps and the radius with it. On an
   absolutely-positioned element the layout it costs is its own box and nothing
   else. */
.nav__pill {
  position: absolute;
  left: 0;
  top: 50%;
  width: 0;
  height: 32px;
  margin-top: -16px;
  border-radius: var(--radius);
  background: rgba(10, 10, 10, .05);
  opacity: 0;
  pointer-events: none;
  transition: transform 200ms var(--ease), width 200ms var(--ease), opacity 140ms ease;
}
.nav__links[data-hover] .nav__pill { opacity: 1; }

/* A pointer-only affordance: on touch, `pointerenter` fires on tap and the pill
   would flash under the finger. */
@media not all and (hover: hover) and (pointer: fine) {
  .nav__pill { display: none; }
}

.nav__end { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 500; }
/* On a phone the header is the mark and the toggle; both buttons live in the
   sheet, where they have the room to be tapped. */
.nav__end .btn { display: none; }
.nav .btn { height: 32px; padding: 0 12px; }
.nav__toggle { display: none; }

/* --- hero --------------------------------------------------------------- */

.hero { position: relative; overflow: hidden; text-align: center; }

.hero__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(#f7f7f7 1px, transparent 1px),
    linear-gradient(90deg, #f7f7f7 1px, transparent 1px);
  background-size: 88px 88px;
  -webkit-mask-image: radial-gradient(ellipse 74% 96% at 50% 26%, #000 0%, rgba(0, 0, 0, .55) 42%, transparent 76%);
  mask-image: radial-gradient(ellipse 74% 96% at 50% 26%, #000 0%, rgba(0, 0, 0, .55) 42%, transparent 76%);
  pointer-events: none;
}

.pill {
  position: relative;
  transition: border-color 160ms ease, background-color 160ms ease;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 32px;
  padding: 0 6px 0 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--page);
  font-size: 13px;
  font-weight: 500;
}
.pill b { display: flex; align-items: center; gap: 7px; font-weight: 500; }
.pill .dot { width: 6px; height: 6px; padding: 0; border: 0; border-radius: 999px; background: var(--accent); flex: none; }
.pill > span { display: flex; align-items: center; gap: 4px; padding: 0 8px; border-left: 1px solid var(--line); color: var(--muted); }
.pill svg { width: 11px; height: 11px; }
@media (hover: hover) and (pointer: fine) { .pill:hover { border-color: #d4d4d4; background: var(--panel); } }

h1 {
  position: relative;
  margin-top: 20px;
  max-width: 900px;
  margin-inline: auto;
  font-size: 34px;
  line-height: 1.15;
  letter-spacing: -.02em;
  font-weight: 600;
  text-wrap: balance;
}

.hero__lede {
  position: relative;
  margin: 20px auto 0;
  max-width: 640px;
  font-size: 17px;
  line-height: 26px;
  color: var(--body);
  text-wrap: pretty;
}

.hero__cta { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 12px; margin-top: 32px; }
.hero__cta .btn { height: 44px; padding: 0 20px; }

/* --- the product block, with the notch ---------------------------------- */

.stage .frame { display: flex; flex-direction: column; align-items: center; padding: 0 var(--gutter); }

.notch {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  width: 100%;
  padding: 28px 0 4px;
  flex: none;
}
.notch__shoulder { display: none; height: 64px; width: auto; flex: none; overflow: visible; }
.notch__shoulder--l { transform: translate(1px, 1px); }
.notch__shoulder--r { transform: translate(-1px, 1px) scaleX(-1); }

.tabs {
  position: relative;
  z-index: 2;
  width: 100%;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.tab {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: #f5f5f5;
  color: var(--body);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease;
}
.tab i {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex: none;
  border: 1px solid rgba(0, 0, 0, .05);
  border-radius: 4px;
  color: var(--accent-900);
  filter: drop-shadow(0 2px 3px rgba(10, 10, 10, .16));
}
.tab i svg { width: 10px; height: 10px; }
.tab[aria-selected='true'] {
  background: var(--page);
  border-color: var(--line);
  color: #262626;
  filter: drop-shadow(0 1px 1px rgba(10, 10, 10, .06));
}

.shot {
  width: 100%;
  max-width: 1000px;
  margin-top: 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--page);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.shot img { width: 100%; }

/* --- feature sections --------------------------------------------------- */

.feature__panel {
  padding: 32px var(--gutter) 0;
  border-top: 1px solid var(--line);
  background: var(--panel);
}
/* On a wide screen the shot is shown whole: reframing it per column cropped the
   table and cut the first letter off every profile name. Making the column change
   move the picture needs one screenshot per column, not a zoom into one. */
.feature__shot img { transform-origin: 0 0; }

.feature__shot {
  width: 100%;
  max-width: 908px;
  margin: 0 auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: var(--page);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.strip { border-top: 1px solid var(--line); }
.strip__inner {
  max-width: 800px;
  margin: 0 auto;
  padding: 28px var(--gutter);
  display: grid;
  grid-template-columns: 1fr;
  column-gap: 40px;
  row-gap: 32px;
}
.point {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0 8px 0 24px;
  text-align: left;
  font-size: 14px;
  color: var(--ink);
  opacity: .5;
  border: 0;
  background: none;
  font-family: inherit;
  cursor: pointer;
  /* Slow while it rotates on its own; a click is a response and snaps. */
  transition: opacity 500ms var(--ease);
}
.point[aria-current='true'] { opacity: 1; }
.strip[data-locked] .point { transition-duration: 180ms; }
@media (hover: hover) and (pointer: fine) {
  .point:not([aria-current='true']):hover { opacity: .7; }
}
.point svg { width: 16px; height: 16px; }
.point h3 { margin-top: 8px; font-size: 14px; font-weight: 500; color: inherit; }
.point p { margin-top: 14px; font-size: 14px; line-height: 20px; color: var(--muted); }

/* The rail is 1px and clips; the fill is a full-size child slid up out of it,
   so the progress runs on transform alone — never on height. */
/* The rail is the 1 px track and it clips; the fill fills it and is slid up out
   of it, so the progress is a transform and never a height. */
.point__rail {
  position: absolute;
  left: -1px;
  top: 0;
  width: 1px;
  height: 100%;
  overflow: hidden;
  background: var(--line);
}
.point__fill {
  width: 100%;
  height: 100%;
  background: var(--accent);
  transform: translateY(-100%);
}
.point[aria-current='true'] .point__fill { animation: rail var(--dwell, 5s) linear forwards; }
.strip[data-paused] .point__fill { animation-play-state: paused; }

@keyframes rail { to { transform: translateY(0); } }

/* --- pricing ------------------------------------------------------------ */

.price {
  display: grid;
  grid-template-columns: 1fr;
  width: 100%;
  max-width: 908px;
  margin: 0 auto;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--page);
  box-shadow: 0 24px 56px -34px rgba(10, 10, 10, .22);
  overflow: hidden;
}
.price__main { padding: 24px; }
.price__side { display: flex; flex-direction: column; padding: 24px; border-top: 1px solid var(--hairline); background: #fcfcfc; }
.label { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.amount { display: flex; align-items: baseline; gap: 10px; margin-top: 14px; }
.amount b { font-size: 52px; line-height: 52px; font-weight: 600; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.amount span { font-size: 15px; color: var(--muted); }
.price__note { margin-top: 14px; max-width: 400px; font-size: 14.5px; line-height: 22px; color: var(--body); }
.included { margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--hairline); }
.included ul { display: grid; grid-template-columns: 1fr; gap: 12px 28px; margin-top: 16px; }
.included li, .promise li { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; line-height: 21px; color: #404040; }
.included svg, .promise svg { width: 14px; height: 14px; flex: none; margin-top: 3px; }
.promise { display: grid; gap: 16px; }
.promise b { display: block; font-size: 13.5px; font-weight: 500; color: var(--ink); }
.promise span { display: block; margin-top: 3px; font-size: 12.5px; line-height: 18px; color: var(--muted); }
.price__side .btn { margin-top: 24px; height: 40px; }
.price__fine { margin-top: 12px; font-size: 12.5px; text-align: center; color: var(--muted); }

/* --- trust -------------------------------------------------------------- */

.trust { display: grid; grid-template-columns: 1fr; gap: 20px; padding: 32px var(--gutter); border-top: 1px solid var(--line); }
.trust > div { padding-left: 24px; border-left: 1px solid var(--line); }
.trust b { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; }
.trust svg { width: 14px; height: 14px; flex: none; }
.trust p { margin-top: 5px; padding-left: 22px; font-size: 13px; line-height: 19px; color: var(--muted); }

/* --- FAQ ---------------------------------------------------------------- */

.faq__inner { display: grid; grid-template-columns: 1fr; gap: 28px; align-items: start; padding: 48px var(--gutter); }
.faq h2 { font-size: 30px; line-height: 32px; letter-spacing: -.024em; font-weight: 600; }
.faq__list { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 22px 0;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -.01em;
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary span { flex: 1; }
.faq summary svg { width: 18px; height: 18px; flex: none; color: var(--faint); transition: transform 200ms var(--ease-out); }
.faq details[open] summary svg { transform: rotate(180deg); }
/* The 0fr → 1fr trick never fired: a closed <details> does not render its
   content at all, so there is no start state to transition from. The panel is
   the browser's own `::details-content`, and `interpolate-size` is what makes
   its `auto` height animatable. Browsers without it simply snap open. */
.faq__answer { display: block; }
.faq details::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 260ms var(--ease), content-visibility 260ms allow-discrete;
}
.faq details[open]::details-content { block-size: auto; }
.faq__answer p { max-width: 620px; padding-bottom: 22px; font-size: 15px; line-height: 24px; color: var(--body); }

/* --- waitlist ----------------------------------------------------------- */

.waitlist .frame { position: relative; }
.waitlist__mark { display: none; position: absolute; left: 70px; top: 55px; width: 240px; height: 240px; color: var(--accent-bright); }
.waitlist__body { position: relative; padding: 44px var(--gutter) 48px; }
.waitlist h2 { max-width: 420px; font-size: 30px; line-height: 32px; letter-spacing: -.022em; font-weight: 600; color: #fafafa; text-wrap: balance; }
.waitlist p { margin-top: 16px; max-width: 520px; font-size: 17px; line-height: 26px; color: var(--faint); }
.waitlist__fine { margin-top: 14px; font-size: 12.5px; color: var(--muted); }

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

.foot__inner { display: flex; flex-direction: column; flex-wrap: wrap; gap: 24px; align-items: flex-start; justify-content: space-between; padding: 40px var(--gutter); }
.foot__links { display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px; color: var(--body); }
.foot small { display: block; margin-top: 10px; font-size: 13px; color: var(--muted); }

/* --- scroll reveal ------------------------------------------------------ */

/* The transition has to live on the starting state: declared only on the end
   state, it never runs — the browser sees the declaration and the new values in
   the same recalculation and simply jumps. */
.rise { opacity: 0; }
/* A CSS animation, not a transition: the browser promotes the layer itself, so
   there is no will-change to set and, more to the point, nothing to clean up. */
.rise[data-shown] {
  animation: slide-up-fade .5s var(--ease) both;
  animation-delay: var(--delay, .15s);
  --offset: 20px;
}

/* The hero does not wait for a scroll — it plays on load, staggered. */
.hero__step { animation: slide-up-fade 1s var(--ease) both; animation-delay: var(--delay, 0s); }
.stage .frame { animation: slide-up-fade .4s var(--ease) .5s both; --offset: 20px; }

/* Columns arrive one after the other, sideways, like the reference — but the
   fade is left to the .point rule, which is what tells active from dimmed. */
.strip:not([data-shown]) .point { opacity: 0; }
.strip[data-shown] .point { animation: slide-left .5s var(--ease) both; --offset: 20px; }
.strip[data-shown] .point:nth-child(1) { animation-delay: .1s; }
.strip[data-shown] .point:nth-child(2) { animation-delay: .2s; }
.strip[data-shown] .point:nth-child(3) { animation-delay: .3s; }

/* --- responsive --------------------------------------------------------- */

/* Tablet and below: the header collapses, the type steps down — but the
   three-column blocks stay three columns, there is room for them. */


/* --- reduced motion ----------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .rise, .rise[data-shown] { opacity: 1; transform: none; animation: none; }
  .hero__step, .stage .frame, .strip[data-shown] .point { animation: none; }
  .strip:not([data-shown]) .point { opacity: .5; }
  .point__fill { animation: none !important; transform: translateY(0); }
  .btn:active { transform: none; }
  .faq details::details-content { transition: none; }
  .feature__shot img { transform: none; }
  *, *::before, *::after { scroll-behavior: auto !important; }
}


/* --- hero tab panels ----------------------------------------------------- */

.shot__stage { position: relative; aspect-ratio: 1000 / 640; }
.panel {
  position: absolute;
  inset: 0;
  opacity: 0;
  /* The outgoing panel leaves the way the new one arrives, so the pair reads as
     one movement rather than two objects swapping. */
  transform: translateX(var(--from, 12px)) scale(.99);
  /* Two screenshots crossfading look like two screenshots. A little blur bridges
     them into one transformation — kept low, it is expensive in Safari. */
  filter: blur(3px);
  transition: opacity 150ms var(--ease), transform 150ms var(--ease), filter 150ms var(--ease);
}
/* Entry is slower than exit: the system responds, then settles. */
.panel[data-active] {
  opacity: 1;
  transform: none;
  filter: none;
  transition-duration: 280ms;
}
.panel img { width: 100%; height: 100%; object-fit: cover; object-position: top; }

@media (prefers-reduced-motion: reduce) {
  .panel { transition: none; filter: none; transform: none; }
  .nav__pill { transition: none; }
}

/* --- mega menu ----------------------------------------------------------
   One shared viewport that resizes between triggers, as Radix does it and as
   dub uses it: measured there at 1020×448, radius 20, `scale-in-content .2s`
   from `rotateX(-30deg) scale(.9)`, and `transition: width, height .15s`.
   ----------------------------------------------------------------------- */

.nav__trigger {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--body);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: color 160ms ease;
}
.nav__trigger[aria-expanded='true'] { color: var(--ink); }
/* The glyph sits low in its 9×9 viewBox, so flipping the <svg> pivots on the
   box centre and shifts the arrow 0.7 px as it turns. `fill-box` pivots on the
   path's own bounds instead: it turns in place. */
.nav__trigger svg path {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 150ms var(--ease);
}
.nav__trigger[aria-expanded='true'] svg path { transform: scaleY(-1); }
@media (hover: hover) and (pointer: fine) { .nav__trigger:hover { color: var(--ink); } }

.mega {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  display: flex;
  justify-content: center;
  /* the panel tips forward as it opens, so the container needs depth */
  perspective: 1200px;
  pointer-events: none;
}
.mega__viewport {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--page);
  box-shadow: 0 4px 6px -4px rgba(10, 10, 10, .1), 0 20px 40px -12px rgba(10, 10, 10, .16);
  transform-origin: top center;
  pointer-events: auto;
  /* the box morphs between menus; the entrance itself is a transform */
  transition: width 150ms var(--ease), height 150ms var(--ease);
}
.mega[hidden] { display: none; }
.mega[data-open] .mega__viewport { animation: mega-in 200ms ease both; }
.mega[data-closing] .mega__viewport { animation: mega-out 120ms ease both; }

@keyframes mega-in {
  from { opacity: 0; transform: rotateX(-30deg) scale(.9); }
  to { opacity: 1; transform: none; }
}
/* Exits are shorter and simpler than entries — no rotation on the way out. */
@keyframes mega-out {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: scale(.97); }
}

.mega__panel { display: grid; gap: 2px; padding: 16px; width: max-content; }
.mega__panel--two { grid-template-columns: repeat(2, 300px); }
.mega__panel--one { grid-template-columns: 340px; }
.mega__panel[hidden] { display: none; }

/* padding 8, radius 8, and a negative margin so the hover ground reaches past
   the panel's own padding — dub's row exactly. */
.mega__item {
  display: flex;
  gap: 10px;
  padding: 8px;
  margin: 0 -8px;
  border-radius: var(--radius);
  transition: background-color 150ms ease;
}
.mega__item b { display: block; font-size: 14px; font-weight: 500; color: var(--ink); }
.mega__item > span > span { display: block; margin-top: 3px; font-size: 13px; line-height: 19px; color: var(--muted); }
.mega__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--accent-ink);
}
.mega__icon svg { width: 16px; height: 16px; }
@media (hover: hover) and (pointer: fine) { .mega__item:hover { background: var(--panel); } }

/* --- newsletter, dressed for the dark block ----------------------------- */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

#brevo-form { margin-top: 26px; max-width: 520px; }
#brevo-form .sib-form,
#brevo-form .sib-form-container,
#brevo-form #sib-container,
#brevo-form #sib-form > div { padding: 0 !important; margin: 0 !important; background: transparent !important; max-width: 100% !important; }
#brevo-form #sib-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; }
#brevo-form #sib-form > div { flex: 1 0 100%; }
#brevo-form .form__entry, #brevo-form .entry_block, #brevo-form .form__label-row, #brevo-form .entry__field { margin: 0 !important; padding: 0 !important; border: 0 !important; background: transparent !important; }
#brevo-form input.input {
  box-sizing: border-box !important;
  width: 100%;
  height: 44px;
  padding: 0 14px !important;
  border: 1px solid var(--dark-line) !important;
  border-radius: var(--radius) !important;
  background: var(--dark-field) !important;
  color: #fafafa !important;
  font-family: inherit !important;
  font-size: 14.5px !important;
  transition: border-color 160ms ease;
}
#brevo-form input.input::placeholder { color: var(--muted); }
#brevo-form input.input:focus { border-color: var(--accent-bright) !important; outline: none; }
#brevo-form .sib-form-block { padding: 0 !important; }
#brevo-form .sib-form-block__button {
  display: inline-flex !important;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 44px;
  padding: 0 22px !important;
  border: 0 !important;
  border-radius: var(--radius) !important;
  background: var(--accent-bright) !important;
  color: var(--ink-strong) !important;
  font-family: inherit !important;
  font-size: 14.5px !important;
  font-weight: 600 !important;
  cursor: pointer;
  transition: transform 160ms var(--ease-out), background-color 160ms ease;
}
#brevo-form .sib-form-block__button:active { transform: scale(.97); }
@media (hover: hover) and (pointer: fine) { #brevo-form .sib-form-block__button:hover { background: #34d17a !important; } }
#brevo-form .sib-form-message-panel {
  flex: 1 0 100%;
  margin: 0 0 4px !important;
  border-radius: 10px !important;
  font-family: inherit !important;
}
#brevo-form .entry__error { color: #fca5a5 !important; font-size: 13px !important; }



@media (prefers-reduced-motion: reduce) {
  .mega[data-open] .mega__viewport,
  .mega[data-closing] .mega__viewport { animation: none; }
  .mega__viewport { transition: none; }
  .nav__trigger svg { transition: none; }
  #brevo-form .sib-form-block__button:active { transform: none; }
}

/* --- Resources panel, on dub's own layout -------------------------------
   Measured there: 1020 wide, three columns at 0.9fr / 0.55fr / 0.55fr with
   1 px rules between them; the first holds two tall tiles (206×214, radius 12,
   #fafafa on a #f5f5f5 border), the others compact rows of 8 px padding.
   Column labels are 12 px uppercase in #737373.
   ----------------------------------------------------------------------- */

.mega__panel--produit { grid-template-columns: repeat(2, 300px); column-gap: 18px; }

.mega__panel--ressources {
  display: grid;
  grid-template-columns: 0.9fr 0.55fr 0.55fr;
  /* dub's exact measure. 840 was my own guess and left the columns loose; at
     1020 the tiles land at 205 px against their 206. Capped so the panel never
     reaches the edges of a narrow laptop. */
  width: min(1020px, calc(100vw - 48px));
  padding: 0;
  gap: 0;
}
.mega__col { padding: 16px 24px; border-left: 1px solid var(--line); }
.mega__col:first-child { padding: 16px; border-left: 0; }
/* auto for the label, 1fr for the tiles: the row takes whatever height the
   tallest column gives the panel, so the tiles reach the bottom. */
.mega__col--tiles { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto 1fr; column-gap: 16px; row-gap: 0; }
.mega__col--tiles .mega__label { grid-column: 1 / -1; }

/* Flush left: the rows pull themselves back by -8 px and their content lands on
   the column's own edge, so an indented label sat 8 px off from everything. */
.mega__label {
  margin: 0 0 16px;
  font-size: 12px;
  line-height: 16px;
  text-transform: uppercase;
  color: var(--muted);
}

.mega__tile {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 20px;
  border: 1px solid #f5f5f5;
  border-radius: 12px;
  background: var(--panel);
  transition: border-color 150ms ease, background-color 150ms ease;
}
/* Icon at the top, text against the bottom edge — the tile fills, it does not
   float its content in the middle. */
.mega__tile-text { margin-top: auto; }
.mega__tile-text b { display: block; font-size: 15px; font-weight: 500; color: var(--ink); }
.mega__tile-text span { display: block; margin-top: 4px; font-size: 13px; line-height: 19px; color: var(--muted); }

.mega__col--rows { display: grid; align-content: start; row-gap: 2px; }
.mega__col--rows .mega__label { margin-bottom: 16px; }
.mega__row {
  display: flex;
  gap: 10px;
  padding: 8px;
  margin: 0 -8px;
  border-radius: var(--radius);
  transition: background-color 150ms ease;
}
.mega__row b { display: block; font-size: 14px; font-weight: 500; color: var(--ink); }
.mega__row > span > span { display: block; margin-top: 2px; font-size: 12.5px; line-height: 18px; color: var(--muted); }

@media (hover: hover) and (pointer: fine) {
  .mega__tile:hover { background: #f5f5f5; border-color: var(--line); }
  .mega__row:hover { background: var(--panel); }
}

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


/* --- mobile navigation ---------------------------------------------------
   The mega menu has nowhere to unfold under 1000 px, so touch gets a flat
   sheet with the same entries.
   ----------------------------------------------------------------------- */

.nav__toggle {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--page);
  color: var(--ink);
  cursor: pointer;
}
.nav__toggle svg { width: 20px; height: 20px; }
/* Three lines folding into a cross. `view-box` pivots each on the icon's centre,
   which is what lets the two outer bars meet. */
.nav__toggle .bar {
  transform-box: view-box;
  transform-origin: center;
  transition: transform 200ms var(--ease), opacity 120ms ease;
}
/* Order matters: in `A B` the browser applies B first. Written translate-then-
   rotate, each bar was rotated about the icon's centre while still off it, so the
   two diagonals ended up 2.4 px apart. Rotate last, and both bars reach the
   centre line before turning. */
.nav__toggle[aria-expanded='true'] .bar--top { transform: rotate(45deg) translateY(5px); }
.nav__toggle[aria-expanded='true'] .bar--bottom { transform: rotate(-45deg) translateY(-5px); }
.nav__toggle[aria-expanded='true'] .bar--mid { opacity: 0; }

.sheet {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--page);
  animation: slide-up-fade 200ms var(--ease) both;
  --offset: -8px;
}
.sheet[hidden] { display: none; }
.sheet__inner { display: grid; gap: 2px; max-width: var(--grid-width); margin: 0 auto; padding: 16px var(--gutter) 24px; }
.sheet__inner a:not(.btn) {
  padding: 12px 8px;
  margin: 0 -8px;
  border-radius: var(--radius);
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
}
.sheet .mega__label { margin: 14px 0 6px; }
.sheet .mega__label:first-child { margin-top: 0; }
.sheet .btn { height: 48px; margin-top: 16px; }





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


/* --- phone --------------------------------------------------------------
   Below 720 px the three-column blocks genuinely have no room; above it they
   still read, so a tablet keeps the desktop composition.
   ----------------------------------------------------------------------- */



/* Between the two: the tablet keeps its columns but tightens their gaps. */



/* --- shots on a phone ----------------------------------------------------
   A whole desktop screen shrunk to 338 px is a grey smudge. Under 720 px each
   panel frames the one region worth reading; the per-column reframing steps
   aside there (the JS skips it), so these values are what shows.
   ----------------------------------------------------------------------- */

/* No crop on a phone either: zooming a desktop screenshot only trades an
   unreadable whole for a cut-off part. Legibility here needs captures taken at
   phone width, not CSS. */


/* --- the notch does not survive a phone ----------------------------------
   The two 85 px shoulders left 170 px for three chips inside a container fixed
   at 65 px: they stacked and overflowed it. dub drops the notch entirely at this
   width and lets the tabs sit on the tinted band, wrapped and centred.
   ----------------------------------------------------------------------- */




/* =========================================================================
   Everything above is the phone. What follows is added as the screen grows —
   two steps, ascending, in one place.
   ========================================================================= */

/* --- tablet: the columns come back --------------------------------------- */
@media (min-width: 721px) {
  .nav__end .btn--primary { display: inline-flex; }

  h1 { font-size: 40px; }
  .hero__cta { flex-direction: row; justify-content: center; }
  .hero__cta .btn { height: 40px; }

  .notch { max-width: 700px; height: 64px; padding: 0; }
  .notch__shoulder { display: block; }
  .tabs { height: 65px; width: auto; flex: 1; background: var(--page); gap: 10px; }

  .strip__inner { grid-template-columns: repeat(3, minmax(0, 1fr)); padding: 28px 0; column-gap: 24px; }
  .price { grid-template-columns: minmax(0, 1fr) 320px; }
  .price__side { border-top: 0; border-left: 1px solid var(--hairline); }
  .included ul { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; }
  .trust { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
  .faq__inner { grid-template-columns: 260px minmax(0, 1fr); gap: 32px; }
  .foot__inner { flex-direction: row; align-items: center; }

  #brevo-form #sib-form > div { flex: 1 1 260px; }
  #brevo-form #sib-form > div:not(:first-child) { flex: 0 0 auto; }
  #brevo-form .sib-form-block__button { width: auto; }
}

/* --- desktop: the full measure ------------------------------------------- */
@media (min-width: 1001px) {
  :root { --gutter: 40px; }

  .pad { padding: 72px var(--gutter); }
  h1 { font-size: 48px; }
  .hero__lede { font-size: 20px; line-height: 28px; }
  h2.title { font-size: 48px; line-height: 48px; letter-spacing: -.022em; }
  .lede { font-size: 18px; line-height: 28px; }

  .nav__links { display: flex; }
  .nav__toggle { display: none; }
  .nav__end .btn { display: inline-flex; }
  .nav__inner > .brand { flex: 1 0 0; }
  .nav__end { flex: 1 0 0; }
  .mega { display: flex; }
  .sheet { display: none !important; }

  .stage .frame { padding: 0 40px; }
  .feature__panel { padding: 56px var(--gutter) 0; }
  .strip__inner { column-gap: 40px; padding: 32px 0; }
  .price__main, .price__side { padding: 32px; }
  .included ul { gap: 12px 28px; }
  .trust { gap: 40px; padding: 40px var(--gutter); }
  .faq__inner { grid-template-columns: 340px minmax(0, 1fr); gap: 56px; padding: 72px var(--gutter); }
  .faq h2 { font-size: 40px; line-height: 42px; letter-spacing: -.022em; }

  .waitlist .frame { min-height: 350px; }
  .waitlist__mark { display: block; }
  .waitlist__body { padding: 52px var(--gutter) 52px 400px; }
  .waitlist h2 { font-size: 44px; line-height: 46px; }
}

/* --- legal pages ---------------------------------------------------------
   Long-form prose: one readable measure, the page's own type scale, and
   nothing else. The content is lifted verbatim from the previous site.
   ----------------------------------------------------------------------- */

.legal { max-width: 720px; padding: 48px var(--gutter) 72px; }
.legal h1 {
  max-width: none;
  margin: 0;
  font-size: 34px;
  line-height: 38px;
  letter-spacing: -.022em;
  font-weight: 600;
  text-align: left;
}
.legal .meta { margin-top: 12px; font-size: 13.5px; color: var(--muted); }
.legal .intro { margin-top: 20px; font-size: 17px; line-height: 27px; color: var(--body); }
.legal h2 {
  margin: 40px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 18px;
  line-height: 26px;
  letter-spacing: -.01em;
  font-weight: 600;
}
.legal p { margin-top: 14px; font-size: 15.5px; line-height: 25px; color: var(--body); }
.legal ul { margin-top: 14px; display: grid; gap: 8px; }
.legal li {
  position: relative;
  padding-left: 18px;
  font-size: 15.5px;
  line-height: 25px;
  color: var(--body);
}
.legal li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 11px;
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--accent);
}
.legal strong { color: var(--ink); font-weight: 600; }
.legal a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .legal a:hover { color: #016630; } }

@media (min-width: 721px) {
  .legal { padding: 64px 56px 88px; }
  .legal h1 { font-size: 40px; line-height: 44px; }
}
