/* ==========================================================================
   mediaTool - landing page
   Design language: large tight typography, generous whitespace, tile stack.
   ========================================================================== */

:root{
  --white:#fff;
  --grey:#f5f5f7;
  --ink:#1d1d1f;
  --ink-2:#6e6e73;
  --black:#000;
  --on-dark:#f5f5f7;
  --on-dark-2:#86868b;
  /* Brand palette. --link is a deepened violet: the raw brand colours sit at
     ~3.1:1 on white, which is under WCAG AA for body-size text. */
  --pink:#fd0fff;
  --violet:#9c65ff;
  --brand:linear-gradient(135deg,#fd0fff,#9c65ff);
  /* Buttons and button-like pills use their own vertical purple ramp. */
  --btn:linear-gradient(180deg,rgba(191,60,241,1) 0%,rgba(134,52,200,1) 100%);
  --link:#7b2ff7;
  --on-dark-accent:#e07bff;
  --hair:rgba(0,0,0,.12);
  --hair-dark:rgba(255,255,255,.14);
  --live:#ff453a;
  --ok:#30d158;
  --amber:#ff9f0a;
  --violet:#bf5af2;
  --r:18px;
  --r-lg:28px;
  --content:980px;
  --grid:1400px;
  --nav-h:77px;
  --sans:-apple-system,BlinkMacSystemFont,'SF Pro Display','SF Pro Text','Inter',
         'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --mono:'SF Mono',ui-monospace,SFMono-Regular,'JetBrains Mono',Menlo,Consolas,monospace;
}

*,*::before,*::after{box-sizing:border-box}
/* An author display declaration outranks the user agent's [hidden] rule, so a
   hidden element laid out as a grid or a flex box stays on screen. The plans
   set their feature lists to display:grid and toggle them with this attribute,
   and were drawing both at once until this rule existed. */
[hidden]{display:none!important}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--white);color:var(--ink);
  font-family:var(--sans);font-size:17px;line-height:1.47;letter-spacing:-.012em;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
img{max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
p{margin:0}
h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.018em;line-height:1.06}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

.skip-link{position:absolute;left:-9999px;top:0;z-index:200;background:var(--link);
  color:#fff;padding:12px 20px;border-radius:0 0 10px 0;font-weight:500}
.skip-link:focus{left:0}
:focus-visible{outline:3px solid var(--violet);outline-offset:3px;border-radius:6px}

/* ------------------------------ NAV ------------------------------ */
.nav{
  position:sticky;top:0;z-index:100;height:var(--nav-h);
  background:rgba(255,255,255,.72);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid rgba(0,0,0,.08);
}
.nav-inner{
  max-width:var(--grid);margin-inline:auto;height:100%;
  padding-inline:23px;display:flex;align-items:center;gap:28px;
}
.nav-logo{display:inline-flex;align-items:center;gap:10px;font-size:16px;letter-spacing:-.02em;color:var(--ink)}
.nav-logo strong{font-weight:600}

.nav-links{display:flex;align-items:center;gap:30px;margin-left:auto}
.nav-links a{
  font-size:14px;font-weight:600;color:var(--ink);opacity:.78;
  transition:opacity .2s ease,color .2s ease;
}
/* .nav-hot paints its text with a gradient, so leave its colour alone: a solid
   hover colour would beat the clip and flatten it. */
.nav-links a:hover:not(.nav-hot){opacity:1;color:var(--link)}
.nav-links a.nav-hot:hover{opacity:1;filter:brightness(1.1)}

/* Three bars of 2px with 5px between them is 16px of content: an even number
   inside an even box, so the stack starts on a whole pixel and each bar is a
   whole number of device pixels at any screen density. At 1.5px a bar was 4.5
   device pixels on a phone, which no screen can draw, and the rounding fell
   differently on each: three lines of visibly different weight. */
.nav-burger{display:none;margin-left:auto;width:36px;height:36px;padding:0;
  background:none;border:0;cursor:pointer;flex-direction:column;justify-content:center;gap:5px}
.nav-burger span{display:block;height:2px;background:var(--ink);border-radius:2px;
  transition:transform .3s ease,opacity .25s ease}
/* Folding into an X: the outer bars travel one bar plus one gap to meet in the
   middle, and the one already there gets out of the way. */
.nav-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ------------------------------ TILES ------------------------------ */
.tile{padding:100px 22px 110px;text-align:center;overflow:hidden}
.tile-light{background:var(--white);color:var(--ink)}
.tile-dark{background:var(--black);color:var(--on-dark)}
.tile-dark .subhead{color:var(--on-dark-2)}

.tile-copy{max-width:var(--content);margin-inline:auto}

.eyebrow{font-size:19px;font-weight:600;letter-spacing:-.01em;color:var(--ink-2);margin-bottom:6px}
.tile-dark .eyebrow{color:var(--on-dark-2)}
/* Every section label is painted in the brand gradient. The SaaS pill is the
   one exception: it is an .eyebrow too, and background-clip:text there would
   clip away the background its animated ring uses as a rim. This has to sit
   after the .tile-dark rule, which it matches on specificity alone. */
.eyebrow:not(.eyebrow-live){
  color:transparent;background:var(--brand);
  -webkit-background-clip:text;background-clip:text;
}

/* Sized so "AI-driven scheduling and playout" holds one line: it fits the
   1100px hero column at 71px, so the cap sits just under that. */
h1{font-size:clamp(30px,5.4vw,68px);letter-spacing:-.015em;line-height:1.05}
h2{font-size:clamp(32px,4.8vw,56px);letter-spacing:-.015em;line-height:1.07}

.subhead{
  margin-top:22px;margin-inline:auto;max-width:660px;
  font-size:clamp(19px,1.7vw,24px);line-height:1.4;letter-spacing:-.01em;color:var(--ink-2);
}

.links{display:flex;flex-wrap:wrap;gap:14px 30px;justify-content:center;align-items:center;margin-top:32px}
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--btn);color:#fff;font-family:inherit;font-size:17px;line-height:1;
  font-weight:600;border:0;cursor:pointer;
  padding:13px 24px;border-radius:980px;transition:filter .2s ease,transform .2s ease;
}
.btn:hover{filter:brightness(1.07);transform:scale(1.02)}
.link{color:var(--link);font-size:17px}

/* Outline pill with an arrow badge, for the secondary call to action. */
/* Sized to sit level with .btn: same 17px type, same 44px tall box, with the
   arrow badge inset so the pill does not grow past it. */
.btn-outline{
  display:inline-flex;align-items:center;gap:12px;
  font-family:inherit;font-size:17px;font-weight:600;line-height:1;color:var(--ink);
  background:#fff;border:1px solid var(--hair);border-radius:980px;
  padding:4px 4px 4px 24px;cursor:pointer;
  transition:border-color .22s ease,transform .22s ease,box-shadow .22s ease;
}
.btn-outline:hover{
  border-color:rgba(0,0,0,.2);transform:scale(1.02);
  box-shadow:0 10px 26px -18px rgba(0,0,0,.5);
}
.btn-arrow{
  width:33px;height:33px;flex:none;border-radius:50%;
  border:1px solid var(--hair);display:grid;place-items:center;
  transition:border-color .22s ease,background .22s ease;
}
.btn-outline:hover .btn-arrow{border-color:var(--violet);background:rgba(156,101,255,.08)}
.btn-arrow svg{
  width:15px;height:15px;fill:none;stroke:var(--link);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .22s cubic-bezier(.28,.11,.32,1);
}
.btn-outline:hover .btn-arrow svg{transform:translate(1.5px,-1.5px)}
.tile-dark .btn-outline{background:transparent;color:var(--on-dark);border-color:var(--hair-dark)}
.tile-dark .btn-arrow{border-color:var(--hair-dark)}
.tile-dark .btn-arrow svg{stroke:var(--on-dark-accent)}
.link:hover{text-decoration:underline}
.tile-dark .link{color:var(--on-dark-accent)}

/* section heading blocks that sit above a grid */
.section-head-block{background:var(--grey);padding:96px 22px 40px;text-align:center}
/* The grid is capped at --grid but its background has to reach the viewport
   edges, otherwise the white body shows as bands beside it on wide screens.
   The spread shadow paints outward; the clip keeps it from bleeding vertically
   into the sections above and below. */
.section-head-block + .grid{
  background:var(--grey);padding-bottom:96px;
  box-shadow:0 0 0 100vmax var(--grey);
  clip-path:inset(0 -100vmax);
}

/* Sections whose animations are only worth running while they can be seen.
   main.js adds .is-idle to a block that has scrolled away; everything inside
   it holds the frame it was on. Half the animations on this page paint or lay
   out on every frame, and paying for that below the fold is what a scroll
   feels. */
.is-idle,
.is-idle *{animation-play-state:paused!important}

/* ------------------------------ REVEAL ------------------------------ */
.reveal{opacity:0;transform:translateY(34px);
  transition:opacity .9s cubic-bezier(.28,.11,.32,1),transform .9s cubic-bezier(.28,.11,.32,1)}
.reveal-slow{transition-delay:.14s}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none}}

/* ------------------------------ HERO VIDEO ------------------------------ */
.hero{padding-bottom:0}
/* A little wider than the shared column, to keep the headline on two lines. */
.hero .tile-copy{max-width:1100px}
/* "Your FAST channel on air in 72 hours." only just clears 980px at 56px,
   which a different loaded font could tip into wrapping. Give it the same
   wider column as the hero rather than shaving the type. */
#fast .tile-copy{max-width:1100px}
.hero-stage{margin:60px auto 0;max-width:920px;padding-bottom:110px}
.hero-video{
  position:relative;width:100%;aspect-ratio:16/9;
  border-radius:var(--r-lg);overflow:hidden;background:#000;
  box-shadow:0 30px 70px -30px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.08);
}
.hero-video iframe,.hero-video #heroPlayer{
  position:absolute;inset:0;width:100%;height:100%;border:0;display:block;
}
/* The player is decorative here: the shield stops a click from pausing it or
   summoning the overlay. Remove it if viewers should be able to unmute. */
.hero-video-shield{position:absolute;inset:0;z-index:1}

/* The one control the hero carries. It sits above the shield, which is there
   to stop a click reaching the player at all. */
.hero-sound{
  position:absolute;right:14px;bottom:14px;z-index:2;
  width:40px;height:40px;padding:0;border:0;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  color:#fff;background:rgba(0,0,0,.45);
  backdrop-filter:saturate(180%) blur(12px);
  -webkit-backdrop-filter:saturate(180%) blur(12px);
  transition:background .2s ease,transform .18s ease,opacity .3s ease;
}
.hero-sound:hover{background:rgba(0,0,0,.68);transform:scale(1.06)}
.hero-sound svg{
  width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
}
.hero-sound .hero-sound-on{display:none}
/* Pressed means the sound is on, so the crossed out speaker gives way. */
.hero-sound[aria-pressed="true"] .hero-sound-off{display:none}
.hero-sound[aria-pressed="true"] .hero-sound-on{display:block}
/* The stop control, one button to the left of the sound. Pressed means the
   video is stopped, so the icon becomes the way to start it again. */
.hero-play{right:62px}
.hero-play .hero-icon-play{display:none}
.hero-play[aria-pressed="true"] .hero-icon-pause{display:none}
.hero-play[aria-pressed="true"] .hero-icon-play{display:block}
@media (max-width:640px){
  .hero-sound{right:10px;bottom:10px;width:44px;height:44px}
  .hero-play{right:62px}
}

/* ------------------------------ FIGURES ------------------------------ */
.figures{max-width:var(--grid);margin:72px auto 0;display:grid;
  grid-template-columns:repeat(4,1fr);gap:44px 24px}
.figure{display:flex;flex-direction:column;gap:8px}
.fig-n{font-size:clamp(34px,3.6vw,48px);font-weight:600;letter-spacing:-.02em;line-height:1}
.fig-l{font-size:15px;color:var(--on-dark-2)}

/* ------------------------------ GRID CELLS ------------------------------ */
.grid{max-width:var(--grid);margin-inline:auto;padding:0 22px;display:grid;gap:20px}
.grid-2{grid-template-columns:repeat(2,1fr)}
.grid-3{grid-template-columns:repeat(3,1fr)}
.cell{
  background:var(--white);border-radius:var(--r-lg);padding:44px 38px;
  transition:transform .5s cubic-bezier(.28,.11,.32,1),box-shadow .5s ease;
}
.cell:hover{transform:translateY(-4px);box-shadow:0 18px 40px -22px rgba(0,0,0,.3)}
.cell h3{font-size:clamp(22px,2.1vw,28px);letter-spacing:-.016em;margin-bottom:12px}
.cell p{font-size:17px;color:var(--ink-2);line-height:1.5}

/* The mark stands on its own. Its gradient rides on a presentation attribute
   inside each <svg>, not on this rule: a CSS stroke pointing at a paint server
   in another element is the form browsers disagree about, and it left the
   marks unpainted on some phones. Brand violet here is what shows if a mark
   ever arrives without a gradient of its own. */
.cell-icon,
.flow-in-icon,
.flow-out-icon,
.flow-node-icon{width:30px;height:30px;flex:none;display:grid;place-items:center}
.cell-icon svg,
.flow-in-icon svg,
.flow-out-icon svg,
.flow-node-icon svg{width:30px;height:30px;fill:none;
  stroke:var(--link);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}

/* Cards that set their mark beside the copy rather than above it. The rest of
   .cell is untouched, so quotes and plan cards keep their own stacking. */
.cell-row{display:flex;align-items:flex-start;gap:18px;position:relative}
.cell-body{min-width:0}

/* Opens the card's dialog. It sits in the corner rather than in the flow, so
   the copy keeps the whole width it had. */
.cell-open{
  position:absolute;top:20px;right:20px;
  width:34px;height:34px;flex:none;border-radius:50%;
  border:1px solid var(--hair);background:#fff;cursor:pointer;
  display:grid;place-items:center;
  transition:border-color .22s ease,background .22s ease,transform .22s ease;
}
.cell-open svg{
  width:15px;height:15px;fill:none;stroke:var(--link);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .22s cubic-bezier(.28,.11,.32,1);
}
.cell-open:hover,
.cell-row.is-openable:hover .cell-open{
  border-color:var(--violet);background:rgba(156,101,255,.08);transform:scale(1.06);
}
.cell-open:hover svg,
.cell-row.is-openable:hover .cell-open svg{transform:translate(1.5px,-1.5px)}

/* The whole card opens the dialog, so the pointer says so anywhere on it. The
   button stays for the keyboard and for anything reading the page. */
.cell-row.is-openable{cursor:pointer}
/* The card's copy must not run under the button. */
.cell-row .cell-body h3{padding-right:44px}

/* Module dialog */
.mod-icon{width:38px;height:38px;margin:0 auto 16px}
.mod-icon svg{width:38px;height:38px;fill:none;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.mod-clip{position:relative;margin-top:26px;border-radius:var(--r);overflow:hidden;background:#000}
/* While the file is on its way the box holds the shape it will have, so the
   dialog does not jump when it lands, and our own mark turns in the middle of
   it: the same lemniscate the playout preview uses. */
.mod-clip.is-loading{aspect-ratio:16/9}
/* A loop or a still: both fill the same 16:9 frame, so a dialog is the same
   shape whichever the panel holds. */
.mod-clip video,
.mod-clip img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}
.mod-body{
  /* The picture is as wide as the dialog; the words under it are not, because
     a 900px line of prose is unreadable. */
  margin:22px auto 0;max-width:660px;
  font-size:16px;line-height:1.55;color:var(--ink-2);
  text-align:left;white-space:pre-line;
}

.tag{display:inline-block;font-size:12px;font-weight:600;letter-spacing:.02em;
  text-transform:uppercase;color:var(--link);margin-bottom:18px}

/* ------------------------------ MONITOR ------------------------------ */
.monitor-stage{margin:64px auto 0;max-width:820px}
.monitor-card{background:#1c1c1e;border-radius:var(--r-lg);overflow:hidden;text-align:left;
  border:1px solid var(--hair-dark)}
.monitor-bar{display:flex;justify-content:space-between;align-items:center;
  padding:16px 22px;border-bottom:1px solid var(--hair-dark);font-size:13px;color:var(--on-dark-2)}
/* What is on air, in the application's own arrangement: a filled tag and the
   title beside it. The magenta is the application's, not the site's pink, and
   it is centred in what the panel's name leaves of the bar. */
.mon-now{display:flex;align-items:center;gap:10px;min-width:0;margin-inline:auto}
.mon-now-tag{
  flex:none;display:inline-flex;align-items:center;gap:7px;
  font-size:11px;font-weight:700;letter-spacing:.02em;color:#fff;
  background:#e6218f;border-radius:980px;padding:4px 11px 4px 10px;
}
/* The pulse the bar used to carry on its right, now inside the tag it belongs
   to, in white against the magenta. */
.mon-now-tag .pulse-dot{width:7px;height:7px;background:#fff}
.mon-now-tag .pulse-dot::after{background:#fff}
.mon-now-name{
  font-size:13px;color:var(--on-dark);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* The bar is two lines on a narrow screen rather than one crowded one: the
   panel's name, then what is on air under it. Hiding the mark altogether was
   worse, since it is the one thing in the bar worth reading. */
@media (max-width:860px){
  .monitor-bar{flex-direction:column;align-items:flex-start;gap:10px;padding:14px 16px}
  .mon-now{margin-inline:0;width:100%}
}

.monitors{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;padding:22px}
.mon{position:relative;aspect-ratio:16/9;border-radius:12px;overflow:hidden;
  background:radial-gradient(120% 120% at 30% 20%,#2c2c2e,#111113);
  border:1px solid var(--hair-dark);display:grid;place-items:center}
.mon.on{border-color:rgba(255,69,58,.45)}
/* An uploaded loop fills the tile; the tag, the wave and the meter sit over it. */
.mon-clip{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  border-radius:inherit;
}
.mon:has(.mon-clip) .wave{display:none}
.mon-tag,.lufs{z-index:2}
.mon-tag{position:absolute;top:9px;left:9px;font-family:var(--mono);font-size:10px;
  letter-spacing:.08em;color:var(--on-dark-2);background:rgba(0,0,0,.5);padding:3px 7px;border-radius:5px}
.wave{width:64%;height:32%;
  background:repeating-linear-gradient(90deg,rgba(253,15,255,.6) 0 2px,transparent 2px 7px);
  mask-image:radial-gradient(closest-side,#000 60%,transparent);
  -webkit-mask-image:radial-gradient(closest-side,#000 60%,transparent)}
.wave.w2{background-image:repeating-linear-gradient(90deg,rgba(156,101,255,.6) 0 2px,transparent 2px 9px)}
.wave.w3{background-image:repeating-linear-gradient(90deg,rgba(48,209,88,.55) 0 2px,transparent 2px 6px)}
.wave.w4{background-image:repeating-linear-gradient(90deg,rgba(255,159,10,.55) 0 2px,transparent 2px 8px)}

/* Loudness, the way a rack monitor shows it: two bars against a fixed scale
   with the -23 LUFS target marked across them. The gradient is sized in pixels
   and pinned to the bottom, so the green, amber and red bands stay put in
   space while the bar's height moves through them. */
.lufs{
  position:absolute;right:9px;bottom:9px;
  width:20px;height:56px;display:flex;gap:3px;align-items:flex-end;
}
/* The bars are drawn full height and scaled from the foot rather than having
   their height animated: a height keyframe is a layout on every frame, and
   eight of them running for the life of the page is felt on any scroll. */
.lufs i{
  flex:1;border-radius:2px;height:100%;
  transform-origin:bottom center;transform:scaleY(.7);
  background:linear-gradient(0deg,#30d158 0 62%,#ff9f0a 62% 82%,#ff453a 82% 100%);
  background-size:100% 56px;background-position:bottom;background-repeat:no-repeat;
  animation:lufs-l 3.1s ease-in-out infinite;
}
.lufs i:nth-child(2){animation-name:lufs-r;animation-duration:2.7s}
/* The target line, and the reading beside it. */
.lufs::after{
  content:"";position:absolute;left:-3px;right:-3px;bottom:72%;
  height:1px;background:rgba(255,255,255,.45);
}
/* The reading, level with the target line. It is an element rather than
   generated content because the tenths move. */
.lufs-read{
  position:absolute;right:24px;bottom:calc(72% - 5px);
  font-family:var(--mono);font-size:8px;font-weight:400;letter-spacing:.04em;
  color:rgba(255,255,255,.5);white-space:nowrap;
}
@keyframes lufs-l{
  0%{transform:scaleY(.68)}  14%{transform:scaleY(.77)} 27%{transform:scaleY(.61)}
  41%{transform:scaleY(.74)} 55%{transform:scaleY(.66)} 68%{transform:scaleY(.79)}
  82%{transform:scaleY(.63)} 100%{transform:scaleY(.68)}
}
@keyframes lufs-r{
  0%{transform:scaleY(.64)}  12%{transform:scaleY(.73)} 26%{transform:scaleY(.80)}
  39%{transform:scaleY(.62)} 52%{transform:scaleY(.71)} 66%{transform:scaleY(.65)}
  81%{transform:scaleY(.76)} 100%{transform:scaleY(.64)}
}
@media (prefers-reduced-motion:reduce){
  .lufs i{animation:none;transform:scaleY(.72)}
}

/* The counters under the previews, as the product wears them: what is on air,
   what is next, and the wall clock, with the skip control beside them. Light
   cards on the dark panel, the way they sit in the application. */
.tcs{
  --tcs-gap:12px;
  display:flex;flex-wrap:wrap;align-items:stretch;justify-content:center;
  gap:var(--tcs-gap);padding:0 22px 22px;
}
.tc-pill{
  display:flex;flex-direction:column;gap:0;
  min-width:142px;padding:6px 12px 7px;
  background:#fff;border:1.5px solid #111;border-radius:11px;color:#111;
}
.tc-l{font-size:9.5px;font-weight:700;letter-spacing:.02em;line-height:1.2}
.tc-v{
  font-size:16px;font-weight:700;letter-spacing:-.01em;line-height:1.2;
  font-variant-numeric:tabular-nums;
}
/* The bar under each counter reads the same thirty seconds: under the clip on
   air it fills as the clip plays, under the wait for the next one it empties.
   The fill is a pseudo-element scaled from the left, which is one paint per
   frame rather than a layout. */
.tc-bar{
  --p:1;
  position:relative;height:2.5px;border-radius:2px;margin-top:3px;overflow:hidden;
  background:rgba(253,15,255,.22);
}
.tc-bar::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:var(--pink);
  transform:scaleX(var(--p));transform-origin:left center;
}

.tc-next{border-color:var(--pink)}
/* The same fill the buttons wear, so the panel and the page agree. */
.tc-air{background:var(--btn);border-color:transparent;color:#fff}
.tc-air .tc-bar{background:rgba(255,255,255,.35)}
.tc-air .tc-bar::after{background:#fff}
.tc-clock{min-width:130px}

/* Take: it puts what is in preview on air, and what was on air back into
   preview, which is the one thing this panel actually does. */
.tc-skip{
  display:grid;place-items:center;width:46px;
  background:#fff;border:1.5px solid var(--pink);border-radius:11px;color:var(--pink);
  cursor:pointer;padding:0;
  transition:background .18s ease,border-color .18s ease,color .18s ease,transform .12s ease;
}
/* Pressing it puts a source to air, so under the pointer it fills with the
   application's own magenta and the mark turns white. */
.tc-skip:hover{background:#ee3d96;border-color:#ee3d96;color:#fff}
.tc-skip:active{transform:scale(.94)}
.tc-skip svg{
  width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linejoin:round;stroke-linecap:round;
}
/* The nudge to press it. Beside the control with its arrow pointing back at
   it, and it stands down once the panel has been used. */
.tc-try{
  display:flex;align-items:center;gap:6px;align-self:center;
  font-size:13px;font-weight:600;color:var(--pink);white-space:nowrap;
  max-width:220px;overflow:hidden;
  transition:opacity .3s ease,max-width .35s ease .1s,margin .35s ease .1s;
}
.tc-try svg{
  width:30px;height:22px;flex:none;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
  animation:try-nod 2.6s ease-in-out infinite;
}
/* Once it has done its job it gets out of the way entirely, gap and all, so
   the counters settle back into the middle of the panel. */
.tcs.is-used .tc-try{
  opacity:0;pointer-events:none;
  max-width:0;margin-inline-start:calc(-1 * var(--tcs-gap));
}
/* The nod runs the way the arrow points, which is back at the control. */
@keyframes try-nod{
  0%,72%,100%{transform:translateX(0)}
  84%{transform:translateX(-4px)}
}
@media (prefers-reduced-motion:reduce){
  .tc-try svg{animation:none}
}

/* Loading a picture into preview: our own mark, a lemniscate with a coloured
   run travelling round a grey track. Drawn with pathLength="100", so the dash
   is in hundredths of the path and the same numbers hold at any size. */
.mon-spin{
  position:absolute;inset:0;z-index:3;display:grid;place-items:center;
  background:rgba(0,0,0,.35);
  opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s;
}
.mon-spin.on{opacity:1;visibility:visible}
.mon-spin svg{width:78px;height:54px}
.mon-spin path{fill:none;stroke-width:3.2;stroke-linecap:round}
.mon-spin .spin-track{stroke:rgba(255,255,255,.16)}
.mon-spin .spin-run{
  stroke-dasharray:26 74;
  animation:spin-run 1.5s linear infinite;
}
@keyframes spin-run{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}
@media (prefers-reduced-motion:reduce){
  .mon-spin .spin-run{animation-duration:3s}
}

/* An input is a source to choose: clicking one puts it in preview. */
.mon.is-source{cursor:pointer}
.mon.is-source:hover{border-color:rgba(253,15,255,.55)}
/* The one that was chosen, edged in the brand colour and saying so beside its
   own tag, in the same chip the tag wears. */
.mon.is-picked{border-color:var(--pink)}
/* Placed off the tag's measured width, which the script hands over. */
.mon-sel{left:var(--sel-left,58px);color:var(--pink)}


@media (max-width:700px){
  .tcs{--tcs-gap:8px;padding:0 14px 14px}
  /* Sized to the reading, not to the row. A counter stretched to whatever
     width is left over is a box with a number in the corner of it, and the two
     of them stop looking like the pair they are. */
  .tc-pill{min-width:0;flex:0 1 auto;padding:5px 10px 6px;border-radius:10px}
  .tc-v{font-size:14px}
  .tc-l{font-size:9px}
  .tc-skip{width:40px;border-radius:10px}
  .tc-skip svg{width:19px;height:19px}
}

/* ==========================================================================
   AI generated EPG
   A dark sheet on a dark tile, like the channel monitor: the entry is written
   into it a character at a time while the key art resolves beside it. The art
   is drawn here rather than shipped, so nothing has to be licensed to show
   what the module produces.
   ========================================================================== */
.epg-stage{margin:60px auto 0;max-width:1000px}
.epg-card{
  background:#1c1c1e;border:1px solid var(--hair-dark);border-radius:var(--r-lg);
  overflow:hidden;text-align:left;
  box-shadow:0 30px 70px -30px rgba(0,0,0,.6);
}
.epg-bar{
  display:flex;align-items:center;gap:12px;
  padding:15px 20px;border-bottom:1px solid var(--hair-dark);
}
.epg-prompt{
  font-size:13px;color:var(--on-dark-2);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.epg-prompt b{color:var(--on-dark);font-weight:600}
.epg-state{
  margin-left:auto;flex:none;font-family:var(--mono);font-size:11px;
  letter-spacing:.08em;color:var(--on-dark-accent);
}

.epg-body{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);gap:20px;padding:20px}

/* The key art. Sky, sun and three ridges, drawn in the brand colours and
   resolving out of a blur as the entry is written. */
.epg-art{
  position:relative;margin:0;aspect-ratio:16/9;border-radius:12px;overflow:hidden;
  background:#0d0d12;isolation:isolate;
}
.epg-art > span{position:absolute;inset:0}
.epg-art-sky{background:linear-gradient(180deg,#2a1140 0%,#5a1d6e 46%,#c02f8f 78%,#ff8a5b 100%)}
.epg-art-sun{
  background:radial-gradient(circle at 62% 74%,rgba(255,214,150,.95) 0 6%,
    rgba(255,150,110,.5) 7%,transparent 22%);
}
.epg-art-ridge{background:#1a0b28}
.epg-art-ridge.r3{
  background:#3a1a52;
  clip-path:polygon(0 62%,18% 44%,34% 58%,52% 38%,72% 55%,88% 42%,100% 52%,100% 100%,0 100%);
}
.epg-art-ridge.r2{
  background:#24102f;
  clip-path:polygon(0 76%,14% 62%,30% 74%,48% 58%,66% 72%,84% 60%,100% 70%,100% 100%,0 100%);
}
.epg-art-ridge.r1{
  background:#120a18;
  clip-path:polygon(0 88%,20% 80%,38% 90%,58% 78%,78% 88%,100% 82%,100% 100%,0 100%);
}
/* The pass that gives the light somewhere to fall. */
.epg-art-cap{
  position:absolute;left:12px;bottom:10px;z-index:3;
  font-family:var(--mono);font-size:9px;letter-spacing:.06em;
  color:rgba(255,255,255,.62);background:rgba(0,0,0,.45);
  padding:3px 8px;border-radius:5px;
}
/* The sweep that says it is being made. */
.epg-art-scan{
  z-index:2;
  background:linear-gradient(100deg,transparent 42%,rgba(255,255,255,.28) 50%,transparent 58%);
  background-size:260% 100%;
}

.epg-text{display:flex;flex-direction:column;gap:16px;min-width:0}
.epg-title{
  margin:0;font-size:19px;font-weight:600;letter-spacing:-.012em;color:var(--on-dark);
}
.epg-title span{
  display:block;margin-top:3px;font-family:var(--mono);font-size:11px;font-weight:400;
  letter-spacing:.05em;color:var(--on-dark-2);
}
.epg-field{display:flex;flex-direction:column;gap:6px;min-width:0}
.epg-label{
  font-family:var(--mono);font-size:9px;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(255,255,255,.4);
}
.epg-out{
  margin:0;font-size:13px;line-height:1.5;color:var(--on-dark-2);
}
.epg-out.is-typing::after{
  content:"";display:inline-block;vertical-align:-1px;
  width:6px;height:13px;margin-left:2px;background:var(--pink);
  animation:epg-caret .9s steps(1) infinite;
}
@keyframes epg-caret{0%,50%{opacity:1}51%,100%{opacity:0}}
/* The rows keep their height while they fill, so nothing below them moves. */
.epg-short{min-height:58px}
.epg-long{min-height:136px}

.epg-foot{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;
  padding:14px 20px;border-top:1px solid var(--hair-dark);
}
.epg-chip{
  font-family:var(--mono);font-size:11px;padding:5px 11px;border-radius:980px;
  border:1px solid var(--hair-dark);color:var(--on-dark-2);
}
.epg-done{margin-inline-start:auto;font-size:13px;color:var(--on-dark)}
.epg-done b{font-family:var(--mono);font-weight:500;color:var(--on-dark-accent)}
/* Three dots that arrive one at a time while the synopsis is being written.
   The span keeps its width whether none or all three are showing: the line is
   pushed to the right-hand end of its row, so a width that grows would drag
   the words along with it. */
.epg-done .ell{display:inline-block;width:1.2em;text-align:left}
.epg-done .ell i{font-style:normal;opacity:0;animation:mt-ell 1.4s linear infinite}
.epg-done .ell i:nth-child(2){animation-delay:.18s}
.epg-done .ell i:nth-child(3){animation-delay:.36s}
@keyframes mt-ell{0%{opacity:0}18%{opacity:1}72%{opacity:1}90%,100%{opacity:0}}
@media (prefers-reduced-motion:reduce){
  .epg-done .ell i{animation:none;opacity:1}
}

/* The whole thing on one cycle: the art resolves while the entry is written,
   and both start again together. */
.epg-stage.in .epg-art > span:not(.epg-art-scan):not(.epg-art-cap),
.epg-stage.in .epg-art-cap{animation:epg-resolve 18s ease-out infinite}
.epg-stage.in .epg-art-scan{animation:epg-scan 18s ease-in-out infinite}
@keyframes epg-resolve{
  0%      {filter:blur(16px) saturate(.35);opacity:.35}
  34%     {filter:blur(0) saturate(1);opacity:1}
  94%     {filter:blur(0) saturate(1);opacity:1}
  100%    {filter:blur(16px) saturate(.35);opacity:.35}
}
@keyframes epg-scan{
  0%      {background-position:120% 0;opacity:1}
  30%     {background-position:-60% 0;opacity:1}
  34%,100%{background-position:-60% 0;opacity:0}
}

@media (max-width:820px){
  .epg-body{grid-template-columns:1fr}
  .epg-long{min-height:0}
  .epg-short{min-height:0}
}
@media (prefers-reduced-motion:reduce){
  .epg-stage.in .epg-art > span,
  .epg-stage.in .epg-art-cap,
  .epg-stage.in .epg-art-scan{animation:none}
  .epg-art-scan{opacity:0}
  .epg-out.is-typing::after{animation:none}
}

.feature-row{list-style:none;margin:64px auto 0;padding:0;max-width:var(--grid);
  display:grid;grid-template-columns:repeat(4,1fr);gap:32px 24px;text-align:left}
.feature-row li{display:flex;flex-direction:column;gap:6px;
  border-top:1px solid var(--hair-dark);padding-top:18px}
.feature-row strong{font-size:19px;font-weight:600;letter-spacing:-.01em}
.feature-row span{font-size:15px;color:var(--on-dark-2)}

/* ------------------------------ CTA ------------------------------ */
.cta{background:var(--white);padding-block:120px}

/* ------------------------------ FOOTER ------------------------------ */
.footer{background:var(--grey);border-top:1px solid rgba(0,0,0,.08);
  font-size:12px;line-height:1.5;color:var(--ink-2)}
.footer-inner{max-width:var(--grid);margin-inline:auto;padding:40px 22px 30px}
.footer-note{max-width:760px;padding-bottom:22px;border-bottom:1px solid rgba(0,0,0,.1)}
.footer-cols{display:grid;grid-template-columns:repeat(3,minmax(0,220px));
  gap:30px;padding:26px 0}
.footer-col{display:flex;flex-direction:column;gap:9px}
.footer-col h3{font-size:12px;font-weight:600;color:var(--ink);margin-bottom:2px}
.footer-col a{color:var(--ink-2);transition:color .2s ease}
.footer-col a:hover{color:var(--ink);text-decoration:underline}
/* The policy sits beside the copyright line, as a button because it opens a
   dialog rather than going anywhere. */
.footer-legal-link{
  font:inherit;font-size:inherit;color:inherit;
  background:none;border:0;padding:0;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px;
}
.footer-legal-link:hover{color:var(--ink)}

/* A footer entry that opens a dialog rather than going anywhere: it has to
   look like the links beside it. */
/* No opacity on the text: nine tenths of the grey over the footer's own grey
   is 3.8:1, under the 4.5 that 12px type has to meet, and the links beside it
   are drawn at full strength anyway. */
.footer-link-btn{
  font:inherit;font-size:inherit;line-height:inherit;text-align:left;
  color:var(--ink-2);background:none;border:0;padding:0;cursor:pointer;
  transition:color .2s ease;
}
.footer-link-btn:hover{color:var(--ink);text-decoration:underline}

/* ==========================================================================
   Coverage, in a dialog
   ========================================================================== */
.press{list-style:none;margin:28px 0 0;padding:0;display:grid;gap:12px;text-align:left}
.press-item{
  display:flex;align-items:center;gap:16px;
  padding:14px;border:1px solid var(--hair);border-radius:16px;background:#fff;
  color:var(--ink);text-decoration:none;
  transition:border-color .22s ease,transform .22s ease,box-shadow .22s ease;
}
.press-item:hover{
  border-color:var(--violet);transform:translateY(-2px);
  box-shadow:0 14px 30px -20px rgba(0,0,0,.45);
}
.press-shot{
  position:relative;flex:none;width:132px;aspect-ratio:16/9;
  border-radius:10px;overflow:hidden;background:var(--grey);
  display:grid;place-items:center;
}
.press-shot img{width:100%;height:100%;object-fit:cover;display:block}
/* A source with no picture of its own gets its initials in the brand gradient. */
.press-shot.is-mark{
  background:var(--brand);color:#fff;
  font-family:var(--mono);font-size:22px;font-weight:700;letter-spacing:.04em;
}
.press-play{
  position:absolute;inset:0;display:grid;place-items:center;
  background:rgba(0,0,0,.28);
}
.press-play svg{width:34px;height:34px;fill:#fff;filter:drop-shadow(0 2px 6px rgba(0,0,0,.5))}
.press-text{display:flex;flex-direction:column;gap:5px;min-width:0}
.press-src{
  font-family:var(--mono);font-size:10px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink-2);
}
.press-text strong{font-size:16px;font-weight:600;line-height:1.35;letter-spacing:-.01em}
.press-item .su-go{margin-left:auto}

@media (max-width:640px){
  .press-item{align-items:flex-start;gap:12px;padding:12px}
  .press-shot{width:96px}
  .press-text strong{font-size:15px}
  .press-item .su-go{display:none}
}

/* Three figures across the top of the About dialog. */
.about-facts{
  display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:26px;
}
.about-fact{
  display:flex;flex-direction:column;gap:2px;align-items:center;
  padding:12px 20px;border:1px solid var(--hair);border-radius:14px;
  font-size:12px;color:var(--ink-2);
}
.about-fact b{
  font-size:18px;font-weight:600;letter-spacing:-.012em;
  color:transparent;background:var(--brand);
  -webkit-background-clip:text;background-clip:text;
}
/* The group's chip goes to the group's own site, so it lifts under the pointer
   the way anything else here does that can be clicked. */
.about-fact-link{
  text-decoration:none;color:inherit;
  transition:border-color .18s ease,transform .18s cubic-bezier(.28,.11,.32,1);
}
.about-fact-link:hover{border-color:rgba(0,0,0,.22);transform:translateY(-2px)}
/* The group's own mark where the panel holds one, sized to sit level with the
   two figures beside it rather than to whatever the file happens to be. */
.about-mark{
  display:block;height:19px;width:auto;max-width:170px;margin:2px 0 3px;
}
/* Two across, because the board is a pair and reads as one. Each still gets
   its own column so a long role does not push the other name out of line. */
/* Named with .legal, which sets an indent for the bulleted lists in the policy
   further down: without that, this list of pills would sit 20px in from the
   text above it for no reason anyone could see. */
.legal .about-people{
  list-style:none;margin:0 0 24px;padding:0;
  display:grid;grid-template-columns:1fr 1fr;gap:12px 22px;
}
@media (max-width:560px){
  .legal .about-people{grid-template-columns:1fr}
}
/* Each one wears what the demo host in the booking dialog wears: a portrait in
   a pill, the name and the role beside it. Two things on this site introduce a
   person, and they should not look like two different ideas. */
.about-people li{
  display:flex;align-items:center;gap:14px;
  padding:9px 26px 9px 9px;
  border:1px solid var(--hair);border-radius:999px;background:#fff;
}
/* A portrait if the panel holds one, initials if it does not. */
.about-face{
  width:69px;height:69px;flex:none;border-radius:50%;overflow:hidden;
  display:grid;place-items:center;background:var(--brand);
  color:#fff;font-family:var(--mono);font-size:20px;font-weight:700;letter-spacing:.04em;
}
.about-face img{width:100%;height:100%;object-fit:cover;display:block}
.about-who{display:flex;flex-direction:column;gap:1px;min-width:0}
.about-people strong{color:var(--ink);font-size:15px;font-weight:600}
.about-who span{font-size:13px;color:var(--ink-2)}
.legal-foot{gap:12px;flex-wrap:wrap}

/* ==========================================================================
   Legal text in a dialog
   Reads down a left aligned column, unlike the short dialogs, which centre.
   ========================================================================== */
.legal{
  margin-top:26px;text-align:left;
  font-size:15px;line-height:1.6;color:var(--ink-2);
}
.legal-date{
  font-family:var(--mono);font-size:11px;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-2);margin:0 0 22px;
}
.legal h3{
  font-size:17px;font-weight:600;letter-spacing:-.01em;color:var(--ink);
  margin:26px 0 8px;
}
.legal h3:first-of-type{margin-top:0}
/* Both edges flush, the way a policy is set on paper. Hyphenation goes with
   it: justified text that cannot break a word opens rivers of white space
   between the short ones instead, which is worse than the ragged edge it
   replaced. The last line of a paragraph stays ragged, as it should. */
.legal p,
.legal li{
  text-align:justify;text-justify:inter-word;
  -webkit-hyphens:auto;hyphens:auto;
}
.legal p{margin:0 0 12px}
.legal ul{margin:0 0 12px;padding-left:20px}
.legal li{margin-bottom:6px}
/* Too narrow to justify: a phone column is a handful of words wide, and the
   gaps a flush right edge needs there are holes. */
@media (max-width:560px){
  .legal p,
  .legal li{text-align:left}
}
/* Underlined at rest, not only on hover: the link colour against the grey
   prose around it is a colour difference and nothing else, which is no
   difference at all to a reader who cannot see the two apart. */
.legal a{color:var(--link);text-decoration:underline;text-underline-offset:2px}
.legal a:hover{color:var(--ink)}
.legal strong{color:var(--ink);font-weight:600}
.legal-foot{display:flex;justify-content:center;margin-top:30px}

.footer-bottom{display:flex;flex-wrap:wrap;gap:6px 24px;justify-content:space-between;
  border-top:1px solid rgba(0,0,0,.1);padding-top:20px}
.footer-group{
  display:inline-flex;align-items:center;gap:7px;
  color:var(--ink-2);text-decoration:none;
}
.footer-group-lead{font-size:13px}
.footer-group b{font-size:13px;font-weight:600;color:var(--ink)}
/* Sized to sit on the same line as the words beside it. */
.footer-mark{height:17px;width:auto;max-width:170px;display:block;opacity:.85}
.footer-group:hover{color:var(--ink)}
.footer-group:hover .footer-mark{opacity:1}

/* ------------------------------ RESPONSIVE ------------------------------ */
@media (max-width:1068px){
  .figures{grid-template-columns:repeat(2,1fr)}
  .feature-row{grid-template-columns:repeat(2,1fr)}
  .grid-3{grid-template-columns:1fr;max-width:700px}
}
@media (max-width:834px){
  .nav-burger{display:flex}
  .nav-links{
    position:absolute;inset:var(--nav-h) 0 auto;flex-direction:column;align-items:stretch;
    gap:0;margin:0;padding:8px 23px 24px;
    /* Opaque. At 96% with a backdrop filter the hero headline still ghosted
       through the drawer at about #e2e2e2, which reads as a rendering fault
       rather than as depth. Nothing is left to blur once it is solid. */
    background:#fff;
    border-bottom:1px solid rgba(0,0,0,.1);display:none;
  }
  .nav-links.open{display:flex}
  .nav-links a{font-size:17px;padding:15px 0;border-bottom:1px solid rgba(0,0,0,.08);opacity:1}
  .nav-links a.nav-hot{font-size:17px;border-bottom:0;align-self:flex-start;margin:10px 0}
  /* The pill runs the width of the drawer here, so centre its label rather
     than leaving it against the left edge where the plain links start. */
  .nav-links a.nav-signup{
    display:flex;justify-content:center;
    padding:14px 22px;border-bottom:0;margin-top:12px;
  }
  .grid-2{grid-template-columns:1fr;max-width:700px}
  .tile{padding:76px 22px 84px}
  .section-head-block{padding-top:76px}
}
@media (max-width:640px){
  /* Touch targets: a mark, an arrow and a footer link are all small boxes
     around small glyphs, so give them the room a finger needs without moving
     what is drawn inside them. */
  .nav-burger{width:44px;height:44px;margin-right:-4px}
  .cell-open{width:40px;height:40px;top:16px;right:16px}
  /* A finger wants about 44px. These are all one line of text, so the height
     comes from padding, which also opens the columns up. */
  .footer-col a,
  .footer-link-btn{padding:11px 0;min-height:44px;display:flex;align-items:center}
  .footer-col{gap:0}
  .footer-bottom a,
  .footer-legal-link{padding:11px 0;min-height:44px}
  .footer-group{padding:8px 0;min-height:40px}

  /* A mark beside the copy leaves the paragraph about 250px to wrap in at
     phone width. Set it back above the text and give the copy the whole card.
     The open control sits in the corner either way, so the heading keeps its
     clearance from it. */
  .cell-row{flex-direction:column;gap:14px}

  /* Two headings break badly this narrow: the hero strands "playout" on a line
     of its own, and the playout heading runs to four. Drop their desktop line
     break and let the browser even out the lines instead. Every other heading
     wraps better with the break it was given, so this is not a blanket rule. */
  .h-rebreak br{display:none}
  .h-rebreak{text-wrap:balance}

  .tile{padding:62px 20px 68px}
  .cta{padding-block:80px}
  .hero-stage{margin-top:44px;padding-bottom:72px}
  .cell{padding:34px 26px;border-radius:var(--r)}
  .grid{gap:14px;padding-inline:20px}
  .figures{gap:34px 18px;margin-top:56px}
  .feature-row{grid-template-columns:1fr;margin-top:48px}
  /* The monitor keeps its two by two shape here rather than becoming a column
     of four tall tiles: closer to the product, and far shorter to scroll. The
     meter shrinks to suit the smaller tile. */
  .monitors{gap:8px;padding:14px}
  .mon-tag{top:6px;left:6px;font-size:9px;padding:2px 5px}
  /* Two chips will not sit side by side on a tile this narrow, so the one
     saying the source is chosen goes under the tag rather than beside it. */
  .mon-sel{left:6px;top:26px}
  .lufs{right:6px;bottom:6px;width:15px;height:38px}
  .lufs i{background-size:100% 38px}
  .lufs-read{right:18px;font-size:7px}
  /* The tile is short here, so lift the waveform clear of the meter and its
     reading rather than letting the three share the middle. */
  .wave{width:66%;height:30%;margin-bottom:20px}
  .footer-cols{grid-template-columns:1fr 1fr}
  .links{gap:12px 20px}
}

/* ==========================================================================
   Sign up button
   ========================================================================== */
.nav-signup{
  background:var(--btn);color:#fff!important;opacity:1!important;
  padding:6px 15px;border-radius:980px;font-weight:500;
  transition:filter .2s ease,transform .2s ease;
}
.nav-signup:hover{filter:brightness(1.07);transform:scale(1.03)}

/* ==========================================================================
   FAST in 72 hours
   ========================================================================== */
.tile-accent{
  background:
    radial-gradient(70% 100% at 15% 0%,rgba(253,15,255,.16),transparent 60%),
    radial-gradient(70% 100% at 85% 10%,rgba(156,101,255,.20),transparent 62%),
    #0a0a0c;
  color:var(--on-dark);
}
.tile-accent .subhead{color:var(--on-dark-2)}
.timeline{
  list-style:none;margin:64px auto 0;padding:0;max-width:var(--grid);
  display:grid;grid-template-columns:repeat(3,1fr);gap:24px;text-align:left;
}
.timeline li{
  padding:28px 26px;border-radius:var(--r-lg);
  background:rgba(255,255,255,.05);border:1px solid var(--hair-dark);
}
.timeline .t-when{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:14px;letter-spacing:.08em;
  text-transform:uppercase;margin-bottom:14px;font-weight:700;
  color:transparent;background:var(--brand);-webkit-background-clip:text;background-clip:text;
}
/* The number itself is a filled disc rather than more gradient type. The three
   count off quickly, one straight after another, and then the row is still for
   five seconds before doing it again: the point is the order they go in, and a
   beat every three seconds says something else entirely. */
.t-num{
  display:grid;place-items:center;width:26px;height:26px;flex:none;
  border-radius:50%;background:var(--brand);
  -webkit-background-clip:border-box;background-clip:border-box;
  color:#fff;font-size:13px;font-weight:700;letter-spacing:0;
  animation:t-num-beat 6.5s ease-in-out infinite;
}
.timeline li:nth-child(2) .t-num{animation-delay:.45s}
.timeline li:nth-child(3) .t-num{animation-delay:.9s}
@keyframes t-num-beat{
  0%       {transform:scale(1)}
  4%       {transform:scale(1.25)}
  9%,100%  {transform:scale(1)}
}
/* The halo is a ring of its own that scales and fades, rather than a spreading
   box-shadow, which would repaint the disc on every frame of it. */
.t-num{position:relative}
.t-num::after{
  content:"";position:absolute;inset:-6px;border-radius:50%;
  border:2px solid rgba(253,15,255,.5);opacity:0;
  animation:t-num-halo 6.5s ease-out infinite;
}
.timeline li:nth-child(2) .t-num::after{animation-delay:.45s}
.timeline li:nth-child(3) .t-num::after{animation-delay:.9s}
@keyframes t-num-halo{
  0%      {opacity:.7;transform:scale(.75)}
  9%      {opacity:0;transform:scale(1.25)}
  10%,100%{opacity:0;transform:scale(.75)}
}
@media (prefers-reduced-motion:reduce){
  .t-num::after{animation:none;opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .t-num{animation:none}
}
.timeline h3{font-size:22px;margin-bottom:8px}
.timeline p{font-size:15px;color:var(--on-dark-2)}
.tile-foot{max-width:640px;margin:40px auto 0;font-size:14px;color:var(--on-dark-2)}

/* ==========================================================================
   Testimonials
   ========================================================================== */
.quotes .quote{margin:0;display:flex;flex-direction:column;gap:22px}
.quote blockquote{
  margin:0;font-size:clamp(16px,1.35vw,18px);line-height:1.5;letter-spacing:-.011em;
  font-weight:500;color:var(--ink);
}
.quote blockquote::before{content:'\201C'}
.quote blockquote::after{content:'\201D'}
.quote figcaption{
  margin-top:auto;display:flex;align-items:center;gap:13px;
  font-size:14px;color:var(--ink-2);padding-top:18px;border-top:1px solid var(--hair);
}
.quote-avatar{
  width:56px;height:56px;flex:none;border-radius:50%;object-fit:cover;
  background:var(--grey);
}
.quote-who{display:flex;flex-direction:column;gap:2px;min-width:0}
.quote figcaption strong{
  font-size:15px;font-weight:600;letter-spacing:.02em;
  color:transparent;background:var(--brand);-webkit-background-clip:text;background-clip:text;
}

/* ==========================================================================
   Plans
   ========================================================================== */
.mode-toggle{
  display:inline-flex;margin-top:36px;padding:4px;gap:4px;
  background:rgba(0,0,0,.06);border-radius:980px;
}
.mode-toggle button{
  font:inherit;font-size:15px;font-weight:500;color:var(--ink-2);
  padding:10px 22px;border:0;border-radius:980px;background:none;cursor:pointer;
  transition:color .25s ease,background .25s ease,box-shadow .25s ease;
}
.mode-toggle button:hover{color:var(--ink)}
.mode-toggle button[aria-selected="true"]{
  background:var(--btn);color:#fff;font-weight:600;
  box-shadow:0 4px 12px -6px rgba(134,52,200,.9);
}
/* The hover lift would otherwise repaint the selected pill in ink. */
.mode-toggle button[aria-selected="true"]:hover{color:#fff}

.plans .plan{display:flex;flex-direction:column;position:relative}
.plan h3{font-size:26px;margin-bottom:6px}
.plan-tag{font-size:15px;color:var(--ink-2)}
.plan .plan-price{
  margin-top:22px;padding-bottom:22px;border-bottom:1px solid var(--hair);
  font-size:27px;font-weight:600;letter-spacing:-.018em;color:var(--ink);
}
.plan-feats{list-style:none;margin:22px 0 0;padding:0;display:grid;gap:12px}
.plan-feats li{position:relative;padding-left:26px;font-size:15px;color:var(--ink-2)}
.plan-feats li::before{
  content:"";position:absolute;left:2px;top:.42em;width:11px;height:6px;
  border-left:2px solid var(--violet);border-bottom:2px solid var(--violet);
  transform:rotate(-45deg);
}
/* ------------------------------- TOOLTIP -------------------------------
   A term worth a sentence, without leaving the card for it. The browser's own
   title attribute is a grey box in the wrong typeface that never appears on a
   phone at all, so this is ours: shown on hover, on keyboard focus, and on a
   tap, which is the only one of the three a phone has.

   It is measured against the list item rather than the word, so it is exactly
   as wide as the line it belongs to and cannot hang off the side of the card
   at any width. The arrow is placed under the word by main.js, which is the
   one thing CSS cannot work out on its own. */
.tip{position:static}
.tip-word{
  font:inherit;color:inherit;background:none;border:0;padding:0;
  cursor:help;text-decoration:underline dotted;text-underline-offset:3px;
  text-decoration-color:rgba(0,0,0,.3);
  transition:color .18s ease,text-decoration-color .18s ease;
}
.tip-word:hover,
.tip-word[aria-expanded="true"]{color:var(--link);text-decoration-color:var(--link)}
.tip-body{
  position:absolute;left:0;right:0;bottom:calc(100% + 11px);z-index:5;
  padding:12px 15px;border-radius:14px;
  background:var(--ink);color:#f5f5f7;
  font-size:13.5px;line-height:1.5;text-align:left;
  box-shadow:0 18px 40px -20px rgba(0,0,0,.65);
  opacity:0;visibility:hidden;transform:translateY(4px);
  transition:opacity .18s ease,transform .18s cubic-bezier(.28,.11,.32,1),visibility .18s;
}
/* The point of the box, under the word it explains. */
.tip-body::after{
  content:"";position:absolute;top:100%;left:var(--tip-x,32px);
  margin-left:-6px;border:6px solid transparent;border-top-color:var(--ink);
}
.tip-word:hover + .tip-body,
.tip-word:focus-visible + .tip-body,
.tip-body.is-open{opacity:1;visibility:visible;transform:none}
@media (prefers-reduced-motion:reduce){
  .tip-body{transition:none}
}

/* One word is a small target next to a card this size, so the button keeps
   the width the longer label used to give it. */
.btn-plan{margin-top:28px;align-self:center;min-width:148px}
.plan-featured{box-shadow:0 0 0 2px var(--violet)}
.plan-badge{
  position:absolute;top:-11px;left:38px;background:var(--btn);color:#fff;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  padding:5px 12px;border-radius:980px;
}
.plans-foot{
  background:var(--grey);margin:0;padding:26px 22px 96px;text-align:center;
  font-size:14px;color:var(--ink-2);
  /* The features pill is taller than a text line, so open the leading enough
     that it does not crowd the line above it. */
  line-height:2.05;
}
/* The Most chosen badge overhangs the card, and the grid is clipped to paint
   its background edge to edge, so leave room for it inside the clip. */
/* The featured card's ring and the Most chosen badge both sit outside the card
   box, and the grid is clipped so its background can reach the viewport edges.
   Leave room on both sides of the clip or they get shaved off. */
.section-head-block + .grid.plans{padding-top:16px;padding-bottom:16px}

/* ==========================================================================
   Demo form
   ========================================================================== */
.form{
  max-width:760px;margin:48px auto 0;text-align:left;
  display:grid;grid-template-columns:1fr 1fr;gap:18px;
}
.field{display:flex;flex-direction:column;gap:7px}
.field-wide{grid-column:1 / -1}
.form label{font-size:14px;font-weight:600;letter-spacing:-.005em}
.form .tz{font-weight:400;color:var(--ink-2)}
.form input,.form select,.form textarea{
  font:inherit;font-size:17px;color:var(--ink);background:#fff;
  padding:12px 14px;border:1px solid var(--hair);border-radius:12px;width:100%;
  transition:border-color .2s ease,box-shadow .2s ease;
}
.form textarea{resize:vertical;min-height:110px}
.form input:focus,.form select:focus,.form textarea:focus{
  outline:none;border-color:var(--violet);box-shadow:0 0 0 4px rgba(156,101,255,.22);
}
.local-hint{font-size:14px;color:var(--ink-2);margin:0}
/* The button is the one thing to do here, so it sits in the middle of the
   form with its reassurance directly underneath. */
.form-actions{
  display:flex;flex-direction:column;align-items:center;gap:10px;
  margin-top:4px;text-align:center;
}
.form-note{font-size:13px;color:var(--ink-2)}
.form-msg{margin:0;font-size:15px;padding:13px 15px;border-radius:12px;display:none}
.form-msg.show{display:block}
.form-msg.ok{background:rgba(26,127,55,.1);color:#1a7f37}
/* The same red the wizard uses, so a problem looks the same wherever it is
   reported. */
.form-msg.bad{background:rgba(230,33,143,.1);color:#d3177f}

/* ==========================================================================
   Footer company details
   ========================================================================== */
/* The registered details on the left, and who we belong to on the right: two
   statements about the same company, so they share a line rather than each
   taking one. Below 640px the mark drops under the address. */
.footer-legal-block{
  border-top:1px solid rgba(0,0,0,.1);padding:22px 0;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px 24px;
}
.footer-legal-who{display:grid;gap:3px}
.footer-legal-block strong{color:var(--ink);font-weight:600}
.footer-bottom a{color:var(--link)}

@media (max-width:1068px){
  .timeline{grid-template-columns:1fr;max-width:640px}
}
@media (max-width:640px){
  .form{grid-template-columns:1fr;margin-top:36px}
  .mode-toggle{width:100%}
  .mode-toggle button{flex:1;padding:10px 12px;font-size:14px}
  .plan-badge{left:26px}
  .plans-foot{padding-bottom:72px}
}

.nav-logo-img{max-height:25.7px;width:auto;display:block}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* ==========================================================================
   Client logo strip
   A single track holding the set twice, shifted by exactly one set width so
   the loop is seamless. Travels left to right.
   ========================================================================== */
.logo-marquee{
  background:var(--grey);padding:8px 0 96px;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.logo-marquee-title{
  text-align:center;font-size:13px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-2);margin-bottom:30px;
}
.logo-track{display:flex;width:max-content;animation:logo-ltr 46s linear infinite}
.logo-marquee:hover .logo-track{animation-play-state:paused}
@keyframes logo-ltr{from{transform:translateX(-50%)}to{transform:translateX(0)}}

.logo-set{
  display:flex;align-items:center;gap:64px;list-style:none;margin:0;padding:0 32px;
}
.logo-set li{flex:none;display:flex;align-items:center;justify-content:center}
.logo-set img{
  /* Real logos arrive at every proportion, so cap both axes and let each keep
     its own ratio rather than forcing a width and squashing it. Shown in their
     own colours, at full strength. */
  max-width:170px;width:auto;height:auto;max-height:44px;object-fit:contain;
}

/* Without motion the strip becomes a plain scrollable row. */
@media (prefers-reduced-motion:reduce){
  .logo-marquee{overflow-x:auto;-webkit-mask-image:none;mask-image:none}
  .logo-track{animation:none;width:auto}
  .logo-set[aria-hidden="true"]{display:none}
}
@media (max-width:640px){
  .logo-marquee{padding-bottom:72px}
  .logo-set{gap:44px;padding-inline:22px}
  .logo-set img{max-width:132px;max-height:36px}
  .logo-track{animation-duration:34s}
}

/* ==========================================================================
   Demo modal
   ========================================================================== */
.modal{
  border:0;padding:0;background:transparent;overflow:visible;
  max-width:min(760px,calc(100vw - 40px));width:100%;
  max-height:calc(100vh - 48px);
  margin:auto;color:var(--ink);
}
.modal::backdrop{
  background:rgba(0,0,0,.42);
  backdrop-filter:saturate(140%) blur(14px);
  -webkit-backdrop-filter:saturate(140%) blur(14px);
}

.modal-card{
  position:relative;background:#fff;border-radius:26px;
  padding:52px 48px 44px;text-align:center;
  max-height:calc(100vh - 48px);overflow-y:auto;overscroll-behavior:contain;
  box-shadow:0 40px 90px -30px rgba(0,0,0,.45);
}
.modal-card h2{font-size:clamp(28px,3.4vw,40px);letter-spacing:-.018em}
.modal-sub{
  margin:14px auto 0;max-width:460px;
  font-size:clamp(17px,1.5vw,19px);line-height:1.4;color:var(--ink-2);
}
/* A lead that is a short list of steps, kept on one line. The dialog is a
   fixed 560px, so below that width it wraps like any other subhead. */
.modal-sub.is-oneline{max-width:none}

/* Who is running the demo, under the lead in the booking dialog. A card rather
   than a line of text: the point of it is the face, and a person named before
   the form is filled in is the difference between a booking and a form.

   One person carries the lead inside the pill. Two carry it once, above them
   both, because the same line printed twice reads as a mistake. */
.demo-hosts{
  display:flex;flex-direction:column;align-items:center;gap:10px;margin:20px 0 0;
}
.demo-hosts.is-pair{
  flex-direction:row;flex-wrap:wrap;justify-content:center;gap:12px;
}
.demo-host-lead-top{width:100%;text-align:center}
.demo-hosts.is-pair .demo-host{margin:0}
.demo-host{
  display:inline-flex;align-items:center;gap:16px;
  margin:0 auto;padding:9px 34px 9px 9px;
  border:1px solid var(--hair);border-radius:999px;background:#fff;
  text-align:left;
}
.demo-host-face{
  width:67px;height:67px;flex:none;border-radius:50%;overflow:hidden;
  display:grid;place-items:center;background:var(--brand);
  color:#fff;font-family:var(--mono);font-size:20px;font-weight:700;letter-spacing:.04em;
}
.demo-host-face img{width:100%;height:100%;object-fit:cover;display:block}
.demo-host-who{display:flex;flex-direction:column;gap:1px;min-width:0}
.demo-host-lead{
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-2);
}
.demo-host-who strong{font-size:15px;font-weight:600;color:var(--ink)}
.demo-host-role{font-size:13px;color:var(--ink-2)}
/* The address is a link, so it is worth a colour, but it sits under a name and
   a role and should not shout over either. */
.demo-host-mail{
  font-size:13px;color:var(--link);text-decoration:none;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.demo-host-mail:hover{text-decoration:underline}
@media (min-width:600px){
  .modal-sub.is-oneline{white-space:nowrap}
}

.modal .form{margin-top:34px}

/* ==========================================================================
   Sign up choices
   Shared by /signup and the Sign Up dialog, so the two cannot drift.
   ========================================================================== */
.su-choice{
  display:flex;align-items:center;gap:18px;width:100%;
  padding:20px 4px;border:0;border-top:1px solid var(--hair);
  background:none;text-align:left;cursor:pointer;color:inherit;
  transition:padding-left .25s cubic-bezier(.28,.11,.32,1);
}
.su-choice:hover{padding-left:10px}
.su-choice-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.su-choice strong{font-size:17px;font-weight:600;letter-spacing:-.012em}
.su-choice span{font-size:14px;color:var(--ink-2)}
.su-choice .su-go{
  width:38px;height:38px;flex:none;border-radius:50%;display:grid;place-items:center;
  border:1px solid var(--hair);transition:border-color .2s ease,background .2s ease;
}
.su-choice:hover .su-go{border-color:transparent;background:var(--btn)}
.su-choice .su-go svg{
  width:15px;height:15px;fill:none;stroke:var(--link);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;transition:stroke .2s ease;
}
.su-choice:hover .su-go svg{stroke:#fff}

/* In the dialog the rows sit under centred copy, so they need their own
   alignment back, and the first one carries the rule that separates it. */
.su-choices{margin-top:30px;text-align:left}
.su-choices .su-choice:first-child{border-top:1px solid var(--hair)}

/* ==========================================================================
   Sign up wizard
   Three steps inside the same dialog. Left aligned, because a form read down
   a centred column is hard to follow.
   ========================================================================== */
.wiz{text-align:left;margin-top:26px}
.wiz-steps{display:flex;gap:7px;justify-content:center;margin-bottom:22px}
.wiz-dot{
  width:34px;height:4px;border-radius:2px;background:var(--hair);
  transition:background .3s ease;
}
.wiz-dot.is-on{background:var(--btn)}
.wiz-title{font-size:20px;font-weight:600;letter-spacing:-.014em;margin-bottom:18px}
.wiz-title.is-centred{text-align:center}
.wiz-h{
  font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-2);margin:24px 0 10px;
}

.wiz-field{display:flex;flex-direction:column;gap:5px;min-width:0}
.wiz-field > span{font-size:13px;font-weight:600;color:var(--ink-2)}
.wiz-field input,
.wiz-field select,
.wiz-phone input,
.wiz-phone select{
  width:100%;font:inherit;font-size:16px;padding:11px 13px;color:var(--ink);
  border:1px solid var(--hair);border-radius:12px;background:#fff;
  transition:border-color .2s ease,box-shadow .2s ease;
}
.wiz-field input:focus,
.wiz-field select:focus,
.wiz-phone input:focus,
.wiz-phone select:focus{
  outline:none;border-color:var(--violet);box-shadow:0 0 0 3px rgba(156,101,255,.18);
}
.wiz-mono{font-family:var(--mono);letter-spacing:.06em;text-transform:uppercase}

.wiz-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.wiz-wide{margin-top:14px}
.wiz-rows{display:flex;flex-direction:column;gap:12px}
.wiz-row{display:grid;gap:12px;align-items:end}
.wiz-row-2{grid-template-columns:1fr 1fr}
.wiz-row-3{grid-template-columns:1fr 1fr 1fr}
.wiz-row-4{grid-template-columns:1fr 1fr 1fr 1fr}

.wiz-phone{display:grid;grid-template-columns:auto minmax(0,1fr);gap:6px}
/* The dial code takes what it needs and no more: twelve digits have to fit
   beside it without the field scrolling. */
.wiz-phone select{width:auto;padding-inline:8px;font-size:15px}
.wiz-phone input{padding-inline:11px}

.wiz-card{
  border:1px solid var(--hair);border-radius:16px;padding:16px;margin-bottom:14px;
  display:flex;flex-direction:column;gap:12px;
}

.wiz-modes{display:flex;gap:6px;padding:4px;background:rgba(0,0,0,.06);border-radius:980px}
.wiz-mode{
  flex:1;font:inherit;font-size:14px;font-weight:500;color:var(--ink-2);
  padding:9px 10px;border:0;border-radius:980px;background:none;cursor:pointer;
  transition:color .25s ease,background .25s ease;
}
.wiz-mode.is-on{background:var(--btn);color:#fff;font-weight:600}

.wiz-plans{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.wiz-plan{
  font:inherit;text-align:left;cursor:pointer;padding:12px;
  border:1px solid var(--hair);border-radius:12px;background:#fff;
  display:flex;flex-direction:column;gap:3px;color:var(--ink);
  transition:border-color .2s ease,box-shadow .2s ease;
}
.wiz-plan strong{font-size:15px;font-weight:600}
.wiz-plan-price{font-size:13px;color:var(--link);font-weight:600}
.wiz-plan-tag{font-size:11px;color:var(--ink-2);line-height:1.3}
.wiz-plan.is-on{border-color:var(--violet);box-shadow:0 0 0 3px rgba(156,101,255,.18)}

/* Address suggestions. Markup of our own inside the dialog rather than the
   dropdown Google appends to <body>, which a modal dialog's top layer puts
   out of reach. Same face as the listbox on the selects above it. */
.wiz-ac-host{position:relative}
.wiz-ac{
  position:absolute;left:0;right:0;top:100%;z-index:5;
  margin:6px 0 0;padding:6px;list-style:none;
  background:rgba(255,255,255,.96);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border:1px solid rgba(0,0,0,.08);border-radius:14px;
  box-shadow:0 18px 44px -12px rgba(0,0,0,.3),0 2px 6px rgba(0,0,0,.08);
  max-height:264px;overflow-y:auto;overscroll-behavior:contain;
  opacity:0;transform:translateY(-6px) scale(.98);transform-origin:top center;
  transition:opacity .18s ease,transform .18s cubic-bezier(.28,.11,.32,1);
}
.wiz-ac.open{opacity:1;transform:none}
.wiz-ac-opt{
  display:flex;flex-direction:column;gap:2px;
  padding:9px 11px;border-radius:9px;cursor:pointer;
}
.wiz-ac-opt strong{font-size:15px;font-weight:500;color:var(--ink)}
.wiz-ac-opt span{font-size:13px;color:var(--ink-2)}
.wiz-ac-opt.active,
.wiz-ac-opt:hover{background:rgba(156,101,255,.12)}

.wiz-add{
  font:inherit;font-size:14px;font-weight:600;color:var(--link);
  background:none;border:0;padding:8px 0;cursor:pointer;
}
.wiz-add::before{content:"+ ";font-weight:700}
.wiz-remove{
  width:34px;height:34px;flex:none;border:1px solid var(--hair);border-radius:50%;
  background:#fff;color:var(--ink-2);font-size:18px;line-height:1;cursor:pointer;
  align-self:end;margin-bottom:3px;
}
.wiz-remove:hover{border-color:var(--bad,#b3261e);color:#b3261e}

.wiz-msg{margin-top:16px;font-size:15px;display:none}
.wiz-msg.show{display:block}
/* Something to fix before the next step, so it is a block rather than a line
   of text: the application's magenta, tinted behind it, and deepened a shade
   for the words themselves so they carry at body size. */
.wiz-msg.bad{
  color:#d3177f;background:rgba(230,33,143,.1);
  padding:11px 14px;border-radius:12px;
}
.wiz-msg.ok{color:var(--ink-2)}

.wiz-foot{display:flex;gap:10px;justify-content:flex-end;margin-top:22px}
.btn-quiet-wide{
  font:inherit;font-size:16px;font-weight:500;color:var(--link);
  padding:12px 22px;border:1px solid var(--hair);border-radius:980px;
  background:none;cursor:pointer;transition:border-color .2s ease;
}
.btn-quiet-wide:hover{border-color:var(--violet)}
/* The declaration the account rests on. A real checkbox, painted in the brand
   colour, because a styled span is a checkbox nobody can use with a keyboard. */
/* Email, role and phone on one row: the role is a word or two, the number
   needs its dial code beside it, so they do not want equal thirds. */
.wiz-row-me{grid-template-columns:1.2fr .72fr 1.3fr}
@media (max-width:640px){
  .wiz-row-me{grid-template-columns:1fr}
}

.wiz-check{
  display:flex;align-items:flex-start;gap:11px;margin-top:18px;
  font-size:15px;line-height:1.45;color:var(--ink-2);cursor:pointer;
  padding:12px 14px;border:1px solid var(--hair);border-radius:12px;
}
.wiz-check input{
  flex:none;width:19px;height:19px;margin:1px 0 0;accent-color:#bf3cf1;cursor:pointer;
}
.wiz-check[aria-invalid="true"]{
  border-color:#e6218f;box-shadow:0 0 0 3px rgba(230,33,143,.18);
}

.wiz-done{font-size:17px;line-height:1.5;color:var(--ink-2);text-align:center}
/* Nothing left to do on this step but leave. */
/* A button is inline-flex, and auto margins do nothing to an inline box: it
   has to be block level before the two of them can centre it. */
.wiz-close{display:flex;width:fit-content;margin:26px auto 6px}

/* The done mark. Both strokes are drawn rather than faded: the ring sweeps
   round first, then the tick is written through it. Shared by the wizard's
   last step and the booked demo. */
.wiz-tick,
.done-tick{width:72px;height:72px;margin:6px auto 22px;display:block}
.wiz-tick svg,
.done-tick svg{width:100%;height:100%;display:block}
.wiz-tick-ring,
.done-tick-ring{
  stroke-dasharray:139;stroke-dashoffset:139;
  animation:wiz-draw .6s cubic-bezier(.4,0,.2,1) forwards;
}
.wiz-tick-path,
.done-tick-path{
  stroke-dasharray:34;stroke-dashoffset:34;
  animation:wiz-draw .34s cubic-bezier(.4,0,.2,1) .48s forwards;
}
@keyframes wiz-draw{to{stroke-dashoffset:0}}
@media (prefers-reduced-motion:reduce){
  .wiz-tick-ring,.wiz-tick-path,
  .done-tick-ring,.done-tick-path{animation:none;stroke-dashoffset:0}
}

/* A step of its own once the demo is booked: the form is gone and this is all
   that is left in the dialog. */
.done{
  display:flex;flex-direction:column;align-items:center;
  padding:22px 0 6px;text-align:center;
}
.done-text{
  margin:0 auto 26px;max-width:420px;
  font-size:17px;line-height:1.5;color:var(--ink-2);
}

/* The wizard needs more room than the two choices it replaces. */
#signupModal:has(#signupWizard:not([hidden])){max-width:min(760px,calc(100vw - 40px))}

@media (max-width:640px){
  .wiz-grid,.wiz-row-2,.wiz-row-3,.wiz-row-4{grid-template-columns:1fr}
  .wiz-plans{grid-template-columns:1fr}
  .wiz-remove{align-self:start;margin-bottom:0}
  .wiz-foot{flex-direction:column-reverse}
  .wiz-foot .btn,.btn-quiet-wide{width:100%;justify-content:center}
}

/* A field that needs fixing wears the same magenta as the message above it,
   and keeps it while it is focused: this comes after the focus rules and names
   focus itself, or the focus ring would paint over the very thing being
   pointed at. */
.form input[aria-invalid="true"],
.form select[aria-invalid="true"],
.form input[aria-invalid="true"]:focus,
.form select[aria-invalid="true"]:focus,
.wiz-field input[aria-invalid="true"],
.wiz-field select[aria-invalid="true"],
.wiz-field input[aria-invalid="true"]:focus,
.wiz-field select[aria-invalid="true"]:focus{
  border-color:#e6218f;box-shadow:0 0 0 3px rgba(230,33,143,.18);
}

.modal-close{
  position:absolute;top:18px;right:18px;width:34px;height:34px;
  display:grid;place-items:center;border:0;border-radius:50%;cursor:pointer;
  background:rgba(0,0,0,.05);color:var(--ink-2);
  transition:background .2s ease,color .2s ease;
}
.modal-close:hover{background:rgba(0,0,0,.1);color:var(--ink)}
/* No coloured ring on the close button. Keyboard focus still has to show, so
   it deepens the button's own tint instead of drawing the violet outline the
   rest of the page uses. */
.modal-close:focus-visible{
  outline:none;background:rgba(0,0,0,.16);color:var(--ink);
}
.modal-close svg{width:15px;height:15px;fill:none;stroke:currentColor;
  stroke-width:1.9;stroke-linecap:round}

/* Apple-ish entrance: a short rise with an eased settle. */
.modal[open]{animation:modal-in .38s cubic-bezier(.32,.72,0,1)}
.modal[open]::backdrop{animation:backdrop-in .38s ease}
@keyframes modal-in{from{opacity:0;transform:translateY(18px) scale(.97)}
                    to{opacity:1;transform:none}}
@keyframes backdrop-in{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){
  .modal[open],.modal[open]::backdrop{animation:none}
}

html.modal-open,body.modal-open{overflow:hidden}

@media (max-width:640px){
  /* Every dialog is a sheet the width of the screen here. The wider ones name
     themselves again, and the wizard by its id, because a width set further
     down the stylesheet would otherwise win and leave the sheet floating in a
     corner of the screen. */
  .modal,
  .modal.modal-wide,
  .modal.modal-about,
  .modal.modal-mod,
  .modal.modal-narrow,
  #signupModal,
  #signupModal:has(#signupWizard:not([hidden])){
    max-width:100%;width:100%;
    margin:0;position:fixed;
    /* A fifth of the screen is left above it. A sheet that covers the whole
       phone reads as a page you have navigated to, and it stops being obvious
       that the site is still underneath and one tap away. Height rather than
       bottom, because an absolutely positioned box with both a top and a
       height ignores the bottom it was given. */
    top:20%;right:0;left:0;bottom:0;
    height:80%;max-height:80%;
  }
  .modal-card{
    border-radius:22px 22px 0 0;padding:44px 22px 32px;
    min-height:100%;max-height:100%;margin-top:auto;
  }
  .modal[open]{animation:sheet-in .4s cubic-bezier(.32,.72,0,1)}
  @keyframes sheet-in{from{transform:translateY(4%);opacity:0}to{transform:none;opacity:1}}
}

/* ==========================================================================
   Selects and date fields
   The native control paints its own chevron and sizing, which does not match
   the rest of the form, so we suppress it and draw our own.
   ========================================================================== */
.form select{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  padding-right:44px;cursor:pointer;
  background-color:#fff;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7' fill='none'%3E%3Cpath d='M1 1l4.5 4.5L10 1' stroke='%236e6e73' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 16px center;
  background-size:11px 7px;
  text-overflow:ellipsis;
}
.form select::-ms-expand{display:none}
.form select:hover{border-color:rgba(0,0,0,.24)}
.form select:focus{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7' fill='none'%3E%3Cpath d='M1 1l4.5 4.5L10 1' stroke='%239c65ff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
/* A select showing its "Select..." option reads as placeholder text. */
.form select:has(option[value=""]:checked){color:var(--ink-2)}

/* Match the date field to the rest: same box, a calmer picker button. */
.form input[type="date"]{cursor:pointer}
.form input[type="date"]::-webkit-calendar-picker-indicator{
  cursor:pointer;opacity:.45;transition:opacity .2s ease;
}
.form input[type="date"]:hover::-webkit-calendar-picker-indicator,
.form input[type="date"]:focus::-webkit-calendar-picker-indicator{opacity:.85}
.form input[type="date"]::-webkit-datetime-edit{color:var(--ink)}
.form input:hover,.form textarea:hover{border-color:rgba(0,0,0,.24)}

/* ==========================================================================
   AI planning
   ========================================================================== */
.ai-stage{margin:56px auto 0;max-width:920px}
/* Light, like the product: a white sheet, grey programme blocks and a couple
   of saturated categories, rather than the dark mock this started as. */
.ai-card{
  background:#fff;border:1px solid var(--hair);border-radius:var(--r-lg);
  overflow:hidden;text-align:left;
  box-shadow:0 30px 70px -30px rgba(0,0,0,.28),0 2px 8px rgba(0,0,0,.06);
  color:var(--ink);
}
.ai-bar{
  display:flex;align-items:center;gap:12px;padding:15px 20px;
  border-bottom:1px solid var(--hair);
}
.ai-spark{
  width:26px;height:26px;flex:none;border-radius:8px;display:grid;place-items:center;
  background:var(--btn);
}
.ai-spark svg{width:14px;height:14px;fill:#fff}
.ai-prompt{
  flex:1;min-width:0;font-size:13px;color:var(--ink-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.ai-state{
  font-family:var(--mono);font-size:11px;letter-spacing:.07em;
  color:var(--link);flex:none;
}

/* The planner grid, drawn the way the product shows it: an hour gutter, day
   columns headed by name and date, and blocks that butt up against each other
   rather than floating. Most of a real grid is neutral, with a few programmes
   carrying colour, so the palette stays mostly grey. */
.planner{display:flex;gap:10px;padding:18px 20px 20px;position:relative}

/* The grid dims behind this while it is putting itself together, and the mark
   goes out once it has. Same cycle as the blocks, so it returns when they
   scatter and rebuild. */
.pb-wiz{
  position:absolute;inset:0;z-index:3;pointer-events:none;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  background:rgba(255,255,255,.66);opacity:0;
}
.ai-stage.in .pb-wiz{animation:pb-wiz 14s linear infinite}
@keyframes pb-wiz{
  0%,28.57%   {opacity:1}
  31.5%,95%   {opacity:0}
  100%        {opacity:1}
}
/* Three marks rather than one in a tile, set in a triangle and each breathing
   at its own pace. */
.pb-wiz-stars{position:relative;width:66px;height:58px}
.pb-wiz-stars svg{
  position:absolute;fill:var(--violet);
  animation:pb-wiz-pulse 1.5s ease-in-out infinite;
}
/* the point of the triangle */
.pb-wiz-stars svg:nth-child(1){
  width:34px;height:34px;top:0;left:50%;margin-left:-17px;fill:var(--pink);
}
/* and its feet */
.pb-wiz-stars svg:nth-child(2){width:22px;height:22px;bottom:0;left:0;animation-delay:.5s}
.pb-wiz-stars svg:nth-child(3){width:26px;height:26px;bottom:2px;right:0;animation-delay:1s}
/* A filled label rather than a line of type: it sits over a busy grid and has
   to be read at a glance. */
.pb-wiz-txt{
  font-family:var(--mono);font-size:13px;letter-spacing:.06em;
  color:#fff;background:var(--btn);padding:8px 18px;border-radius:980px;
  box-shadow:0 12px 26px -12px rgba(134,52,200,.85);
}
/* The three dots run while it is thinking. */
.pb-wiz-txt i{font-style:normal;opacity:.3;animation:pb-wiz-dot 1.2s ease-in-out infinite}
.pb-wiz-txt i:nth-of-type(2){animation-delay:.2s}
.pb-wiz-txt i:nth-of-type(3){animation-delay:.4s}
@keyframes pb-wiz-dot{
  0%,60%,100%{opacity:.3}
  30%        {opacity:1}
}
@keyframes pb-wiz-pulse{
  0%,100%{transform:scale(.62);opacity:.5}
  50%    {transform:scale(1);opacity:1}
}

.phours{
  display:flex;flex-direction:column;flex:none;width:44px;
  font-family:var(--mono);font-size:9px;color:#8e8e93;padding-top:34px;
  /* Wide enough for a full hh:mm without the column wrapping. */
}
.phours-tz{margin-bottom:6px;color:#a1a1a6}
.phours span{flex:1;line-height:1}

.pgrid{flex:1;min-width:0;display:grid;grid-template-columns:repeat(7,1fr);gap:6px;
  overflow:hidden}
.pcol{display:flex;flex-direction:column}
.pcol-head{
  display:flex;align-items:center;justify-content:center;gap:5px;
  padding-bottom:8px;margin-bottom:4px;border-bottom:1px solid var(--hair);
}
.pday{font-family:var(--mono);font-size:9px;letter-spacing:.08em;color:#8e8e93}
.pdate{font-size:12px;font-weight:600;color:var(--ink)}
/* Today, drawn the way the product draws it: a filled violet disc with the
   date reversed out and a green status dot on its shoulder. */
.pdate.is-today{
  position:relative;width:22px;height:22px;border-radius:50%;
  display:inline-grid;place-items:center;
  background:#8b7cf0;color:#fff;font-size:11px;
}
.pdate.is-today::after{
  content:"";position:absolute;top:0;right:0;width:6px;height:6px;
  border-radius:50%;background:#34d399;box-shadow:0 0 0 1.5px #fff;
}

/* Columns are stretched to the tallest one by the grid, so a filler at the
   foot of each takes up whatever is left and the week reads as fully planned
   instead of trailing off into white. */
.pb-fill{flex:1;min-height:0;height:auto!important;margin-bottom:0}

.pb{
  display:block;height:calc(var(--h) * 6px);margin-bottom:1px;
  border-radius:2px;border-left:2px solid transparent;
  padding:3px 4px 0;overflow:hidden;
  opacity:0;transform:translateY(-4px);
}
.pb em{
  display:block;height:2px;border-radius:1px;
  background:rgba(0,0,0,.3);margin-bottom:3px;
}
.pb em:nth-child(2){width:62%;background:rgba(0,0,0,.16)}

/* Most of a real week is ordinary programming, drawn in grey. Colour marks the
   categories, and one block carries the violet edge the product uses for a
   flagged item. */
.pb-n{background:#d4d4d6;border-left-color:#bcbcc0}
.pb-r{background:#c9c9cc;border-left-color:#a9a9ae}
.pb-m{background:#ff1fa8;border-left-color:#d1017f}
.pb-b{background:#00b0f0;border-left-color:#0089bd}
.pb-v{background:#d4d4d6;border-left-color:#7b5cfa}
.pb-c{background:#f2a33c;border-left-color:#c97d18}

/* The saturated blocks need their rules the other way round. */
.pb-m em,.pb-b em{background:rgba(255,255,255,.62)}
.pb-m em:nth-child(2),.pb-b em:nth-child(2){background:rgba(255,255,255,.34)}
.pb-c em{background:rgba(0,0,0,.34)}
.pb-c em:nth-child(2){background:rgba(0,0,0,.2)}

/* The whole thing is one fourteen second cycle: the grid settles out of
   nowhere over the first four seconds, then a block is carried across and
   back, then it fades out and settles again.

   Each block arrives from an offset of its own, handed over as --rx and --ry
   by main.js so the scatter is different on every load rather than a pattern
   baked into the stylesheet. */
.ai-stage.in .pb{
  animation:pb-settle 14s cubic-bezier(.28,.11,.32,1) var(--rd,0s) infinite;
}
/* Each block takes about two thirds of a second to arrive, and starts whenever
   its own --rd says: the four seconds of settling are a hundred of
   these landing one after another in no order at all. */
@keyframes pb-settle{
  0%          {opacity:0;transform:translate(var(--rx,0px),var(--ry,0px)) scale(.94)}
  5%,92.86%   {opacity:1;transform:none}
  100%        {opacity:0;transform:translate(var(--rx,0px),var(--ry,0px)) scale(.94)}
}

/* The carried block and the ones that part for it have to stay in step with
   each other, so their timing cannot be randomised. They fade in on their own
   schedule instead, opacity only, leaving transform to the animation that
   carries them. */
@keyframes pb-appear{
  0%          {opacity:0}
  5%,92.86%   {opacity:1}
  100%        {opacity:0}
}

/* A block being picked up, carried a column across and set down, then taken
   back where it came from. The block's own width is a column's width, so
   100% plus the grid gap lands it exactly one column over at any size, and
   the flex column holds its slot open while it is away.

   It runs alongside pb-in rather than instead of it: two animations touching
   transform means the later one wins while it is running, and this one has a
   delay long enough that the grid has finished filling before it starts. */
.pb-drag{position:relative;z-index:2}
.ai-stage.in .pb-drag{
  animation:
    pb-appear 14s linear var(--rd,0s) infinite,
    pb-drag 14s cubic-bezier(.4,0,.2,1) infinite;
}
/* The blocks below the landing slot part to make room while one is carried in,
   and close up again once it has gone. Timed off the same nine second cycle:
   open just before the drop, hold while it sits there, close once it is lifted
   back out. */
.ai-stage.in .pb-part{
  animation:
    pb-appear 14s linear var(--rd,0s) infinite,
    pb-part 14s cubic-bezier(.4,0,.2,1) infinite;
}
/* Parting once over the same fourteen seconds, transform only. */
@keyframes pb-part{
  0%,36.93%       {transform:none}
  47.86%,69.71%   {transform:translateY(var(--sy))}
  81.28%,100%     {transform:none}
}

/* The carried block, transform only: four seconds still while the grid builds
   itself, then taken across and back once, then it fades with the rest. The
   nine second sequence is mapped into 28.57-92.86% of the fourteen. */
@keyframes pb-drag{
  0%,28.57%       {transform:none;box-shadow:none}
  31.79%          {transform:none;box-shadow:none}
  35.64%          {transform:scale(1.07) rotate(-1.2deg);
                   box-shadow:0 12px 24px -8px rgba(0,0,0,.75)}
  47.21%          {transform:translate(calc(100% + 6px),var(--dy,16px)) scale(1.07) rotate(-1.2deg);
                   box-shadow:0 12px 24px -8px rgba(0,0,0,.75)}
  51.07%,65.21%   {transform:translate(calc(100% + 6px),var(--dy,16px));box-shadow:none}
  69.07%          {transform:translate(calc(100% + 6px),var(--dy,16px)) scale(1.07) rotate(1.2deg);
                   box-shadow:0 12px 24px -8px rgba(0,0,0,.75)}
  80.64%          {transform:scale(1.07) rotate(1.2deg);
                   box-shadow:0 12px 24px -8px rgba(0,0,0,.75)}
  84.5%,92.86%   {transform:none;box-shadow:none}
}
}
}

@media (prefers-reduced-motion:reduce){
  .pb{opacity:1;transform:none}
  .ai-stage.in .pb,
  .ai-stage.in .pb-drag,
  .ai-stage.in .pb-part{animation:none}
  .pb-wiz,
  .ai-stage.in .pb-wiz{animation:none;opacity:0}
  .pb-wiz-stars svg,
  .pb-wiz-txt i{animation:none}
}

.ai-foot{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;
  padding:15px 20px;border-top:1px solid var(--hair);
}
/* Pushed to the far end of the row, so the counted result reads as the
   outcome of the chips beside it. */
.ai-done{font-size:13px;color:var(--ink);margin-inline-start:auto}
.ai-done b{font-family:var(--mono);font-weight:500;color:var(--link)}
.ai-chip{
  font-family:var(--mono);font-size:11px;padding:5px 11px;border-radius:980px;
  border:1px solid var(--hair);color:var(--ink-2);
}

.ai-points{
  list-style:none;margin:56px auto 0;padding:0;max-width:var(--grid);
  display:grid;grid-template-columns:repeat(4,1fr);gap:30px 24px;text-align:left;
}
.ai-points li{display:flex;flex-direction:column;gap:6px;
  border-top:1px solid var(--hair);padding-top:18px}
.ai-points strong{font-size:18px;font-weight:600;letter-spacing:-.01em}
.ai-points span{font-size:15px;color:var(--ink-2)}

@media (prefers-reduced-motion:reduce){
}
@media (max-width:1068px){
  .ai-points{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:640px){
  /* The chips wrap here, and a result pushed to the far end lands beside one
     of them and reads as its label. Give it the width. */
  .ai-foot{justify-content:center;padding:13px 16px}
  .ai-done{margin-inline-start:0;flex-basis:100%;text-align:center}
  .planner{padding:14px 12px 16px;gap:6px}
  .phours{width:30px;font-size:8px}
  .pgrid{gap:3px}
  .pb{height:calc(var(--h) * 4px);padding:2px 2px 0}
  .pb em{display:none}
  .pdate{font-size:10px}
  .ai-points{grid-template-columns:1fr;margin-top:44px}
  .ai-bar{flex-wrap:wrap}
  .ai-prompt{order:3;flex-basis:100%;white-space:normal}
}
/* Seven columns and a day name in each is more than 320px holds: the dates
   alone still say which column is which. */
@media (max-width:340px){
  .pday{display:none}
}

/* ==========================================================================
   Custom select
   The native popup is drawn by the OS and cannot be styled, so JS swaps in a
   listbox. The real <select> stays in the DOM as the source of truth, and the
   whole thing falls back to the native control when JS does not run.
   ========================================================================== */
.sel{position:relative}
.sel-native{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;
  clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;pointer-events:none;
}
.sel-btn{
  display:flex;align-items:center;gap:10px;width:100%;
  font:inherit;font-size:17px;color:var(--ink);text-align:left;cursor:pointer;
  background:#fff;padding:12px 44px 12px 14px;
  border:1px solid var(--hair);border-radius:12px;
  transition:border-color .2s ease,box-shadow .2s ease;
}
.sel-btn:hover{border-color:rgba(0,0,0,.24)}
.sel-btn[aria-expanded="true"],
.sel-btn:focus-visible{
  outline:none;border-color:var(--violet);box-shadow:0 0 0 4px rgba(156,101,255,.22);
}
.sel-btn .sel-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sel-btn.is-placeholder .sel-label{color:var(--ink-2)}
.sel-btn .sel-chev{
  position:absolute;right:16px;top:50%;width:11px;height:7px;margin-top:-3px;
  fill:none;stroke:var(--ink-2);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;
  transition:transform .25s cubic-bezier(.28,.11,.32,1),stroke .2s ease;
}
.sel-btn[aria-expanded="true"] .sel-chev{transform:rotate(180deg);stroke:var(--violet)}
.field[aria-invalid="true"] .sel-btn,.sel-btn[aria-invalid="true"]{border-color:#e6218f}

.sel-list{
  position:fixed;z-index:60;margin:0;padding:6px;list-style:none;
  background:rgba(255,255,255,.92);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border:1px solid rgba(0,0,0,.08);border-radius:14px;
  box-shadow:0 18px 44px -12px rgba(0,0,0,.3),0 2px 6px rgba(0,0,0,.08);
  max-height:264px;overflow-y:auto;overscroll-behavior:contain;
  opacity:0;transform:translateY(-6px) scale(.98);transform-origin:top center;
  transition:opacity .18s ease,transform .18s cubic-bezier(.28,.11,.32,1);
}
.sel-list.up{transform-origin:bottom center;transform:translateY(6px) scale(.98)}
.sel-list.open{opacity:1;transform:none}
.sel-opt{
  display:flex;align-items:center;gap:9px;
  padding:9px 12px 9px 10px;border-radius:9px;
  font-size:16px;color:var(--ink);cursor:pointer;white-space:nowrap;
}
.sel-opt .sel-tick{
  width:14px;height:14px;flex:none;fill:none;stroke:currentColor;
  stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;opacity:0;
}
.sel-opt[aria-selected="true"]{font-weight:500}
.sel-opt[aria-selected="true"] .sel-tick{opacity:1;stroke:var(--link)}
.sel-opt.active{background:var(--btn);color:#fff}
.sel-opt.active .sel-tick{stroke:#fff}
.sel-opt.is-placeholder{color:var(--ink-2)}
.sel-opt.active.is-placeholder{color:#fff}

/* The filter above a long list. Pinned to the top of the scroller, so it is
   still there once you are two hundred countries down. */
.sel-search{
  position:sticky;top:-6px;z-index:1;
  margin:-6px -6px 6px;padding:6px 6px 7px;
  background:#fff;border-bottom:1px solid rgba(0,0,0,.07);
  border-radius:14px 14px 0 0;
}
.sel-search-in{
  width:100%;font:inherit;font-size:15px;color:var(--ink);
  padding:8px 11px;border:1px solid var(--hair);border-radius:9px;background:#fff;
}
.sel-search-in:focus{
  outline:none;border-color:var(--violet);box-shadow:0 0 0 3px rgba(156,101,255,.18);
}
.sel-empty{padding:9px 12px;font-size:15px;color:var(--ink-2)}

@media (prefers-reduced-motion:reduce){
  .sel-list{transition:none}
  .sel-btn .sel-chev{transition:none}
}

/* ==========================================================================
   Date picker
   ========================================================================== */
.cal-ico{width:15px;height:15px;margin-top:-7.5px;transform:none!important;
  stroke:var(--ink-2);stroke-width:1.7}
.sel-btn[aria-expanded="true"] .cal-ico{stroke:var(--violet)}

.cal{padding:14px;min-width:274px;max-height:none;overflow:visible}
.cal-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:12px}
.cal-title{font-size:15px;font-weight:600;letter-spacing:-.01em}
.cal-nav{
  width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:50%;
  background:none;cursor:pointer;color:var(--ink-2);transition:background .2s ease,color .2s ease;
}
.cal-nav:hover:not(:disabled){background:rgba(0,0,0,.06);color:var(--ink)}
.cal-nav:disabled{opacity:.28;cursor:not-allowed}
.cal-nav svg{width:8px;height:12px;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}

.cal-dows{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}
.cal-dows span{
  text-align:center;font-size:11px;font-weight:600;letter-spacing:.04em;
  color:var(--ink-2);padding:4px 0;
}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.cal-day{
  aspect-ratio:1;display:grid;place-items:center;border:0;border-radius:50%;
  background:none;cursor:pointer;font:inherit;font-size:14px;color:var(--ink);
  transition:background .18s ease,color .18s ease;
}
.cal-day:hover:not(:disabled):not(.sel){background:rgba(0,0,0,.06)}
.cal-day:disabled{color:rgba(0,0,0,.22);cursor:not-allowed}
.cal-day.today:not(.sel){box-shadow:inset 0 0 0 1.5px var(--hair);font-weight:600}
.cal-day.sel{background:var(--btn);color:#fff;font-weight:600}
.cal-day:focus-visible{outline:2px solid var(--violet);outline-offset:1px}

@media (max-width:640px){
  .cal{min-width:0;width:calc(100vw - 40px);max-width:320px}
}

/* ==========================================================================
   Independent scheduling
   One source fanning out to three destinations. The connector is built from
   plain elements rather than an SVG so it stretches with the grid instead of
   distorting, and it collapses to a single stem once the cards stack.
   ========================================================================== */
.tile-grey{background:var(--grey);color:var(--ink)}

.flow{max-width:1000px;margin:56px auto 0}
.flow-src{
  max-width:420px;margin-inline:auto;
  background:#1c1c1e;color:var(--on-dark);border-radius:var(--r-lg);
  padding:26px 28px;display:flex;flex-direction:column;gap:5px;align-items:center;
  text-align:center;box-shadow:0 22px 50px -30px rgba(0,0,0,.6);
}
.flow-src strong{font-size:23px;font-weight:600;letter-spacing:-.016em}
.flow-note{font-size:13px;color:var(--on-dark-2)}

.flow-in{
  max-width:420px;margin-inline:auto;background:#fff;
  border:1px solid var(--hair);border-radius:var(--r-lg);
  padding:22px 26px;display:flex;flex-direction:column;align-items:center;gap:4px;
  text-align:center;
}
.flow-in-icon{margin-bottom:8px}
.flow-in strong{font-size:18px;font-weight:600;letter-spacing:-.012em}
.flow-note-light{font-size:13px;color:var(--ink-2)}

.flow-connect{position:relative;height:58px}
.flow-connect span{position:absolute;background:rgba(156,101,255,.45)}
.flow-trunk{left:50%;top:0;width:2px;height:24px;margin-left:-1px}
.flow-bar{left:16.667%;right:16.667%;top:23px;height:2px}
.flow-drop{left:var(--x);top:23px;width:2px;height:35px;margin-left:-1px}

/* A single stem where there is nothing to fan out to. This has to come after
   .flow-connect: the two match with the same weight, so the later one wins,
   and while it was declared first the box stayed 58px tall around a 40px stem
   and the line stopped short of the card below it. */
.flow-connect-single{height:40px}
.flow-connect-single .flow-trunk{height:100%}

/* A pulse running the length of each connector, so the diagram reads as
   something flowing rather than as wiring. The line itself stays put; only
   this highlight travels. */
.flow-connect span{overflow:hidden}
.flow-connect span::after{
  content:"";position:absolute;inset:0;background-repeat:no-repeat;
}
.flow-trunk::after,
.flow-drop::after{
  background-image:linear-gradient(180deg,transparent,rgba(253,15,255,.95),transparent);
  background-size:100% 55%;
  animation:flow-pulse-y 2.8s linear infinite var(--pd,0s);
}
.flow-bar::after{
  background-image:linear-gradient(90deg,transparent,rgba(253,15,255,.95),transparent);
  background-size:38% 100%;
  animation:flow-pulse-x 2.8s linear infinite var(--pd,.55s);
}
@keyframes flow-pulse-y{from{background-position:0 -60%}to{background-position:0 160%}}
@keyframes flow-pulse-x{from{background-position:-40% 0}to{background-position:140% 0}}

@media (prefers-reduced-motion:reduce){
  .flow-connect span::after{animation:none;opacity:0}
}

.flow-outs{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.flow-out{
  position:relative;background:#fff;border:1px solid var(--hair);border-radius:var(--r-lg);
  padding:26px 24px;display:flex;flex-direction:column;gap:6px;text-align:center;
  align-items:center;
}
.flow-out strong{font-size:17px;font-weight:600;letter-spacing:-.012em}
.flow-out span{font-size:14px;color:var(--ink-2);line-height:1.45}
.flow-out.is-own{border-color:transparent;box-shadow:0 0 0 2px var(--violet)}
.indep-points{max-width:1000px}

@media (max-width:820px){
  .flow-outs{grid-template-columns:1fr;max-width:420px;margin-inline:auto}
  /* Stacked cards make a fan meaningless: keep a single stem. */
  .flow-connect,
  .flow-connect-single{height:34px}
  .flow-bar,.flow-drop{display:none}
  .flow-trunk{height:34px}
}

/* ==========================================================================
   Custom select
   The native popup is drawn by the OS and cannot be styled, so JS swaps in a
   listbox. The real <select> stays in the DOM as the source of truth, and the
   whole thing falls back to the native control when JS does not run.
   ========================================================================== */
.sel{position:relative}
.sel-native{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;
  clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;pointer-events:none;
}
.sel-btn{
  display:flex;align-items:center;gap:10px;width:100%;
  font:inherit;font-size:17px;color:var(--ink);text-align:left;cursor:pointer;
  background:#fff;padding:12px 44px 12px 14px;
  border:1px solid var(--hair);border-radius:12px;
  transition:border-color .2s ease,box-shadow .2s ease;
}
.sel-btn:hover{border-color:rgba(0,0,0,.24)}
.sel-btn[aria-expanded="true"],
.sel-btn:focus-visible{
  outline:none;border-color:var(--violet);box-shadow:0 0 0 4px rgba(156,101,255,.22);
}
.sel-btn .sel-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sel-btn.is-placeholder .sel-label{color:var(--ink-2)}
.sel-btn .sel-chev{
  position:absolute;right:16px;top:50%;width:11px;height:7px;margin-top:-3px;
  fill:none;stroke:var(--ink-2);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;
  transition:transform .25s cubic-bezier(.28,.11,.32,1),stroke .2s ease;
}
.sel-btn[aria-expanded="true"] .sel-chev{transform:rotate(180deg);stroke:var(--violet)}
.field[aria-invalid="true"] .sel-btn,.sel-btn[aria-invalid="true"]{border-color:#e6218f}

.sel-list{
  position:fixed;z-index:60;margin:0;padding:6px;list-style:none;
  background:rgba(255,255,255,.92);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border:1px solid rgba(0,0,0,.08);border-radius:14px;
  box-shadow:0 18px 44px -12px rgba(0,0,0,.3),0 2px 6px rgba(0,0,0,.08);
  max-height:264px;overflow-y:auto;overscroll-behavior:contain;
  opacity:0;transform:translateY(-6px) scale(.98);transform-origin:top center;
  transition:opacity .18s ease,transform .18s cubic-bezier(.28,.11,.32,1);
}
.sel-list.up{transform-origin:bottom center;transform:translateY(6px) scale(.98)}
.sel-list.open{opacity:1;transform:none}
.sel-opt{
  display:flex;align-items:center;gap:9px;
  padding:9px 12px 9px 10px;border-radius:9px;
  font-size:16px;color:var(--ink);cursor:pointer;white-space:nowrap;
}
.sel-opt .sel-tick{
  width:14px;height:14px;flex:none;fill:none;stroke:currentColor;
  stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;opacity:0;
}
.sel-opt[aria-selected="true"]{font-weight:500}
.sel-opt[aria-selected="true"] .sel-tick{opacity:1;stroke:var(--link)}
.sel-opt.active{background:var(--btn);color:#fff}
.sel-opt.active .sel-tick{stroke:#fff}
.sel-opt.is-placeholder{color:var(--ink-2)}
.sel-opt.active.is-placeholder{color:#fff}

/* The filter above a long list. Pinned to the top of the scroller, so it is
   still there once you are two hundred countries down. */
.sel-search{
  position:sticky;top:-6px;z-index:1;
  margin:-6px -6px 6px;padding:6px 6px 7px;
  background:#fff;border-bottom:1px solid rgba(0,0,0,.07);
  border-radius:14px 14px 0 0;
}
.sel-search-in{
  width:100%;font:inherit;font-size:15px;color:var(--ink);
  padding:8px 11px;border:1px solid var(--hair);border-radius:9px;background:#fff;
}
.sel-search-in:focus{
  outline:none;border-color:var(--violet);box-shadow:0 0 0 3px rgba(156,101,255,.18);
}
.sel-empty{padding:9px 12px;font-size:15px;color:var(--ink-2)}

@media (prefers-reduced-motion:reduce){
  .sel-list{transition:none}
  .sel-btn .sel-chev{transition:none}
}

/* ==========================================================================
   Date picker
   ========================================================================== */
.cal-ico{width:15px;height:15px;margin-top:-7.5px;transform:none!important;
  stroke:var(--ink-2);stroke-width:1.7}
.sel-btn[aria-expanded="true"] .cal-ico{stroke:var(--violet)}

.cal{padding:14px;min-width:274px;max-height:none;overflow:visible}
.cal-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:12px}
.cal-title{font-size:15px;font-weight:600;letter-spacing:-.01em}
.cal-nav{
  width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:50%;
  background:none;cursor:pointer;color:var(--ink-2);transition:background .2s ease,color .2s ease;
}
.cal-nav:hover:not(:disabled){background:rgba(0,0,0,.06);color:var(--ink)}
.cal-nav:disabled{opacity:.28;cursor:not-allowed}
.cal-nav svg{width:8px;height:12px;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}

.cal-dows{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}
.cal-dows span{
  text-align:center;font-size:11px;font-weight:600;letter-spacing:.04em;
  color:var(--ink-2);padding:4px 0;
}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.cal-day{
  aspect-ratio:1;display:grid;place-items:center;border:0;border-radius:50%;
  background:none;cursor:pointer;font:inherit;font-size:14px;color:var(--ink);
  transition:background .18s ease,color .18s ease;
}
.cal-day:hover:not(:disabled):not(.sel){background:rgba(0,0,0,.06)}
.cal-day:disabled{color:rgba(0,0,0,.22);cursor:not-allowed}
.cal-day.today:not(.sel){box-shadow:inset 0 0 0 1.5px var(--hair);font-weight:600}
.cal-day.sel{background:var(--btn);color:#fff;font-weight:600}
.cal-day:focus-visible{outline:2px solid var(--violet);outline-offset:1px}

@media (max-width:640px){
  .cal{min-width:0;width:calc(100vw - 40px);max-width:320px}
}



.grid.quotes{padding-bottom:56px}


/* ==========================================================================
   Hero eyebrow
   ========================================================================== */
/* A pill with a highlight travelling round its edge. The ring is a conic
   gradient on an oversized square that spins behind the pill; the pill clips it
   to its own shape and an inner fill covers everything but a 1.5px rim. Doing
   it this way rather than animating a gradient angle keeps it working without
   @property support. */
.eyebrow-live,
.link-inline,
.nav-links .nav-hot{
  position:relative;overflow:hidden;isolation:isolate;
  display:inline-flex;align-items:center;gap:10px;
  padding:9px 20px;border-radius:980px;
  font-size:17px;font-weight:600;letter-spacing:.01em;color:var(--ink-2);
  background:rgba(0,0,0,.09);
}
.eyebrow-live::before,
.link-inline::before,
.kw-search::before,
.btn-outline.is-ringed::before,
.nav-links .nav-hot::before{
  content:"";position:absolute;left:50%;top:50%;width:240%;aspect-ratio:1;
  translate:-50% -50%;
  background:conic-gradient(from 0deg,
    transparent 0deg 190deg,
    rgba(253,15,255,.9) 268deg,
    rgba(156,101,255,.9) 310deg,
    transparent 360deg);
  animation:eyebrow-ring 4.2s linear infinite;
}
.eyebrow-live::after,
.link-inline::after,
.kw-search::after,
.btn-outline.is-ringed::after,
.nav-links .nav-hot::after{
  content:"";position:absolute;inset:1.5px;border-radius:inherit;background:#fff;
}
/* Both pseudo-elements sit behind the content. "SaaS" is a bare text node, so
   it cannot take a z-index of its own: the fill has to go under it rather than
   the text being lifted over the fill. isolation keeps the negative layers
   inside the pill instead of dropping them behind the page. */
.eyebrow-live::before,
.link-inline::before,
.kw-search::before,
.btn-outline.is-ringed::before,
.nav-links .nav-hot::before{z-index:-2}
.eyebrow-live::after,
.link-inline::after,
.kw-search::after,
.btn-outline.is-ringed::after,
.nav-links .nav-hot::after{z-index:-1}

/* The outline pill wearing the same travelling ring. Its border hands over to
   the ring, and the padding takes on the pixel the border was holding, so the
   pill is the size it always was and still lines up with the button beside it. */
.btn-outline.is-ringed{
  position:relative;overflow:hidden;isolation:isolate;
  border:0;padding:5px 5px 5px 25px;background:transparent;
}
.btn-outline.is-ringed:hover{
  border-color:transparent;
  transform:scale(1.02);box-shadow:0 10px 26px -18px rgba(0,0,0,.5);
}
@keyframes eyebrow-ring{to{transform:rotate(360deg)}}

/* A run of text lit by the brand gradient drifting across it. The gradient
   ends on the colour it starts with and travels exactly one background width,
   so the loop has no seam. */
.grad-anim{
  color:transparent;
  background:linear-gradient(90deg,#fd0fff 0%,#9c65ff 50%,#fd0fff 100%);
  background-size:200% 100%;
  -webkit-background-clip:text;background-clip:text;
  animation:grad-drift 5s linear infinite;
}
@keyframes grad-drift{from{background-position:0 0}to{background-position:200% 0}}
@media (prefers-reduced-motion:reduce){
  .grad-anim{animation:none}
}

/* The features link wears the same ring, sized down to sit in the note under
   the plans and coloured as the control it is. It is a real <button>, so undo
   what the UA gives it. */
.link-inline{
  font-family:inherit;font-size:13px;line-height:1;letter-spacing:-.01em;
  color:var(--link);padding:6px 15px;border:0;cursor:pointer;
  vertical-align:middle;margin-left:5px;
  transition:filter .2s ease,transform .2s ease;
}
.link-inline:hover{transform:scale(1.03)}
.link-inline:hover::after{background:#fbf7ff}

/* Over a photograph the pill sits on dark, so the fill follows. */
.hero.has-bg .eyebrow-live{background:rgba(255,255,255,.28)}
.hero.has-bg .eyebrow-live::after{
  background:rgba(0,0,0,.32);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}

@media (prefers-reduced-motion:reduce){
  .eyebrow-live::before,
  .link-inline::before,
  .kw-search::before,
  .nav-links .nav-hot::before{animation:none}
}
.pulse-dot{
  position:relative;width:9px;height:9px;flex:none;border-radius:50%;
  background:var(--violet);
}
.pulse-dot::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  background:var(--violet);animation:dot-pulse 2s ease-out infinite;
}
@keyframes dot-pulse{
  0%{transform:scale(1);opacity:.55}
  70%{transform:scale(3);opacity:0}
  100%{transform:scale(3);opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .pulse-dot::after{animation:none;opacity:0}
}

/* ==========================================================================
   Key features
   ========================================================================== */
.modal-wide{max-width:min(940px,calc(100vw - 40px))}
/* The About dialog carries a paragraph of prose and a board two across, and
   both want a longer line than the 760px the short dialogs use. */
.modal-about{max-width:min(880px,calc(100vw - 40px))}
/* A module dialog is mostly a picture of the module working, and at 560px that
   picture was a thumbnail of a screen full of small type. This is twice its
   width, which is the size at which the columns in it can be read. */
.modal-mod{max-width:min(1030px,calc(100vw - 40px))}
/* The key features list is long, and at full height the dialog fills the
   screen. Three tenths shorter leaves the page visible around it and the list
   scrolls inside as it did before. */
.modal-short,
.modal-short .modal-card{max-height:calc((100vh - 48px) * .7)}
/* The Sign Up dialog holds two rows and a line of copy, so it wants to be
   narrower than the form the default width is sized for. */
.modal-narrow{max-width:min(560px,calc(100vw - 40px))}

/* Filter box above the keyword pills. It wears the same travelling ring as the
   SaaS pill: the arc rides on this wrapper, because an <input> cannot carry
   pseudo-elements of its own. The field then has to be transparent and
   borderless, or it would paint over the rim the wrapper is showing. */
.kw-search{
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;align-items:center;
  margin:26px auto 0;max-width:420px;
  border-radius:980px;background:rgba(0,0,0,.09);
}
.kw-search-icon{
  position:absolute;left:16px;top:50%;translate:0 -50%;
  width:17px;height:17px;fill:none;stroke:var(--ink-2);stroke-width:1.8;
  stroke-linecap:round;pointer-events:none;
}
.kw-search input{
  width:100%;font:inherit;font-size:16px;color:var(--ink);
  padding:12px 16px 12px 43px;border:0;border-radius:980px;background:transparent;
}
.kw-search input::placeholder{color:var(--ink-2)}
/* The ring is the field's own outline, so a second one on focus would sit on
   top of it. The glow goes on the wrapper instead, outside the clip. */
.kw-search input:focus{outline:none}
.kw-search:focus-within{box-shadow:0 0 0 4px rgba(156,101,255,.18)}
/* The clear affordance the browser draws sits oddly inside a pill. */
.kw-search input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}

.kw-empty{margin-top:26px;font-size:15px;color:var(--ink-2)}
.kw-clear{
  font:inherit;font-size:15px;color:var(--link);background:none;border:0;
  padding:0;cursor:pointer;text-decoration:underline;text-underline-offset:3px;
}
.kw-list{
  list-style:none;margin:34px 0 0;padding:0;
  display:flex;flex-wrap:wrap;gap:10px;justify-content:center;
}
.kw-list li{
  font-size:14px;line-height:1.35;color:var(--ink);
  background:var(--grey);border:1px solid transparent;border-radius:980px;
  padding:9px 16px;transition:border-color .2s ease,background .2s ease,color .2s ease;
}
.kw-list li:hover{background:#fff;border-color:var(--violet);color:var(--ink)}
.section-head-block .links{margin-top:28px}

@media (max-width:640px){
  .kw-list{gap:8px;justify-content:flex-start;text-align:left}
  .kw-list li{font-size:13px;padding:8px 13px}
}

/* The one nav item worth pulling the eye, in the brand gradient. Scoped to
   .nav-links so it outranks the colour that rule sets on every nav link. */
.nav-links .nav-hot{
  font-weight:600;opacity:1;
  /* The shared ring block sets 17px and outranks .nav-links a, so the size
     has to be restated here to sit level with the other links. */
  font-size:14px;padding:7px 15px;gap:0;
}
/* The gradient sits on the span, not the link: background-clip:text on the
   link itself would clip away the background the ring uses as its rim. */
.nav-links .nav-hot span{
  color:transparent;background:var(--brand);
  -webkit-background-clip:text;background-clip:text;
}

/* The independent scheduling section is centred, so its points are too. */
.indep-points li{text-align:center;align-items:center}

/* Icons on the flow nodes, matched to the storage one that starts the chain. */
.flow-node-icon{margin-bottom:10px}

/* A gradient that moves inside the mark it paints. Each stop walks between the
   two brand colours a beat behind the one before it, which reads as the
   gradient running round the stroke; animating the stops rather than the
   gradient's own geometry is the form every browser agrees on. */
.grad-flow stop{animation:grad-flow 3.2s ease-in-out infinite}
.grad-flow stop:nth-child(2){animation-delay:-1.06s}
.grad-flow stop:nth-child(3){animation-delay:-2.13s}
@keyframes grad-flow{
  0%,100%{stop-color:#fd0fff}
  50%    {stop-color:#9c65ff}
}
@media (prefers-reduced-motion:reduce){
  .grad-flow stop{animation:none}
}
.flow-out-icon{margin-bottom:8px}

/* ==========================================================================
   Hero background uploaded through /admin
   A photograph replaces a flat white ground, so the dark copy would sit on an
   unknown image. The section flips to light-on-dark behind a gradient that is
   heaviest where the headline sits.
   ========================================================================== */
.hero.has-bg{
  background-image:
    linear-gradient(180deg,rgba(0,0,0,.62) 0%,rgba(0,0,0,.3) 24%,rgba(0,0,0,0) 45%),
    var(--hero-image);
  background-size:cover;
  background-position:center;
  background-repeat:no-repeat;
}
.hero.has-bg h1{color:#fff}
.hero.has-bg .subhead{color:rgba(255,255,255,.82)}
.hero.has-bg .eyebrow-live{color:rgba(255,255,255,.9)}
.hero.has-bg .pulse-dot,
.hero.has-bg .pulse-dot::after{background:#fff}

/* Over a photograph the solid gradient button competes with the picture, so
   it goes white with the brand arc travelling round its rim. Its own ring
   rather than the shared one: the shared block also sets padding and type,
   which would undo the button's. Slower and softer than the SaaS pill, which
   is closer to the eye and can carry a brighter sweep. */
.hero.has-bg .btn,
.cta.has-bg .btn{
  position:relative;overflow:hidden;isolation:isolate;
  background:rgba(255,255,255,.5);color:var(--ink);
}
.hero.has-bg .btn::before,
.cta.has-bg .btn::before{
  content:"";position:absolute;left:50%;top:50%;width:260%;aspect-ratio:1;
  translate:-50% -50%;z-index:-2;
  background:conic-gradient(from 0deg,
    transparent 0deg 200deg,
    rgba(253,15,255,.75) 272deg,
    rgba(156,101,255,.75) 312deg,
    transparent 360deg);
  animation:eyebrow-ring 6.5s linear infinite;
}
.hero.has-bg .btn::after,
.cta.has-bg .btn::after{
  content:"";position:absolute;inset:1.5px;border-radius:inherit;background:#fff;z-index:-1;
}
.hero.has-bg .btn:hover,
.cta.has-bg .btn:hover{filter:none;transform:scale(1.02)}
@media (prefers-reduced-motion:reduce){
  .hero.has-bg .btn::before,
  .cta.has-bg .btn::before{animation:none}
}

/* The secondary pill is white-on-white by default, which disappears here. */
.hero.has-bg .btn-outline{
  background:rgba(255,255,255,.1);color:#fff;border-color:rgba(255,255,255,.35);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
}
.hero.has-bg .btn-outline:hover{border-color:rgba(255,255,255,.7)}
.hero.has-bg .btn-arrow{border-color:rgba(255,255,255,.35)}
.hero.has-bg .btn-outline:hover .btn-arrow{
  border-color:rgba(255,255,255,.7);background:rgba(255,255,255,.12);
}
.hero.has-bg .btn-arrow svg{stroke:#fff}

/* The closing call to action takes the same picture. Its copy is centred
   rather than stacked at the top, so the scrim is even across the section
   instead of heaviest at one edge. Keep it light enough that the picture
   still reads; the shadow behind the copy carries the legibility over a
   bright patch, so the scrim does not have to. */
.cta.has-bg{
  background-image:
    linear-gradient(rgba(0,0,0,.34),rgba(0,0,0,.34)),
    var(--hero-image);
  background-size:cover;
  background-position:center;
  background-repeat:no-repeat;
}
.cta.has-bg h2{color:#fff;text-shadow:0 2px 22px rgba(0,0,0,.55)}
.cta.has-bg .subhead{color:rgba(255,255,255,.88);text-shadow:0 1px 16px rgba(0,0,0,.5)}

/* Held until branding.js knows which logo belongs here. The class is set by an
   inline script, so a visitor without JS never sees it and keeps the mark. */
.branding-pending .nav-logo{visibility:hidden}

/* A sygnet is square, so it can run taller than a wide lockup at the same
   optical weight. 28.3px in a 77px bar leaves 24.4px of air above and below.
   A height rather than a cap on one: an SVG carrying a viewBox and no width or
   height of its own has no size to be capped, and comes out at nothing. */
.nav-logo-img.is-sygnet{height:28.3px;max-height:none;width:auto}

/* The card takes focus when a modal opens, so suppress its outline: the ring
   belongs on real controls, not the panel. */
.modal-card:focus{outline:none}

/* The hero stacks taller on a phone, pushing the buttons past the halfway
   point, so the scrim has to run a little further down there. */
@media (max-width:640px){
  .hero.has-bg{
    background-image:
      linear-gradient(180deg,rgba(0,0,0,.62) 0%,rgba(0,0,0,.4) 30%,rgba(0,0,0,0) 62%),
      var(--hero-image);
  }
}

/* ==========================================================================
   Phone touch targets that have to outrank rules declared further down.
   A media query adds no specificity, so these belong after the base rules
   they adjust rather than in the block further up.
   ========================================================================== */
@media (max-width:640px){
  .link-inline{padding:10px 17px}
  .plans-foot{line-height:1.8}
  /* The mark is 24px of glyph in a 77px bar; the link is what a finger hits. */
  .nav-logo{padding:10px 0}
  /* And eight per cent off an uploaded mark here: the bar is the same height
     as on a desktop but holds a third of the width, so the same glyph reads
     heavier in it. */
  .nav-logo-img.is-sygnet{height:27.5px}
}
