/* Tarvo: the palette (the brand's own colours, printed by taste-skill's start.mjs brand) and the
   dealt type (funnel), then the page's own CSS: what every section shares, then each part of the page in turn.
   Linked after the kit's stylesheets in src/app/[lang]/layout.tsx. The font variables come from next/font. */
:root {
  --p-bg: #ffffff; --p-surface: #f3f2fb; --p-ink: #14121f; --p-muted: #56546b;
  --p-accent: #5b4bff; --p-accent-ink: #ffffff; --p-action: #5b4bff; --p-action-ink: #ffffff;
  --p-inv-bg: #14121f; --p-inv-surface: #211f2c; --p-inv-ink: #ffffff; --p-inv-muted: #9c9ba2;
  --p-inv-accent: #5b4bff; --p-inv-accent-ink: #ffffff; --p-inv-action: #5b4bff; --p-inv-action-ink: #ffffff;
  --font-display: var(--font-funnel-display), system-ui, sans-serif;
  --font-text: var(--font-funnel-sans), system-ui, sans-serif;
  --font-mono: var(--font-dm-mono), ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --display-weight: 400;
  --display-tracking: -0.03em;
  --display-tracking-xl: -0.04em;
  --ly-scale: 0.98;
}
/* the lit ground behind UI (data-ground="sky"), turned to the brand's own lilac */
html[data-ground="sky"] { --ground-bg: #dcd8ff; --ground-surface: #ebe8ff; --ground-ink: #18152e; --ground-muted: #4a4766; --ground-accent: #5b4bff; }

/* ---------------------------------------------------------------- rhythm: sections as tall as their content
   The kit makes every section one or two full screens, which left empty ground under short content.
   Here only the hero and the pinned #custom keep their screens; #product keeps at least its screen from
   1024px (its own rule, below). Every other section and the closing footer are as tall as their
   content, --tv-sec above and below. A section sets its own padding with its #id. */
:root { --tv-sec: clamp(64px, 7vw, 96px); }
main > :is(section, .section):not(.hero):where(:not(.section--hero, [data-moment="pinned-chapters"], #product)),
footer.closing {
  height: auto; min-height: 0; padding-block: var(--tv-sec);
}

/* ---------------------------------------------------------------- shared: the right column of a split, from the page's split line */
@media (min-width: 1024px) {
  .grid > .tv-right { grid-column: 7 / -1; }
}

/* ---------------------------------------------------------------- nav: the three product cards */
.menu-card .panel { --p-h: 200px; }

/* ---------------------------------------------------------------- nav: the Product word and its chevron
   "Product" is a link to #product; the chevron beside it is the button that opens the panel
   (src/components/site/nav/nav-behaviour.tsx). Below 1024 the kit's sheet uses its own expand button. */
.tv-nav__chev { display: none; }
@media (min-width: 1024px) {
  #site-nav .nav__item:has(> .tv-nav__chev) > .nav__link { padding-right: 0; }
  #site-nav .nav__item:has(> .tv-nav__chev) > .nav__link::before,
  #site-nav .nav__item:has(> .tv-nav__chev) > .nav__link::after { right: 0; }
  /* the word's gap and right padding as before, now a 28 x 36 button */
  .tv-nav__chev {
    display: inline-grid; place-items: center start; width: 28px; height: 36px; margin: 0; padding: 0 0 0 var(--s-1);
    border: 0; border-radius: var(--r-sm); background: none; color: var(--ink); cursor: pointer;
  }
  .tv-nav__chev .chev { width: 12px; height: 12px; opacity: .6; transition: transform 240ms var(--m-ease), opacity var(--m-out) var(--m-ease); }
  .tv-nav__chev:hover .chev { opacity: 1; transition-duration: 240ms, var(--m-in); }
  /* without the script: the kit's hover and focus opening, the chevron turns with it */
  #site-nav:not(.tv-aim) .nav__item:is(:hover, :focus-within) > .tv-nav__chev .chev { transform: rotate(180deg); }
  /* a quiet shadow under the open panel, so it reads as laid over the page */
  #site-nav .nav__menu { box-shadow: 0 28px 48px -36px rgb(20 18 31 / .28); }
}

/* ---------------------------------------------------------------- nav: the panel under the script
   One source of truth: .tv-open on the item (set by nav-behaviour.tsx). The kit's :hover and
   :focus-within opening is overridden by the #id; motion.js's .m-menu-open no longer matters here.
   Opening: the panel reveals downward from the bar and fades in, the cards drop 8px into place 45ms
   apart, the chevron turns. Closing is quicker and all at once. */
@media (min-width: 1024px) {
  #site-nav.tv-aim .nav__menu {
    opacity: 0; visibility: hidden; transform: none; pointer-events: none; clip-path: inset(0 0 100% 0);
    transition: opacity 140ms var(--m-ease), clip-path 160ms var(--m-ease), visibility 0s linear 160ms;
  }
  #site-nav.tv-aim .nav__item.tv-open > .nav__menu {
    opacity: 1; visibility: visible; pointer-events: auto; clip-path: inset(0 0 -64px 0);
    transition: opacity 200ms var(--m-ease), clip-path 320ms var(--m-ease), visibility 0s;
  }
  #site-nav.tv-aim .nav__menu .grid > * {
    opacity: 0; transform: translateY(-8px);
    transition: opacity 100ms var(--m-ease), transform 140ms var(--m-ease); transition-delay: 0s;
  }
  #site-nav.tv-aim .nav__item.tv-open > .nav__menu .grid > * {
    opacity: 1; transform: none;
    transition: opacity 240ms var(--m-ease), transform 340ms var(--m-ease);
    transition-delay: calc(50ms + var(--m-i, 0) * 45ms);
  }
  #site-nav.tv-aim .nav__item > .tv-nav__chev .chev { transform: none; }
  #site-nav.tv-aim .nav__item.tv-open > .tv-nav__chev .chev { transform: rotate(180deg); opacity: 1; }
  /* the open word keeps its underline while the pointer is on the panel or on its way there */
  #site-nav.tv-aim .nav__item.tv-open > .nav__link::before { transform: scaleX(1); transform-origin: left; }
  /* on the way to the panel the pointer crosses other words: they do not answer */
  #site-nav.tv-aim.tv-aiming .nav__item:not(.tv-open) > .nav__link::before { transform: scaleX(0); }
}
@media (prefers-reduced-motion: reduce) {
  #site-nav .nav__menu, #site-nav .nav__menu .grid > *, #site-nav .tv-nav__chev .chev { transition-delay: 0s !important; }
}
html[data-motion="off"] #site-nav :is(.nav__menu, .nav__menu .grid > *, .tv-nav__chev .chev) { transition: none !important; }

/* ---------------------------------------------------------------- nav: a menu card answers */
@media (hover: hover) and (pointer: fine) {
  html:not([data-motion="off"]) #site-nav .menu-card .panel {
    transition: transform var(--m-out) var(--m-ease), border-color var(--m-out) var(--m-ease), box-shadow var(--m-out) var(--m-ease);
  }
  html:not([data-motion="off"]) #site-nav .menu-card .at-corner { transition: transform 320ms var(--m-ease); }
  html:not([data-motion="off"]) #site-nav .menu-card :is(.t-card, .t-small) { transition: color var(--m-out) var(--m-ease); }
  html:not([data-motion="off"]) #site-nav .menu-card:hover .panel {
    transform: translateY(var(--m-lift)); border-color: color-mix(in oklab, var(--ink) 16%, transparent);
    box-shadow: 0 14px 32px -18px rgb(20 18 31 / .32); transition-duration: 180ms;
  }
  html:not([data-motion="off"]) #site-nav .menu-card:hover .at-corner { transform: translate(-4px, -4px); }
  html:not([data-motion="off"]) #site-nav .menu-card:hover .t-card { color: var(--action); transition-duration: var(--m-in); }
}
/* keyboard focus: the ring sits on the picture, the title takes the accent */
#site-nav .menu-card:focus-visible { outline: none; }
#site-nav .menu-card:focus-visible .panel { outline: 2px solid var(--action); outline-offset: 3px; }
#site-nav .menu-card:focus-visible .t-card { color: var(--action); }

/* ---------------------------------------------------------------- nav: where an in-page link lands
   A section as tall as its content (site.css) has only --tv-sec above its heading, as little as the
   bar's own height (768: 72 and 72), so a jump to it left the heading flush under the fixed bar. It
   lands with its top under the bar instead. The hero, #product from 1024px and the pinned #custom have
   the bar inside their own top padding: they keep the kit's landing at the very top. */
main > [id]:not(.hero, #product, [data-moment="pinned-chapters"]), footer.closing[id] { scroll-margin-top: var(--nav); }

/* ---------------------------------------------------------------- nav: the word of the section in view
   aria-current="location" (nav-behaviour.tsx) takes the kit's still bar for the current page */
#site-nav .nav__link[aria-current="location"]::after {
  content: ""; position: absolute; left: var(--s-3); right: var(--s-3); bottom: -2px; height: 2px; border-radius: 2px; background: currentColor;
}
@media (min-width: 1024px) and (max-width: 1279px) {
  #site-nav .nav__link[aria-current="location"]::after { left: var(--s-2); right: var(--s-2); }
}
@media (max-width: 1023px) {
  #site-nav.is-open .nav__link[aria-current="location"]::after { left: 0; right: auto; width: 24px; bottom: 10px; }
}

/* ---------------------------------------------------------------- hero: the words on the page's split pair
   The kit's centred hero (headline, lead, buttons, the window in a lit frame; no news pill), with its
   words set left: the h1 on the left line; the lead and the buttons from the split line, so the page
   keeps equal edges and the window gets more of the screen. */
.hero--centred .hero__c { justify-items: start; text-align: left; max-width: none; margin-inline: 0; }
.hero--centred .btn-row { justify-content: flex-start; margin-top: 0; }
.tv-hero__side { display: grid; gap: var(--s-5); justify-items: start; }
@media (min-width: 1024px) {
  .hero--centred .hero__c { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); align-items: start; }
  /* six columns hold the headline at the split heroes' size (the centred size wants the full width) */
  .hero--centred .hero__c > h1 { grid-column: 1 / span 6; font-size: var(--ly-h1-col); max-width: none; }
  .hero--centred .hero__lead { max-width: none; }
  .hero--centred .hero__c > .tv-hero__side { grid-column: 7 / -1; }
}
@media (max-width: 639px) {
  .tv-hero__side { width: 100%; }
}

/* ---------------------------------------------------------------- hero: the window on the real app
   (src/components/site/hero.tsx) The kit's lit frame under the words, here in the brand's violet (one
   hue, lit from the upper left, drawn in CSS: no effect runs in the hero). In it stands one window,
   --tv-edge in from the frame's top and sides: a bar with a tab per screen, then that screen, a
   screenshot of the Tarvo app (public/showcase).
   The frame is as tall as the window and the first screen allow: where the screen is shorter than
   the window (a laptop) the frame takes what is left and cuts the window at its foot; where it is
   taller, the frame ends under the window. Either way it fades over its last --tv-fade, so a cut
   never shows as a sliced row. */
.hero--centred .hero__window {
  --tv-edge: var(--s-5); --tv-fade: 56px;
  flex: 0 1 auto; min-height: clamp(220px, 32svh, 340px); padding: var(--tv-edge) var(--tv-edge) calc(var(--tv-fade) + var(--s-2));
  background: radial-gradient(120% 150% at 12% 0%, #9a8bff 0%, #7a66ff 34%, #5f4dff 68%, #4c3bdb 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--tv-fade)), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - var(--tv-fade)), transparent);
}
.tv-show {
  position: relative; z-index: 1; overflow: clip;
  border-radius: 14px; background: #ffffff; color: var(--p-ink);
  box-shadow: 0 0 0 1px rgb(20 18 31 / .1), 0 30px 70px -30px rgb(20 18 31 / .6);
}
/* the bar: three dots and the tabs, as a browser sets them. No rule under it: the bar is white, the
   app's own ground under it a shade darker */
.tv-show__bar { display: flex; align-items: center; gap: var(--s-4); height: 46px; padding: 0 var(--s-3) 0 var(--s-4); }
.tv-show__dots { display: flex; flex: none; gap: 6px; }
.tv-show__dots > i { width: 10px; height: 10px; border-radius: 50%; background: rgb(20 18 31 / .13); }
.tv-show__tabs { display: flex; gap: 2px; min-width: 0; }
.tv-show__tab {
  display: inline-flex; align-items: center; gap: 7px; flex: none; height: 32px; margin: 0; padding: 0 12px 0 10px;
  border: 0; border-radius: 9px; background: none; color: var(--p-muted); cursor: pointer;
  font: 500 14px/1 var(--font-text); white-space: nowrap;
  transition: background-color var(--m-out) var(--m-ease), color var(--m-out) var(--m-ease), scale var(--m-press) var(--m-ease);
}
.tv-show__tab > svg { flex: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.tv-show__tab:hover { background: rgb(20 18 31 / .05); color: var(--p-ink); transition-duration: var(--m-in); }
.tv-show__tab:active { scale: 0.97; }
.tv-show__tab[aria-selected="true"] { background: color-mix(in oklab, var(--p-accent) 11%, #ffffff); color: color-mix(in oklab, var(--p-accent) 78%, var(--p-ink)); }
.tv-show__tab:focus-visible { outline: 2px solid var(--p-accent); outline-offset: 1px; }
/* a screen: the picture as wide as the window, its height from its own ratio (16:13; a tablet's 820 x 1100, a phone's 390 x 780) */
.tv-show__screen > picture, .tv-show__screen img { display: block; width: 100%; height: auto; }
.tv-show__screen[hidden] { display: none; }
@media (max-width: 1023px) {
  .hero--centred .hero__window { --tv-edge: var(--s-4); }
}
@media (max-width: 639px) {
  /* a phone: the tabs share the bar's width, words only */
  .hero--centred .hero__window { --tv-edge: var(--s-3); --tv-fade: 40px; }
  .tv-show { border-radius: 12px; }
  .tv-show__bar { height: 42px; padding-inline: 5px; }
  .tv-show__dots { display: none; }
  .tv-show__tabs { flex: 1; gap: 0; }
  .tv-show__tab { flex: 1 1 0; justify-content: center; min-width: 0; padding: 0 4px; font-size: 13px; }
  .tv-show__tab > svg { display: none; }
}
@media (prefers-reduced-motion: reduce) { .tv-show__tab { transition: none; } }
html[data-motion="off"] .tv-show__tab { transition: none; }

/* ---------------------------------------------------------------- #product: one window, wired to its heading
   (src/components/site/product.tsx) The heading stands in four lines, one per thing the window holds,
   each ending with a chip of that thing. From 1024px the window stands beside it and a line runs
   from every chip to its part of the window (product/wires.tsx draws them). Below 1024px the window
   follows the words and the lines go.
   The section keeps at least its screen from 1024px and grows when the window needs more; below, it is
   as tall as its content like the sections after it. Its ground is the kit's halo, set behind the window. */
main > #product { height: auto; min-height: 100vh; min-height: 100svh; --halo-x: 77%; --halo-y: 46%; --g-hue: #7a66ff; --g-hue-t: #ff9ad5; }
@media (max-width: 1023px) {
  main > #product { min-height: 0; padding-block: var(--tv-sec); scroll-margin-top: var(--nav); --halo-x: 50%; --halo-y: 66%; }
}
/* a phone's hero ends 24px above its foot: the heading keeps the page's gap between sections */
@media (max-width: 639px) { main > #product { padding-top: calc(var(--tv-sec) + var(--s-6)); } }
.tv-one { position: relative; align-items: start; row-gap: var(--s-7); }
.tv-one__text { display: grid; gap: var(--s-5); justify-items: start; min-width: 0; }
.tv-one__line { display: block; }
.tv-one__text > .t-lead { max-width: 46ch; text-wrap: pretty; }
@media (min-width: 1024px) {
  /* the heading at the column's head, the lead and the link at its foot, level with the window's */
  .tv-one > .tv-one__text { grid-column: 1 / span 6; align-self: stretch; grid-template-rows: auto 1fr auto; }
  .tv-one > .tv-sheet { grid-column: 7 / -1; }
  /* the lines turn in the last 84px before the window: the lead stays clear of them */
  .tv-one__text > .t-lead { align-self: end; max-width: min(46ch, 100% - 84px); }
}

/* a chip in the heading (.tv-pin): the thing its line names, as the window shows it. Its words come
   from data-label, so they are no part of the heading's text */
.tv-pin.ui, .tv-sheet.ui { --fx-bg: #ffffff; --fx-surface: #f4f4f3; --fx-ink: #16181a; --fx-muted: #4a4f55; --fx-accent: var(--p-accent); --fx-accent-ink: var(--p-accent-ink); }
.tv-pin {
  display: inline-flex; align-items: center; gap: 8px; vertical-align: middle; position: relative; top: -0.06em;
  height: clamp(30px, calc(var(--t-h2) * 0.8), 40px); margin-left: 0.3em; padding: 0 14px 0 7px; border-radius: 999px;
  border: 1px solid var(--u-line-2); background: var(--u-bg); color: var(--u-ink);
  box-shadow: 0 1px 2px rgb(20 18 31 / .06), 0 8px 18px -10px rgb(20 18 31 / .28);
  font: 500 clamp(13px, calc(var(--t-h2) * 0.3125), 15px)/1 var(--font-text); letter-spacing: 0; white-space: nowrap;
  font-variant-numeric: tabular-nums; transition: border-color var(--m-out) var(--m-ease);
}
.tv-pin::after, .tv-pin > .ui-avatar::before { content: attr(data-label); }
.tv-pin > .ui-avatar { width: clamp(20px, calc(var(--t-h2) * 0.54), 26px); height: clamp(20px, calc(var(--t-h2) * 0.54), 26px); font-size: 10px; }
.tv-pin__box { flex: none; width: 18px; height: 18px; margin-left: 4px; border-radius: 6px; box-shadow: inset 0 0 0 1.5px var(--u-line-2); }

/* the window: its bar, then its parts down the page (the deal, its contacts, its tasks, its activity) */
.tv-sheet {
  container: tv-sheet / inline-size; position: relative; overflow: clip; min-width: 0;
  background: var(--u-bg); border: 1px solid var(--u-border); border-radius: var(--r-lg); box-shadow: var(--u-shadow);
  font: 400 13px/20px var(--font-text); color: var(--u-ink);
}
.tv-sheet__bar { display: flex; align-items: center; gap: 12px; height: 44px; padding: 0 14px 0 16px; border-bottom: 1px solid var(--u-line); background: var(--u-fill); color: var(--u-text-2); white-space: nowrap; }
.tv-sheet__crumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tv-sheet__crumb i { margin: 0 2px; font-style: normal; }
.tv-sheet__crumb b { font-weight: 500; color: var(--u-ink); }
.tv-sheet__team { display: flex; flex: none; gap: 4px; }
.tv-sheet__team > .ui-avatar { width: 22px; height: 22px; font-size: 10px; }

.tv-sheet__part { position: relative; padding: 14px 20px; border-bottom: 1px solid var(--u-line); transition: background-color var(--m-out) var(--m-ease); }
.tv-sheet__part:last-child { border-bottom: 0; }
/* the edge a line lands on: lit while its pair is under the pointer */
.tv-sheet__part[data-k]::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 2px; background: var(--u-accent); opacity: 0; transition: opacity var(--m-out) var(--m-ease); }
.tv-sheet__label { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 10px; color: var(--u-text-2); font-size: 12px; line-height: 16px; }
.tv-sheet__label > span { color: var(--u-ink); font-weight: 500; }
.tv-sheet__label > em { font-style: normal; font-variant-numeric: tabular-nums; }

/* the deal: who and how much, the stage track, owner and close date */
.tv-sheet__deal { padding-top: 20px; }
.tv-sheet__top { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; column-gap: 14px; align-items: center; }
.tv-sheet__mark { width: 44px; height: 44px; font-size: 15px; }
.tv-sheet__who { display: grid; gap: 2px; min-width: 0; }
.tv-sheet__who > b { font-size: 18px; line-height: 24px; font-weight: 500; letter-spacing: -0.01em; }
.tv-sheet__who > span { color: var(--u-text-2); }
.tv-sheet__value { font: var(--display-weight) 30px/1 var(--font-display); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tv-track { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; align-items: start; margin-top: 18px; }
.tv-track > span { color: var(--u-text-2); font-size: 12px; line-height: 16px; }
/* a name too long for its fifth breaks, so two names never touch */
.tv-track i { display: block; padding-right: 8px; font-style: normal; }
.tv-track > span::before { content: ""; display: block; height: 4px; margin-bottom: 8px; border-radius: 2px; background: var(--u-fill-3); }
.tv-track > .is-past::before { background: var(--u-ink); }
/* the window's one accent: the stage the deal is in */
.tv-track > .is-now { color: var(--u-ink); font-weight: 500; }
.tv-track > .is-now::before { background: var(--u-accent); }
.tv-sheet__facts { display: flex; flex-wrap: wrap; gap: 4px 28px; margin: 14px 0 0; }
.tv-sheet__facts > div { display: flex; align-items: baseline; gap: 8px; }
.tv-sheet__facts dt { color: var(--u-text-2); font-size: 12px; }
.tv-sheet__facts dd { margin: 0; font-weight: 500; }

/* its contacts: who, their role, the apps they answer in */
.tv-people { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 20px; }
.tv-person { display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; column-gap: 10px; align-items: center; }
.tv-person__who { display: grid; min-width: 0; }
.tv-person__who > b { font-weight: 500; }
.tv-person__who > span { color: var(--u-text-2); font-size: 12px; line-height: 16px; }
.tv-person__via { display: flex; gap: 4px; }
.tv-person__via > .ui-logo { width: 24px; height: 24px; border-radius: 7px; }
.tv-person__via > .ui-logo img { width: 14px; height: 14px; }

/* its tasks: the open ones first, the last one done */
.tv-task { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto 20px; column-gap: 10px; align-items: center; min-height: 34px; padding-block: 7px; }
.tv-task + .tv-task { border-top: 1px solid var(--u-line); }
.tv-task:first-child { padding-top: 0; min-height: 27px; }
.tv-task:last-child { padding-bottom: 0; min-height: 27px; }
.tv-task__box { display: grid; place-items: center; width: 18px; height: 18px; border-radius: 6px; box-shadow: inset 0 0 0 1.5px var(--u-line-2); color: transparent; }
.tv-task__box svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.tv-task__what { min-width: 0; font-weight: 500; }
.tv-task__when { color: var(--u-text-2); font-size: 12px; white-space: nowrap; }
.tv-task > .ui-avatar { width: 20px; height: 20px; font-size: 9px; }
.tv-task.is-done > .tv-task__box { background: var(--u-ink); box-shadow: none; color: var(--u-bg); }
.tv-task.is-done > .tv-task__what { color: var(--u-text-2); font-weight: 400; text-decoration: line-through; text-decoration-color: var(--u-line-2); }

/* its activity: whole rows only. Four, so the window ends inside a 900px screen; five on a taller one,
   three on a phone */
.tv-feed__row { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; column-gap: 12px; align-items: start; padding-block: 8px; border-top: 1px solid var(--u-line); }
.tv-feed__row:first-child { padding-top: 0; border-top: 0; }
.tv-feed__row > .ui-icon { width: 16px; height: 16px; margin-top: 2px; color: var(--u-text-2); }
.tv-feed__row > span { display: grid; min-width: 0; }
.tv-feed__row b { font-weight: 500; }
.tv-feed__row span > span, .tv-feed__row > time { color: var(--u-text-2); font-size: 12px; line-height: 16px; }
.tv-feed__row > time { padding-top: 2px; white-space: nowrap; }
.tv-feed__row:nth-child(n+5) { display: none; }
.tv-sheet__history { padding-bottom: 18px; }
@media (max-width: 639px) { .tv-feed__row:nth-child(4) { display: none; } }
@media (min-width: 1280px) and (min-height: 960px) { .tv-feed__row:nth-child(5) { display: grid; } }
/* a small laptop: the window is narrow and its rows stack, so it keeps three */
@media (min-width: 1024px) and (max-width: 1279px) { .tv-feed__row:nth-child(4) { display: none; } }

/* a narrow window (a phone, a small laptop's column): one contact a row, a task's time under it, no
   activity dates, the value under the name */
@container tv-sheet (width < 520px) {
  .tv-people { grid-template-columns: minmax(0, 1fr); }
  .tv-sheet__crumb > span { display: none; }
  /* the stage track: the bars, and the name of the stage the deal is in, which may run on under the next bar */
  .tv-track > span:not(.is-now) > i { display: none; }
  .tv-track > .is-now > i { width: max-content; }
}
@container tv-sheet (width < 440px) {
  .tv-sheet__part { padding-inline: 16px; }
  .tv-sheet__top { grid-template-columns: 44px minmax(0, 1fr); row-gap: 12px; }
  .tv-sheet__value { grid-column: 1 / -1; font-size: 28px; }
  .tv-task { grid-template-columns: 18px minmax(0, 1fr) 20px; align-items: start; }
  .tv-task__box { margin-top: 1px; }
  .tv-task__when { grid-column: 2; grid-row: 2; }
  .tv-task > .ui-avatar { grid-column: 3; grid-row: 1; }
  .tv-feed__row { grid-template-columns: 16px minmax(0, 1fr); }
  .tv-feed__row > time { display: none; }
}

/* the lines (product/wires.tsx): a quiet line from each chip to a port on the window's edge */
.tv-wires { display: none; position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
@media (min-width: 1024px) { .tv-wires { display: block; } }
.tv-wire > path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.tv-wire__base { stroke: color-mix(in oklab, var(--ink) 30%, transparent); stroke-width: 1.25; }
.tv-wire__on { stroke: var(--accent); stroke-width: 1.75; stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 200ms var(--m-ease); }
.tv-wire__port { fill: var(--p-bg); stroke: color-mix(in oklab, var(--ink) 38%, transparent); stroke-width: 1.25; transition: fill var(--m-out) var(--m-ease), stroke var(--m-out) var(--m-ease); }

/* a pair answers together: the pointer on a heading line or on its part of the window draws that line in
   the accent from the chip to the window and lights the port, the chip's edge and the part's edge.
   At rest the deal's line is the lit one (the picture's one accent stroke); the pointer on another
   pair moves the light there */
.tv-one:not(:has([data-k]:hover)) [data-wire="deal"] > .tv-wire__on,
.tv-one:has([data-k="deal"]:hover) [data-wire="deal"] > .tv-wire__on,
.tv-one:has([data-k="contact"]:hover) [data-wire="contact"] > .tv-wire__on,
.tv-one:has([data-k="task"]:hover) [data-wire="task"] > .tv-wire__on { stroke-dashoffset: 0; transition-duration: 420ms; }
.tv-one:not(:has([data-k]:hover)) [data-wire="deal"] > .tv-wire__port,
.tv-one:has([data-k="deal"]:hover) [data-wire="deal"] > .tv-wire__port,
.tv-one:has([data-k="contact"]:hover) [data-wire="contact"] > .tv-wire__port,
.tv-one:has([data-k="task"]:hover) [data-wire="task"] > .tv-wire__port { fill: var(--accent); stroke: var(--accent); transition-delay: 260ms; }
.tv-one:has([data-k="deal"]:hover) [data-pin="deal"],
.tv-one:has([data-k="contact"]:hover) [data-pin="contact"],
.tv-one:has([data-k="task"]:hover) [data-pin="task"] { border-color: var(--u-accent); transition-duration: var(--m-in); }
@media (min-width: 1024px) { .tv-one:not(:has([data-k]:hover)) [data-pin="deal"] { border-color: var(--u-accent); } }
.tv-one:has([data-k="deal"]:hover) .tv-sheet__part[data-k="deal"],
.tv-one:has([data-k="contact"]:hover) .tv-sheet__part[data-k="contact"],
.tv-one:has([data-k="task"]:hover) .tv-sheet__part[data-k="task"] { background: color-mix(in oklab, var(--u-accent) 5%, var(--u-bg)); transition-duration: var(--m-in); }
.tv-one:has([data-k="deal"]:hover) .tv-sheet__part[data-k="deal"]::before,
.tv-one:has([data-k="contact"]:hover) .tv-sheet__part[data-k="contact"]::before,
.tv-one:has([data-k="task"]:hover) .tv-sheet__part[data-k="task"]::before { opacity: 1; transition-duration: var(--m-in); }
@media (prefers-reduced-motion: reduce) {
  .tv-wire__on, .tv-wire__port, .tv-pin, .tv-sheet__part, .tv-sheet__part::before { transition: none; }
}
html[data-motion="off"] :is(.tv-wire__on, .tv-wire__port, .tv-pin, .tv-sheet__part, .tv-sheet__part::before) { transition: none; }

/* ---------------------------------------------------------------- #custom: the steps' screens (pinned-chapters)
   Each step's visual is a drawn window on its own tint of the lit ground. */
#custom .section-head { margin-bottom: 0; }
#custom .mo-pc__step h3 { display: flex; align-items: flex-start; gap: var(--s-3); }
/* the step's number: outlined at rest, filled in the accent on the step in hand (live), centred on
   the title's first line (a title line is 1.3 times --t-lead, the disc 32px) */
#custom .mo-pc__step h3 > .step-num { flex: none; margin-block: calc((1.3 * var(--t-lead) - 32px) / 2); transition: background-color 300ms var(--m-ease), border-color 300ms var(--m-ease), color 300ms var(--m-ease); }
.tv-step--1 { --ground-bg: #dcd8ff; }
.tv-step--2 { --ground-bg: #cfe2ff; }
.tv-step--3 { --ground-bg: #ffd9ee; }
.tv-step > .ui { width: min(100%, 380px); }
.tv-step > .tv-hub { width: 100%; height: 100%; min-height: 220px; }

/* live (from 1024px on a screen 640px or taller): the stage uses the screen under the header. The
   frame is as tall as the screen allows (4:5, at most the screen less the header and 48px above and
   below), on seven columns; the text on five, centred against it. The windows on it are wider than at
   rest, so the frame reads as a picture of the product, not a box.
   flex: none, because system.css gives a section's .wrap flex: 1 0 auto from 640 to 1279px, and the
   sticky stage then grew to the section's two screens and slid away instead of holding. */
main #custom.is-live > .mo-pc__grid { flex: none; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--s-8); }
#custom.is-live .mo-pc__visuals { aspect-ratio: 4 / 5; max-height: calc(100svh - var(--nav, 72px) - 2 * var(--s-7)); border-radius: var(--r-lg); overflow: clip; }
/* each visual fills the shared frame (at rest it keeps its own 4:3) */
#custom.is-live .mo-pc__visual { aspect-ratio: auto; height: 100%; }
#custom.is-live .tv-step > .ui { width: min(100% - 2 * var(--s-7), 440px); }
/* on a wide frame the windows read at a little over true size, so they hold the picture */
@media (min-width: 1280px) { #custom.is-live .tv-step > .ui { zoom: 1.2; } }
#custom.is-live .tv-step > .tv-hub { min-height: 0; }
#custom.is-live .mo-pc__text { gap: var(--s-7); }
#custom.is-live .mo-pc__steps { gap: var(--s-4); }
#custom.is-live .mo-pc__step { padding-block: var(--s-2); }
#custom.is-live .mo-pc__step.is-on .step-num { background: var(--accent); border-color: var(--accent); color: #ffffff; }
#custom.is-live .mo-pc__step:not(.is-on) .step-num { color: var(--muted); }
/* the step's lines open under its title, in line with the title's words */
#custom .mo-pc__step p { padding-left: calc(32px + var(--s-3)); }
@media (min-width: 1024px) and (max-width: 1279px) {
  main #custom.is-live > .mo-pc__grid { column-gap: var(--s-7); }
  #custom.is-live .tv-step > .ui { width: min(100% - 2 * var(--s-5), 400px); }
}

/* at rest (phones, tablets, a short screen, reduced motion): the section is as tall as its steps,
   --tv-sec above and below, not the moment's two screens */
main > #custom:not(.is-live) { height: auto; min-height: 0; padding-block: var(--tv-sec); }
/* a desktop at rest (reduced motion, a screen under 640px tall): a row per step, the screen 16:9 so a
   row is no taller than its window needs */
@media (min-width: 1024px) { #custom:not(.is-live) .mo-pc__step .mo-pc__visual { aspect-ratio: 16 / 9; } }
@media (min-width: 640px) and (max-width: 1023px) {
  /* a tablet stacks each step over its screen */
  #custom:not(.is-live) .mo-pc__step { grid-template-columns: minmax(0, 1fr); }
  #custom:not(.is-live) .mo-pc__step .mo-pc__visual { grid-column: 1; grid-row: auto; margin-top: var(--s-4); aspect-ratio: 16 / 9; }
}
@media (max-width: 639px) {
  /* a phone: each screen as tall as its window, never cut */
  #custom .tv-step { aspect-ratio: auto; padding: var(--s-5) var(--s-4); }
  #custom .tv-step > .tv-hub { height: 240px; }
  #custom .mo-pc__step p { padding-left: 0; }
}

/* ---------------------------------------------------------------- #ways: ready-made or custom, compared row by row
   (src/components/site/ways.tsx) One grid of seven rows: the option's name, the five criteria, the
   action. Each option is a card on the rows' subgrid, so every answer lines up with its neighbour.
   From 1024: the criteria as a column of their own at the left, the switch line under them beside the
   actions. 640 to 1023: the two options side by side, each answer under its criterion's name.
   A phone: one option under the other, each a list of its own. */
.tv-cmp { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: var(--gutter); }
.tv-cmp__criteria { display: none; margin: 0; padding: 0; list-style: none; }
#ways .tv-cmp__opt { gap: 0; transition: border-color var(--m-out) var(--m-ease); }
#ways .tv-cmp__opt > h3 { display: flex; align-items: center; gap: var(--s-2); padding-bottom: var(--s-5); }
.tv-cmp__opt > h3 > .ic { flex: none; width: 22px; height: 22px; color: var(--action); }
.tv-cmp__opt > dl { margin: 0; }
/* a row: the criterion's name over its answer, a rule above */
.tv-cmp__opt > dl > div, .tv-cmp__criteria > li { padding-block: var(--s-4); border-top: 1px solid var(--line); }
.tv-cmp__opt > dl > div:last-child, .tv-cmp__criteria > li:last-child { border-bottom: 1px solid var(--line); }
.tv-cmp__opt dt { margin-bottom: var(--s-1); color: var(--muted); font-size: var(--t-small); line-height: 1.4; }
.tv-cmp__opt dd { margin: 0; color: var(--c-text); font-size: var(--t-body); line-height: 1.5; text-wrap: pretty; }
#ways .tv-cmp__opt > .btn { justify-self: start; align-self: start; margin-top: var(--s-5); }
.tv-cmp__switch { margin: 0; color: var(--muted); font-size: var(--t-body); line-height: 1.5; text-wrap: pretty; }
#ways .section-head > p { text-wrap: pretty; }
@media (max-width: 639px) { .tv-cmp__opt > dl > div { padding-block: var(--s-3); } }

/* the card answers its action: the edge darkens a step while the button is hovered, takes the accent
   while it has keyboard focus (no lift: the card itself is not the link) */
@media (hover: hover) and (pointer: fine) {
  #ways .tv-cmp__opt:has(> .btn:hover) { border-color: color-mix(in oklab, var(--ink) 18%, transparent); transition-duration: var(--m-in); }
}
#ways .tv-cmp__opt:has(> .btn:focus-visible) { border-color: var(--action); }

@media (min-width: 640px) {
  .tv-cmp { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(7, auto) auto; column-gap: var(--gutter); row-gap: 0; }
  #ways .tv-cmp__opt { grid-row: 1 / span 7; display: grid; grid-template-rows: subgrid; }
  .tv-cmp__opt > dl { grid-row: span 5; display: grid; grid-template-rows: subgrid; }
  .tv-cmp__switch { grid-column: 1 / -1; grid-row: 8; margin-top: var(--s-5); }
}

@media (min-width: 1024px) {
  .tv-cmp { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(7, auto); }
  .tv-cmp__criteria {
    grid-column: 1; grid-row: 2 / span 5; display: grid; grid-template-rows: subgrid;
    color: var(--ink); font-size: var(--t-body); font-weight: 500; line-height: 1.5;
  }
  #ways .tv-cmp__opt:nth-of-type(1) { grid-column: 2; }
  #ways .tv-cmp__opt:nth-of-type(2) { grid-column: 3; }
  /* the column names the criteria; each answer keeps its name for a screen reader only */
  .tv-cmp__opt dt { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  /* the switch line sits on the actions' row, centred on the buttons */
  .tv-cmp__switch {
    grid-column: 1; grid-row: 7; align-self: start; display: flex; align-items: center;
    min-height: var(--btn-h); margin-top: var(--s-5); padding-right: var(--s-6);
  }
}

/* ---------------------------------------------------------------- #packs: the list and its frame
   The section is as tall as its content (site.css). The heading row on top (the link to the prices at
   its right), then the packs as a vertical tab list beside the frame that shows the chosen one. From
   1024 the two share one row and the frame is exactly as tall as the list; below, the frame follows
   the list. Each row: the pack's icon, name, price a month and an arrow; the chosen row takes a fill
   tinted with its screen's ground (--pack, set on the row), its icon chip in that colour, and opens
   to its two sentences. A line in the same colour runs from the chosen row to the frame. */
#packs .tv-packs { row-gap: var(--s-5); align-items: stretch; }
#packs .tv-picks__list { display: grid; gap: var(--s-2); }

#packs .tv-pick {
  position: relative; display: grid; grid-template-columns: 40px minmax(0, 1fr) auto 16px; grid-template-rows: 40px 0fr;
  column-gap: var(--s-4); align-items: center; width: 100%; padding: 11px var(--s-4) 11px 11px;
  border: 1px solid transparent; border-radius: var(--r-md); background: color-mix(in oklab, var(--ink) 5%, transparent);
  color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
#packs .tv-pick:hover { background: color-mix(in oklab, var(--ink) 9%, transparent); border-color: var(--line); }
#packs .tv-pick:not([aria-selected="true"]):active { scale: 0.985; }
#packs .tv-pick:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
#packs .tv-pick[aria-selected="true"] {
  grid-template-rows: 40px 1fr; cursor: default;
  background: color-mix(in oklab, var(--pack) 15%, var(--bg)); border-color: color-mix(in oklab, var(--pack) 55%, transparent);
}

#packs .tv-pick__icon {
  display: grid; place-items: center; width: 40px; height: 40px; border-radius: 10px;
  background: color-mix(in oklab, var(--ink) 8%, transparent); color: var(--muted);
}
#packs .tv-pick__icon > .ic { width: 20px; height: 20px; }
#packs .tv-pick:hover > .tv-pick__icon { color: var(--pack); }
#packs .tv-pick[aria-selected="true"] > .tv-pick__icon { background: var(--pack); color: var(--bg); }
#packs .tv-pick__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-body); font-weight: 500; }
#packs .tv-pick__price { color: var(--muted); font-size: var(--t-small); font-variant-numeric: tabular-nums; white-space: nowrap; }
#packs .tv-pick[aria-selected="true"] > .tv-pick__price { color: var(--ink); }
#packs .tv-pick__arrow { width: 16px; height: 16px; color: color-mix(in oklab, var(--ink) 45%, transparent); }
#packs .tv-pick:hover > .tv-pick__arrow { color: var(--ink); translate: 2px 0; }
#packs .tv-pick[aria-selected="true"] > .tv-pick__arrow { color: var(--pack); translate: 2px 0; }

/* the row's text: a grid row from 0fr to 1fr, so it opens and closes by its height. The text keeps
   --lines lines, the longest pack's text at each width in either language (measured from 320 to
   1920), so every open row is one height: the list, and the frame beside it, never change size
   when the pack changes. A copy change that adds a line needs these counts checked again */
#packs .tv-pick__more { grid-column: 2 / -1; grid-row: 2; min-height: 0; overflow: hidden; visibility: hidden; }
#packs .tv-pick[aria-selected="true"] > .tv-pick__more { visibility: visible; }
#packs .tv-pick__text {
  --lines: 3;
  display: block; min-height: calc(var(--lines) * 1lh + var(--s-2) + var(--s-1)); padding: var(--s-2) 0 var(--s-1);
  color: color-mix(in oklab, var(--ink) 84%, transparent); font-size: 15px; line-height: 1.5; opacity: 0;
}
#packs .tv-pick[aria-selected="true"] .tv-pick__text { opacity: 1; }
@media (min-width: 1440px) { html[lang="en"] #packs .tv-pick__text { --lines: 2; } }
@media (min-width: 1024px) and (max-width: 1119px) { #packs .tv-pick__text { --lines: 4; } }
@media (min-width: 600px) and (max-width: 1023px) { #packs .tv-pick__text { --lines: 2; } }
@media (max-width: 431px) { #packs .tv-pick__text { --lines: 4; } }
@media (max-width: 383px) { #packs .tv-pick__text { --lines: 5; } }

@media (min-width: 1024px) {
  /* the frame takes the list's height (its own ratio is only a floor) */
  #packs .tv-packs > .tv-packs__frame { --ratio: 40%; }
  /* the line from the chosen row across the gutter to the frame's edge */
  #packs .tv-pick[aria-selected="true"]::after {
    content: ""; position: absolute; left: calc(100% + 1px); top: 31px; width: calc(var(--gutter) - 1px); height: 2px;
    background: var(--pack); transform-origin: left center;
  }
}
@media (max-width: 1023px) {
  /* stacked, the chosen row's arrow points down at the frame under the list */
  #packs .tv-pick[aria-selected="true"] > .tv-pick__arrow { rotate: 90deg; translate: 0 2px; }
}
@media (max-width: 639px) {
  #packs .tv-pick { grid-template-columns: 36px minmax(0, 1fr) auto 14px; grid-template-rows: 36px 0fr; column-gap: var(--s-3); padding: 7px var(--s-3) 7px 7px; }
  #packs .tv-pick[aria-selected="true"] { grid-template-rows: 36px 1fr; }
  #packs .tv-pick__icon { width: 36px; height: 36px; border-radius: 9px; }
  #packs .tv-pick__arrow { width: 14px; height: 14px; }
  #packs .tv-pick__name { font-size: 15px; }
  #packs .tv-pick__price { font-size: 13px; }
}

/* light UI on the lit frame: the dark band's card colour would make the fragments dark */
#packs .frame--lit { --card: var(--ground-surface); --frag: #ffffff; --accent: var(--p-accent); --accent-ink: var(--p-accent-ink); padding: 0; }
/* one screen per pack, each on its own ground, filling the frame (the kit sets a frame's children relative) */
#packs .frame > .tv-screen { position: absolute; inset: 0; max-width: none; z-index: 1; }
.tv-screen__ground { position: absolute; inset: 0; }
#packs .frame > .tv-screen[hidden] { display: none; z-index: 0; }
/* the follow-up diagram fills its screen less 24px a side (diagram.css leaves a .dg in a stage in flow,
   as wide as the frame, where its widest layout would run into the frame's edge) */
#packs .tv-screen > .stage > .tv-dg { position: absolute; inset: var(--s-5); width: auto; }
/* the follow-up diagram held still (reduced motion, a phone) freezes its loop mid-run, one lane done:
   here it rests on the finished picture, every lane ticked, as its paused loop does */
#packs .tv-dg.is-still .dg-node > .dg-st { background: var(--dg-accent); box-shadow: none; }
#packs .tv-dg.is-still .dg-node > .dg-st svg,
#packs .tv-dg.is-still .dg-node > .dg-check { opacity: 1; scale: 1; }
#packs .tv-dg.is-still .dg-node:has(> :is(.dg-st, .dg-check)) > .dg-cap { color: var(--dg-ink); }
/* the frame's height follows the list (and the width), so a list screen shows only the rows that fit
   whole: the frame's edge never slices a line of text. Rows are 56px under a 90px head on a desktop
   and a tablet, up to 72px on a phone (two-line subtitles), where the last row also keeps clear of the
   bottom fade. A screen is a size container: its size comes from the frame alone */
#packs .tv-screen { container: tv-screen / size; }
/* a rising fragment stands in the middle of its screen, by its own width (--w). The kit centres one
   in a frame's own .stage; here the stage sits one level deeper, inside the pack's screen */
#packs .tv-screen > .stage > .at-rise { --ax: max(24px, calc(50% - var(--w, 64%) / 2)); }
@container tv-screen (max-height: 549px) { #packs .ui-apps__list > li:nth-child(n+8) { display: none; } }
@container tv-screen (max-height: 493px) { #packs .ui-apps__list > li:nth-child(n+7) { display: none; } }
@container tv-screen (max-height: 437px) { #packs .ui-apps__list > li:nth-child(n+6) { display: none; } }
@container tv-screen (max-height: 381px) { #packs .ui-apps__list > li:nth-child(n+5) { display: none; } }
/* a narrow frame (beside the list from 1024 to about 1279): the page and the chart take the frame's
   width less 24px a side, as a phone does (cards.css), so their right edge never cuts a line */
@media (min-width: 640px) {
  @container tv-screen (max-width: 539px) {
    #packs .tv-screen > .stage > :is(.at-rise, .at-corner):not(.wide) { left: 24px; right: 24px; width: auto; }
    #packs .tv-screen :is(.ui-doc, .ui-stat, .ui-apps) { width: 100%; }
  }
}
@media (max-width: 639px) {
  @container tv-screen (max-height: 473px) { #packs .ui-apps__list > li:nth-child(n+5) { display: none; } }
  @container tv-screen (max-height: 401px) { #packs .ui-apps__list > li:nth-child(n+4) { display: none; } }
}
/* stacked (below 1024) the frame is 4:3; a phone gets a little more than a square, and the invoice
   shows its first paragraphs only, so the text ends above the bottom fade */
#packs .frame--split { --ratio: 75%; }
@media (max-width: 639px) {
  #packs .frame--split { --ratio: 110%; }
  #packs .ui-doc__page > .ui-doc__text:nth-child(n+6) { display: none; }
}

/* ---------------------------------------------------------------- #packs: a pack change
   system.js toggles [hidden] on the screen a row controls and fades the chosen one in (opacity, 280ms).
   Around that:
   - the frame: the screen that goes keeps its place (display, allow-discrete) under the one that
     comes until that one has faded in over it, so the frame never shows an empty ground; its own
     fragment fades out first, so the two never read as one picture. The new screen's fragment
     rises 12px (@starting-style, armed only once the page is ready, so nothing moves at load).
   - the list: the old row closes while the new one opens (the same height, the same curve, so the
     list's height holds); the old text fades out at once, the new one fades in once its row has room.
     The line to the frame draws from the row. Hover and press answer at once. */
@media (prefers-reduced-motion: no-preference) {
  html:not([data-motion="off"]) #packs .frame > .tv-screen { transition: display 320ms allow-discrete; }
  html[data-ready]:not([data-motion="off"]) #packs .tv-screen > .stage { transition: translate 440ms var(--m-ease); }
  html:not([data-motion="off"]) #packs .tv-screen[hidden] > .stage { opacity: 0; transition: opacity 140ms var(--m-ease); }
  @starting-style {
    html[data-ready]:not([data-motion="off"]) #packs .tv-screen > .stage { translate: 0 12px; }
  }

  html:not([data-motion="off"]) #packs .tv-pick {
    transition: grid-template-rows 360ms var(--m-ease), background-color var(--m-out) var(--m-ease),
                border-color var(--m-out) var(--m-ease), scale var(--m-press) var(--m-ease);
  }
  html:not([data-motion="off"]) #packs .tv-pick:hover { transition-duration: 360ms, var(--m-in), var(--m-in), var(--m-press); }
  html:not([data-motion="off"]) #packs .tv-pick > :is(.tv-pick__icon, .tv-pick__price, .tv-pick__arrow) {
    transition: background-color var(--m-out) var(--m-ease), color var(--m-out) var(--m-ease),
                translate var(--m-out) var(--m-ease), rotate 360ms var(--m-ease);
  }
  html:not([data-motion="off"]) #packs .tv-pick > .tv-pick__more { transition: visibility 0s 360ms; }
  html:not([data-motion="off"]) #packs .tv-pick[aria-selected="true"] > .tv-pick__more { transition: visibility 0s; }
  html:not([data-motion="off"]) #packs .tv-pick .tv-pick__text { translate: 0 4px; transition: opacity 120ms var(--m-ease), translate 0s 360ms; }
  html:not([data-motion="off"]) #packs .tv-pick[aria-selected="true"] .tv-pick__text {
    translate: 0 0; transition: opacity 240ms var(--m-ease) 140ms, translate 320ms var(--m-ease) 140ms;
  }
  html[data-ready]:not([data-motion="off"]) #packs .tv-pick[aria-selected="true"]::after { transition: scale 280ms var(--m-ease) 120ms; }
  @starting-style {
    html[data-ready]:not([data-motion="off"]) #packs .tv-pick[aria-selected="true"]::after { scale: 0 1; }
  }
}

/* ---------------------------------------------------------------- #packs: the iris moment
   moment.css takes the stage off the screen (display: none) once the disc is open. On the first frame
   back above that point moment.js measures the stage before it shows it again, reads an empty box and
   draws the cover with a 2px hole: the whole section flashes the light ground, and stays so if the
   scroll stops there. Kept in layout but invisible while open, the stage always has its real box.
   (An #id rule: moment.css is injected after this file.) */
#packs.mo-io.is-open > .mo-io__stage { display: block; visibility: hidden; }

/* ---------------------------------------------------------------- #connect: the website, AI agents and sign-in
   Four cards (src/components/site/connect.tsx), each a title, its lines and a panel on the lit ground
   holding a mock-up in the kit's .ui classes: the website's form and the lead it becomes, the CRM
   calendar and the website's booking widget, the agent's chat beside the MCP apps, the sign-in step.
   From 1024: the two website cards side by side, then the agents (span-8) beside sign-in (span-4); the
   kit's spans take them a row each where a panel would be too narrow. Each card is a subgrid of three
   rows, so titles and panels line up across a row whatever the number of lines. The chat is the
   group's one loop; every other mock-up is static. */
#connect .tv-cx > .card { display: grid; grid-row: span 3; grid-template-rows: subgrid; row-gap: 0; }
#connect .panel { --p-h: 380px; }
@media (max-width: 639px) { #connect .panel { --p-h: 360px; } }
/* 640 to 1279: sign-in has a row to itself, where its small mock-up would sit alone in a wide, tall
   panel. There the card lies on its side: the words at the left, the panel down its right half */
@media (min-width: 640px) and (max-width: 1279px) {
  #connect .tv-cx > .tv-cx-card--signin {
    grid-row: auto; grid-template-rows: auto minmax(0, 1fr); grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--c-pad);
  }
  #connect .tv-cx-card--signin > :is(h3, p) { grid-column: 1; }
  #connect .tv-cx-card--signin > .panel {
    grid-column: 2; grid-row: 1 / span 2; --p-h: 320px;
    margin: calc(-1 * var(--c-pad) - 1px) calc(-1 * var(--c-pad) - 1px) calc(-1 * var(--c-pad) - 1px) 0;
  }
  #connect .tv-cx-card--signin > .panel::after { box-shadow: inset 1px 0 0 color-mix(in oklab, var(--ink) 7%, transparent); }
  /* the mock-up with the same ground above and below it */
  #connect .tv-cx-card--signin .tv-cx-at-sign { --ay: 30px; }
}

/* a website's piece: a browser bar (three dots and the page's or the site's name) over its body */
#connect .tv-cx-web { overflow: hidden; }
#connect .tv-cx-bar {
  display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 12px;
  border-bottom: 1px solid var(--u-line); background: var(--u-fill);
}
#connect .tv-cx-bar .ui-dots i { width: 8px; height: 8px; }
#connect .tv-cx-bar__label { min-width: 0; overflow: hidden; color: var(--u-muted); font-size: 12px; line-height: 16px; text-overflow: ellipsis; white-space: nowrap; }
#connect .tv-cx-web__body { display: grid; gap: 12px; padding: 14px 16px 16px; }
#connect .tv-cx-web__h { font-size: 14px; font-weight: 500; line-height: 20px; }
#connect .tv-cx-web__btn { justify-self: start; height: 32px; padding: 0 14px; }

/* the form: name and company side by side, the message under them */
#connect .tv-cx-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
#connect .tv-cx-field { display: grid; gap: 4px; min-width: 0; }
#connect .tv-cx-field:last-child { grid-column: 1 / -1; }
#connect .tv-cx-field__label { color: var(--u-muted); font-size: 12px; line-height: 16px; }
#connect .tv-cx-field__box {
  display: block; min-height: 32px; padding: 6px 10px; overflow: hidden; border-radius: var(--u-r3);
  background: var(--u-bg); box-shadow: inset 0 0 0 1px var(--u-line-2); text-overflow: ellipsis; white-space: nowrap;
}
#connect .tv-cx-field:last-child > .tv-cx-field__box { white-space: normal; }
/* the form at the top left, the lead it becomes over its lower right corner */
#connect .tv-cx-at-form { --ax: 40px; --ay: 32px; width: min(320px, 100% - 2 * var(--ax)); }
#connect .tv-cx-at-lead { --bx: 40px; --by: 32px; width: min(300px, 100% - 2 * var(--bx)); }
#connect .tv-cx-lead .ui-head { height: 40px; }
#connect .tv-cx-lead .ui-agent { width: 20px; height: 20px; }
#connect .tv-cx-lead__row { display: flex; align-items: center; gap: 12px; padding: 12px 16px; }
#connect .tv-cx-lead__text { display: grid; flex: 1; min-width: 0; }
#connect .tv-cx-lead__name { font-weight: 500; }
#connect .tv-cx-lead__sub { overflow: hidden; color: var(--u-muted); line-height: 16px; text-overflow: ellipsis; white-space: nowrap; }

/* the CRM calendar at the top right, the website's booking widget under it at the left */
#connect .tv-cx-at-cal { --ax: 40px; --ay: 32px; width: min(340px, 100% - 2 * var(--ax)); }
#connect .tv-cx-at-book { --bx: 40px; --by: 32px; width: min(300px, 100% - 2 * var(--bx)); }
#connect .tv-cx-slots { padding: 6px 0; }
#connect .tv-cx-slot { display: flex; align-items: center; gap: 12px; height: 52px; padding: 0 16px; }
#connect .tv-cx-slot + .tv-cx-slot { box-shadow: inset 0 1px 0 var(--u-line); }
#connect .tv-cx-slot__time { flex: none; width: 40px; color: var(--u-muted); font-variant-numeric: tabular-nums; }
#connect .tv-cx-slot__text { display: grid; flex: 1; min-width: 0; padding-left: 12px; border-left: 3px solid var(--u-fill-3); }
#connect .tv-cx-slot.is-on .tv-cx-slot__text { border-left-color: var(--u-accent); }
#connect .tv-cx-slot__name { font-weight: 500; }
#connect .tv-cx-slot__meta { color: var(--u-muted); line-height: 16px; }
#connect .tv-cx-book__body { display: flex; align-items: center; gap: 12px; padding: 12px 12px 12px 16px; }
#connect .tv-cx-book__pick { display: grid; flex: 1; min-width: 0; }
#connect .tv-cx-book__what { font-weight: 500; white-space: nowrap; }
#connect .tv-cx-book__left { color: var(--u-muted); line-height: 16px; white-space: nowrap; }

/* a website card's panel under 500px (two-up from 720 to 1279, and a phone): the two pieces stack
   across the panel's width, the website's under or over Tarvo's, in a taller panel, so neither
   covers the other's text or button */
#connect :is(.tv-cx-card--form, .tv-cx-card--bookings) > .panel { container: tv-cx / inline-size; }
@media (max-width: 1279px) { #connect :is(.tv-cx-card--form, .tv-cx-card--bookings) > .panel { --p-h: 424px; } }
#connect .panel { --tv-in: 24px; }
@media (max-width: 639px) { #connect .panel { --tv-in: 16px; } }
@container tv-cx (max-width: 499px) {
  #connect :is(.tv-cx-at-form, .tv-cx-at-cal) { top: 24px; left: var(--tv-in); right: var(--tv-in); width: auto; }
  #connect .tv-cx-at-lead { bottom: 24px; left: calc(var(--tv-in) + 24px); right: var(--tv-in); width: auto; }
  #connect .tv-cx-at-book { bottom: 24px; left: var(--tv-in); right: calc(var(--tv-in) + 24px); width: auto; }
  /* the company takes the row: two fields side by side would cut its name */
  #connect .tv-cx-field:first-child { display: none; }
  #connect .tv-cx-fields { grid-template-columns: minmax(0, 1fr); }
}

/* the agents: the chat and the MCP apps side by side, centred in the panel; the chat runs out of
   the bottom edge, the list stands whole */
#connect .tv-cx-pair { --ay: 40px; display: flex; align-items: flex-start; justify-content: center; gap: 24px; }
@media (min-width: 640px) { #connect .tv-cx-pair { left: 32px; right: 32px; } }
#connect .tv-cx-pair > .ui-chat { flex: 0 1 400px; min-width: 0; width: auto; }
#connect .tv-cx-pair > .tv-cx-apps { flex: 0 1 360px; min-width: 0; width: auto; height: auto; }
#connect .tv-cx-apps .ui-app { height: 48px; }
#connect .tv-cx-apps .ui-head > img { width: 16px; height: 16px; }
#connect .tv-cx-app { width: 24px; height: 24px; border-radius: 6px; }
#connect .tv-cx-app img { width: 14px; height: 14px; }
#connect .ui-msg__av.tv-cx-app { width: 22px; height: 22px; }
/* a phone has room for the chat alone; the card's lines name the apps */
@media (max-width: 639px) { #connect .tv-cx-apps { display: none; } }

/* sign-in: the two-factor step and the passkey still to come */
#connect .tv-cx-at-sign { --fit-max: 320px; --ax: 24px; --ay: 40px; }
#connect .tv-cx-sign__body { display: grid; gap: 12px; padding: 14px 16px 16px; }
#connect .tv-cx-sign__step { font-size: 14px; font-weight: 500; line-height: 20px; }
#connect .tv-cx-sign__hint { margin-top: -10px; color: var(--u-muted); }
#connect .tv-cx-code { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
#connect .tv-cx-code > span {
  display: grid; place-items: center; height: 40px; border-radius: var(--u-r3); box-shadow: inset 0 0 0 1px var(--u-line-2);
  font-size: 16px; font-weight: 500; font-variant-numeric: tabular-nums;
}
#connect .tv-cx-code > .is-on { box-shadow: inset 0 0 0 1.5px var(--u-accent); }
#connect .tv-cx-sign__go { height: 32px; }
#connect .tv-cx-sign__key {
  display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 6px 0 10px;
  border-radius: var(--u-r3); box-shadow: inset 0 0 0 1px var(--u-line); color: var(--u-muted);
}
#connect .tv-cx-sign__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------------------------------------------------------------- #roadmap: four lanes down one rail
   (src/components/site/roadmap.tsx) On the surface ground, so it parts #pricing from #questions.
   Each lane is a label (its mark, title, count and line) and a body. From 1024 the label takes
   three columns and the body nine, and a rail runs down the marks: solid under what is built,
   dashed from there on. Below 1024 the label stands over its body and the rail goes.
   Below 1024 one of the first three lanes shows at a time, chosen by the radios above them.
   The bodies: built is names only, grouped by area in balanced columns; in progress is a card each,
   with what is left under a rule; planned is the same columns of rows that tick; the request is a
   white panel whose send link carries the picks and the visitor's own words as an email. */
.tv-rm { display: grid; row-gap: var(--s-8); margin: 0; padding: 0; list-style: none; }
.tv-rm__lane { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); row-gap: var(--s-5); }
#roadmap-request { scroll-margin-top: calc(var(--nav) + var(--s-5)); }

/* the mark on the centre line of the title's first line (a title line is 1.2 times --t-h3) */
.tv-rm__label { --tv-rm-off: calc((1.2 * var(--t-h3) - 28px) / 2); display: grid; grid-template-columns: 28px minmax(0, 1fr); align-content: start; align-items: start; gap: var(--s-2) var(--s-4); }
.tv-rm__mark { width: 28px; height: 28px; margin-top: var(--tv-rm-off); overflow: visible; }
.tv-rm__fill { fill: var(--action); }
.tv-rm__ring { fill: none; stroke: var(--action); stroke-width: 1.5; }
.tv-rm__ring--dashed { stroke: color-mix(in oklab, var(--ink) 48%, transparent); stroke-dasharray: 3.2; }
.tv-rm__tick, .tv-rm__plus { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.tv-rm__tick { stroke: var(--action-ink); }
.tv-rm__plus { stroke: var(--action); stroke-width: 1.75; }
.tv-rm__title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s-3); min-width: 0; }
.tv-rm__count { color: var(--muted); font-size: var(--t-small); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tv-rm__label > p { grid-column: 1 / -1; margin: 0; max-width: 46ch; font-size: var(--t-body); line-height: 1.5; text-wrap: pretty; }

@media (min-width: 1024px) {
  .tv-rm__lane { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .tv-rm__label { grid-column: 1 / span 3; padding-right: var(--s-4); }
  .tv-rm__label > p { grid-column: 2; }
  .tv-rm__body { grid-column: 4 / -1; min-width: 0; }
  /* the rail: from 8px under a mark to 8px over the next one, on the marks' centre line */
  .tv-rm__lane:not(:last-child)::before {
    content: ""; position: absolute; left: 13.5px; top: 36px; bottom: calc(8px - var(--s-8));
    border-left: 1px dashed color-mix(in oklab, var(--ink) 30%, transparent);
  }
  .tv-rm__lane[data-lane="built"]::before { border-left: 1px solid var(--action); }
}

/* a group: an area's name over its features, a rule above. In columns a group never breaks; its
   bottom space is padding, which a column keeps (a margin there is dropped), and the body gives the
   last row's back */
.tv-rm__areas, .tv-rm__plans { columns: 3; column-gap: var(--gutter); margin-bottom: calc(-1 * var(--s-6)); }
.tv-rm__group { break-inside: avoid; padding: var(--s-3) 0 var(--s-6); border-top: 1px solid var(--line-strong); }
.tv-rm__group > h4 { margin: 0 0 var(--s-3); color: var(--muted); font: 500 var(--t-small)/1.4 var(--font-text); letter-spacing: 0; }

/* built: a name a row, a tick in the accent before it */
.tv-rm__done { display: grid; gap: var(--s-2); margin: 0; padding: 0; list-style: none; }
.tv-rm__done > li { display: grid; grid-template-columns: 16px minmax(0, 1fr); column-gap: 10px; font-size: var(--t-body); line-height: 1.4; }
.tv-rm__done > li::before {
  content: ""; width: 16px; height: 16px; margin-top: 3px; background: var(--action);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m3.5 8.4 2.9 2.9 6.1-6.5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 16px no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m3.5 8.4 2.9 2.9 6.1-6.5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 16px no-repeat;
}

/* in progress: each card a subgrid of four rows (glyph, name, line, what is left), so the rules
   line up across a row whatever the number of lines */
.tv-rm__cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
#roadmap .tv-rm__card { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; padding: var(--s-5); }
.tv-rm__card > .ic { width: 22px; height: 22px; margin-bottom: var(--s-4); color: var(--action); }
#roadmap .tv-rm__card > p { margin: var(--s-2) 0 0; max-width: none; text-wrap: pretty; }
#roadmap .tv-rm__card > .tv-rm__left {
  align-self: end; margin-top: var(--s-5); padding-top: var(--s-3); border-top: 1px solid var(--line);
  font-size: var(--t-small); font-weight: 500; line-height: 1.45;
}
.tv-rm__left > span { display: block; color: var(--muted); font-size: var(--t-label); }

/* planned: a row a feature, each a toggle button with a dashed ring where a built one has its
   tick. Picked, the ring fills in the accent and a tick draws in it. The button reaches 8px past its
   words on each side for its hover ground; the list steps back by as much on the left, so the rings
   stand on the ticks' line, and ends on the column's right line */
.tv-rm__picks { display: grid; gap: 2px; margin: -5px 0 -5px -8px; padding: 0; list-style: none; }
.tv-rm__pick {
  display: grid; grid-template-columns: 16px minmax(0, 1fr); column-gap: 10px; width: 100%; padding: 5px 8px;
  border: 0; border-radius: var(--r-sm); background: none; color: var(--ink);
  font: 400 var(--t-body)/1.4 var(--font-text); text-align: left; cursor: pointer;
  transition: background-color var(--m-out) var(--m-ease);
}
.tv-rm__pick > svg { width: 16px; height: 16px; margin-top: 3px; overflow: visible; }
.tv-rm__pick-ring {
  fill: transparent; stroke: color-mix(in oklab, var(--ink) 50%, transparent); stroke-width: 1.5; stroke-dasharray: 2.6 2.46;
  transition: fill var(--m-out) var(--m-ease), stroke var(--m-out) var(--m-ease);
}
.tv-rm__pick-tick { fill: none; stroke: var(--action-ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 10; stroke-dashoffset: 10; }
@media (hover: hover) and (pointer: fine) {
  .tv-rm__pick:hover { background: color-mix(in oklab, var(--ink) 7%, transparent); transition-duration: var(--m-in); }
  .tv-rm__pick:hover .tv-rm__pick-ring { stroke: var(--ink); }
}
.tv-rm__pick:active .tv-rm__pick-ring { fill: color-mix(in oklab, var(--action) 30%, transparent); }
.tv-rm__pick:focus-visible { outline: 2px solid var(--action); outline-offset: -2px; }
.tv-rm__pick[aria-pressed="true"] .tv-rm__pick-ring { fill: var(--action); stroke: var(--action); stroke-dasharray: none; }
.tv-rm__pick[aria-pressed="true"] .tv-rm__pick-tick { stroke-dashoffset: 0; transition: stroke-dashoffset 200ms var(--m-ease) 60ms; }

/* the request: the visitor's own words, then what was picked beside the send link */
.tv-rm__ask { display: grid; gap: var(--s-4); padding: var(--s-6); border-radius: var(--r-lg); background: var(--surface); }
.tv-rm__ask .field textarea { min-height: 96px; }
.tv-rm__ask .field textarea:focus-visible { outline: 2px solid var(--action); outline-offset: 1px; }
.tv-rm__send { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4) var(--s-6); }
.tv-rm__picked { display: grid; flex: 1 1 280px; gap: 2px; min-width: 0; margin: 0; }
.tv-rm__picked > b { font-weight: 500; font-variant-numeric: tabular-nums; }
.tv-rm__picked > span, .tv-rm__note { color: var(--muted); font-size: var(--t-small); line-height: 1.45; }
.tv-rm__note { margin: 0; }

/* a narrow label column: the line under the title keeps what room there is */
@media (min-width: 1024px) and (max-width: 1279px) {
  .tv-rm__label { column-gap: var(--s-3); padding-right: 0; }
}
@media (max-width: 1279px) {
  .tv-rm__areas, .tv-rm__plans { columns: 2; }
  .tv-rm__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* below 1024, where the lanes stack and the rail goes: a switch between the first three lanes (the
   page's segmented control), three radios and :has(), no script. Without :has() every lane shows,
   as from 1024px. (#roadmap: .tv-seg sets its own display further down this file.) */
#roadmap .tv-rm__switch { display: none; }
@media (max-width: 1023px) {
  /* as wide as its three words (the .wrap is a flex column, which would stretch it) */
  #roadmap .tv-rm__switch { display: inline-flex; align-self: flex-start; margin-bottom: var(--s-6); }
  #roadmap:has(input[value="built"]:checked) .tv-rm__lane:is([data-lane="building"], [data-lane="planned"]),
  #roadmap:has(input[value="building"]:checked) .tv-rm__lane:is([data-lane="built"], [data-lane="planned"]),
  #roadmap:has(input[value="planned"]:checked) .tv-rm__lane:is([data-lane="built"], [data-lane="building"]) { display: none; }
}
@media (max-width: 639px) {
  .tv-rm { row-gap: var(--s-7); }
  #roadmap .tv-rm__switch { display: flex; align-self: stretch; }
  .tv-rm__switch > .tv-seg__opt { flex: 1 1 auto; font-size: 15px; }
  .tv-rm__areas, .tv-rm__plans { columns: 1; }
  .tv-rm__cards { grid-template-columns: minmax(0, 1fr); }
  /* a finger's row */
  .tv-rm__pick { padding-block: 10px; }
  .tv-rm__picks { margin-block: -10px; }
  .tv-rm__ask { padding: var(--s-5); }
  .tv-rm__send > .btn { width: 100%; }
}
/* the narrowest phones: the three words of the longer language still fit the track */
@media (max-width: 359px) {
  .tv-rm__switch > .tv-seg__opt { padding: 0 var(--s-2); font-size: 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .tv-rm__pick, .tv-rm__pick-ring, .tv-rm__pick[aria-pressed="true"] .tv-rm__pick-tick { transition: none; }
}
html[data-motion="off"] :is(.tv-rm__pick, .tv-rm__pick-ring, .tv-rm__pick-tick) { transition: none !important; }

/* ---------------------------------------------------------------- #pricing: the needs the visitor states and the plan cards that answer them
   (src/components/site/pricing/calculator.tsx) */

/* ---------------------------------------------------------------- the needs: users, packs, billing
   One grid. From 1280: users and billing at the heading's right, the packs across the row under it.
   Below 1280: users and billing side by side, the packs under them. A phone: one column. */
.tv-top {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: end;
  grid-template-areas: "head users billing" "packs packs packs";
  gap: var(--s-6) var(--s-6); margin-bottom: var(--s-6);
}
#pricing .tv-top > .section-head { grid-area: head; margin-bottom: 0; }
.tv-need--users { grid-area: users; }
.tv-need--packs { grid-area: packs; }
.tv-need--billing { grid-area: billing; }
.tv-need { margin: 0; padding: 0; border: 0; min-width: 0; }
.tv-need > legend { padding: 0; margin-bottom: var(--s-2); color: var(--ink); font-weight: 500; }
.tv-need__note { margin-left: var(--s-1); color: var(--muted); font-weight: 400; }

/* a segmented choice of real radios: the chosen option a raised pill on the tinted track */
.tv-seg { display: inline-flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
.tv-seg__opt {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  height: 44px; padding: 0 var(--s-4); border-radius: 999px; color: var(--muted); font-weight: 500; white-space: nowrap; cursor: pointer;
  transition: color var(--m-in) var(--m-ease), background-color var(--m-out) var(--m-ease), box-shadow var(--m-out) var(--m-ease);
}
.tv-seg__opt > input { position: absolute; inset: 0; margin: 0; border-radius: inherit; opacity: 0; cursor: pointer; }
.tv-seg__opt:hover { color: var(--ink); }
.tv-seg__opt:has(> input:checked) { background: var(--bg); color: var(--ink); box-shadow: 0 0 0 1px var(--line), 0 1px 3px rgb(20 18 31 / .1); }
.tv-seg__opt:has(> input:focus-visible) { outline: 2px solid var(--action); outline-offset: 2px; }
.tv-seg__save {
  display: inline-flex; align-items: center; height: 22px; padding: 0 var(--s-2); border-radius: 999px;
  background: color-mix(in oklab, var(--action) 12%, var(--bg)); color: var(--action); font: 500 var(--t-label)/1 var(--font-text);
}

/* the packs as toggle tiles (buttons with aria-pressed), each with its own price a month: six in a
   row, the name over the price. A chosen one takes the brand tint */
.tv-chips { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s-2); }
.tv-chip {
  display: flex; align-items: center; gap: var(--s-3); min-width: 0; height: 60px; padding: 0 var(--s-4);
  border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--bg); color: var(--ink);
  font: 500 15px/1.2 var(--font-text); text-align: left; white-space: nowrap; cursor: pointer;
  transition: background-color var(--m-out) var(--m-ease), border-color var(--m-out) var(--m-ease), transform var(--m-press) var(--m-ease);
}
.tv-chip > .ic { flex: none; width: 20px; height: 20px; color: var(--muted); transition: color var(--m-out) var(--m-ease); }
.tv-chip__text { display: grid; gap: 3px; min-width: 0; }
.tv-chip__name { overflow: hidden; text-overflow: ellipsis; }
.tv-chip__price { color: var(--muted); font-weight: 400; font-size: var(--t-small); font-variant-numeric: tabular-nums; }
.tv-chip:hover { border-color: color-mix(in oklab, var(--ink) 40%, transparent); transition-duration: var(--m-in); }
.tv-chip[aria-pressed="true"] { border-color: var(--action); background: color-mix(in oklab, var(--action) 10%, var(--bg)); }
.tv-chip[aria-pressed="true"] > .ic { color: var(--action); }
.tv-chip:active { transform: scale(.97); }

/* ---------------------------------------------------------------- the plan cards
   Each card is a subgrid of the row's seven rows (head, audience, price, billing, packs, button,
   what it includes), so prices, buttons and lists line up and every card is the row's height. */
.tv-plans { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(7, auto); column-gap: var(--gutter); }
#pricing .tv-plan {
  grid-row: span 7; display: grid; grid-template-rows: subgrid; gap: 0; align-content: start;
  transition: background-color 240ms var(--m-ease), border-color 240ms var(--m-ease), box-shadow 240ms var(--m-ease), transform 180ms var(--m-ease);
}
.tv-plan :is(h3, p, li, .ic, .tv-plan__tag) { transition: color 240ms var(--m-ease), opacity 240ms var(--m-ease), background-color 240ms var(--m-ease); }
.tv-plan__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); min-height: 28px; }
#pricing .tv-plan__head > h3 { display: flex; align-items: center; gap: var(--s-2); margin: 0; }
.tv-plan__head > h3 > .ic { width: 22px; height: 22px; color: var(--action); }
.tv-plan__tag { display: inline-flex; align-items: center; height: 26px; padding: 0 10px; border-radius: 999px; font: 500 var(--t-label)/1 var(--font-text); white-space: nowrap; }
.tv-plan__tag--small { color: var(--muted); box-shadow: inset 0 0 0 1px var(--line-strong); }
#pricing .tv-plan > p { margin: 0; max-width: none; }
#pricing .tv-plan > .tv-plan__for { margin-top: var(--s-1); color: var(--c-text); }
#pricing .tv-plan > .tv-plan__price {
  margin-top: var(--s-5); color: var(--ink);
  font: var(--display-weight) clamp(40px, 1.2vw + 30px, 48px)/1.1 var(--font-display); letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
#pricing .tv-plan > .tv-plan__note { margin-top: var(--s-1); color: var(--muted); font-size: var(--t-small); line-height: 1.45; }
#pricing .tv-plan > .tv-plan__packs { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line); color: var(--c-text); font-size: var(--t-small); line-height: 1.45; }
#pricing .tv-plan > .btn { width: 100%; margin-top: var(--s-5); }
#pricing .tv-plan > .checks { margin: var(--s-5) 0 0; padding: 0; color: var(--c-text); }

/* hover and focus: a 2px lift and a darker edge (the kit leaves plan cards still, so this is the one lift) */
@media (hover: hover) and (pointer: fine) {
  html:not([data-motion="off"]) #pricing .tv-plan:hover {
    transform: translateY(-2px); border-color: color-mix(in oklab, var(--ink) 18%, transparent);
    box-shadow: 0 1px 2px rgb(20 18 31 / .06), 0 18px 36px -20px rgb(20 18 31 / .3);
  }
}
#pricing .tv-plan:has(:focus-visible) { border-color: var(--action); }

/* the best fit: the brand's own fill, white type, the button turned white; a soft light from the top
   corner (its own layer, so it fades in and out with the fill instead of jumping) */
#pricing .tv-plan::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  background: radial-gradient(120% 70% at 0% 0%, rgb(255 255 255 / .2), transparent 60%);
  transition: opacity 240ms var(--m-ease);
}
#pricing .tv-plan.is-fit {
  --ink: #ffffff; --muted: rgb(255 255 255 / .8); --c-text: rgb(255 255 255 / .9); --line: rgb(255 255 255 / .24);
  --action: #ffffff; --action-ink: var(--p-action);
  background-color: var(--p-action); border-color: var(--p-action);
  box-shadow: 0 24px 48px -28px color-mix(in oklab, var(--p-action) 80%, transparent);
}
#pricing .tv-plan.is-fit::before { opacity: 1; }
#pricing .tv-plan.is-fit .tv-plan__tag { background: #ffffff; color: var(--p-action); }
#pricing .tv-plan.is-fit > .btn--primary:hover { background: color-mix(in oklab, #ffffff 88%, var(--p-action)); }
@media (hover: hover) and (pointer: fine) {
  html:not([data-motion="off"]) #pricing .tv-plan.is-fit:hover { border-color: var(--p-action); box-shadow: 0 28px 52px -26px color-mix(in oklab, var(--p-action) 90%, transparent); }
}

/* a plan too small for the team: a plain card, its numbers faded, the tag saying why */
#pricing .tv-plan.is-small { background-color: var(--bg); }
#pricing .tv-plan.is-small > :is(.tv-plan__price, .tv-plan__note, .tv-plan__packs, .checks) { opacity: .55; }

/* past the plans: two linked cards, the full calculator and the custom build */
.tv-more { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gutter); margin-top: var(--gutter); }
.tv-more__card { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s-1) var(--s-6); }
.tv-more__card > .t-card { grid-column: 1; }
.tv-more__line { grid-column: 1; color: var(--c-text, var(--muted)); font-size: var(--t-small); line-height: 1.45; }
.tv-more__card > .link { grid-column: 2; grid-row: 1 / span 2; white-space: nowrap; }

/* ---------------------------------------------------------------- the rolling total
   A changed digit rolls in from below when the amount rises and from above when it falls, the old
   digit leaving the other way; units first, each digit to the left 28ms later, 470ms at most.
   At rest, and under reduced motion, only the new digits show. */
.tv-roll { --from: 1; }
.tv-roll[data-dir="down"] { --from: -1; }
.tv-roll__text { display: inline-flex; white-space: pre; overflow: clip; padding-block: .1em; margin-block: -.1em; }
.tv-roll__cell { position: relative; display: inline-block; }
.tv-roll__out { position: absolute; left: 0; top: 0; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  html:not([data-motion="off"]) .tv-roll__in { display: inline-block; animation: tv-roll-in 330ms cubic-bezier(.22, 1, .36, 1) calc(var(--i) * 28ms) both; }
  html:not([data-motion="off"]) .tv-roll__out { animation: tv-roll-out 330ms cubic-bezier(.22, 1, .36, 1) calc(var(--i) * 28ms) both; }
}
@keyframes tv-roll-in { from { opacity: 0; transform: translateY(calc(var(--from) * 70%)); } }
@keyframes tv-roll-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(calc(var(--from) * -70%)); } }

@media (prefers-reduced-motion: reduce) {
  #pricing .tv-plan, #pricing .tv-plan:hover, .tv-chip:active { transform: none; }
}

/* ---------------------------------------------------------------- at each width */
@media (max-width: 1279px) {
  .tv-top { grid-template-columns: auto auto minmax(0, 1fr); grid-template-areas: "head head head" "users billing ." "packs packs packs"; row-gap: var(--s-5); }
}
@media (min-width: 1024px) and (max-width: 1279px) {
  /* narrower cards: the packs line keeps room for its two lines, so a longer one never moves the row */
  #pricing .tv-plan { --c-pad: 24px; }
  #pricing .tv-plan > .tv-plan__packs { min-height: calc(2lh + var(--s-3) + 1px); }
}
@media (max-width: 1023px) {
  /* one card a row: the plan on the left, what it includes on the right */
  .tv-plans { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: var(--s-4); }
  #pricing .tv-plan { grid-row: auto; grid-template-rows: none; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-7); }
  #pricing .tv-plan > :not(.checks) { grid-column: 1; }
  #pricing .tv-plan > .checks { grid-column: 2; grid-row: 1 / span 6; align-self: center; margin: 0; }
}
@media (max-width: 1279px) {
  .tv-chips { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tv-more__card { grid-template-columns: minmax(0, 1fr); }
  .tv-more__card > .link { grid-column: 1; grid-row: auto; justify-self: start; margin-top: var(--s-3); }
}
@media (min-width: 640px) and (max-width: 1023px) {
  #pricing .tv-plan > .tv-plan__packs { min-height: calc(2lh + var(--s-3) + 1px); }
}
@media (max-width: 639px) {
  .tv-top { grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "users" "packs" "billing"; }
  .tv-seg { display: flex; }
  .tv-seg__opt { flex: 1 1 0; padding: 0 var(--s-3); }
  .tv-chips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tv-chip { padding: 0 var(--s-3); }
  .tv-more { grid-template-columns: minmax(0, 1fr); }
  #pricing .tv-plan { grid-template-columns: minmax(0, 1fr); }
  #pricing .tv-plan > .checks { grid-column: 1; grid-row: auto; margin-top: var(--s-5); }
}

/* ---------------------------------------------------------------- #questions: the heading left, the rows right */
/* under 1024 the heading, the rows, then the way to ask; from 1024 the heading and the ask stack on
   the left (the second row takes what the rows leave) and the rows run down the right */
#questions .tv-qs { row-gap: var(--s-7); align-items: start; }
#questions .tv-qs__head > * + * { margin-top: var(--s-4); }
#questions .tv-qs__head h2 { max-width: 14ch; }
#questions .tv-qs__head .t-lead { max-width: 34ch; color: var(--muted); }
/* the way to ask something else: a quiet panel under the lead, on the column's width */
#questions .tv-qs__ask {
  display: grid; justify-items: start; gap: var(--s-2); max-width: 440px;
  padding: var(--s-5) var(--s-6) var(--s-6); border-radius: var(--r-lg); background: var(--surface);
}
#questions .tv-qs__ask > p { margin: 0; }
#questions .tv-qs__ask > p:not(.t-card) { color: var(--muted); }
#questions .tv-qs__ask > .link { margin-top: var(--s-3); }
@media (max-width: 1023px) {
  #questions .tv-qs__ask { max-width: none; }
}
@media (min-width: 1024px) {
  #questions .tv-qs { grid-template-rows: auto 1fr; }
  #questions .tv-qs__head, #questions .tv-qs__ask { grid-column: 1 / span 5; }
  #questions .tv-faq { grid-column: 7 / -1; grid-row: 1 / span 2; }
}

/* the highlight's colour: the brand violet lifted toward white, so the ink on it keeps its contrast */
#questions { --tv-hl: color-mix(in oklab, var(--p-accent) 27%, #fff); --tv-open: 380ms; }

.tv-faq { border-top: 1px solid var(--line); }
.tv-faq__row { border-bottom: 1px solid var(--line); }
.tv-faq__q { margin: 0; font: inherit; letter-spacing: 0; }

/* the whole row is the button; its hover and focus box reaches 12px past the text on each side */
.tv-faq__q > button {
  position: relative; isolation: isolate; display: flex; align-items: center; justify-content: space-between; gap: var(--s-5);
  width: 100%; margin: 0; padding: var(--s-5) 0; border: 0; background: none; color: var(--ink); text-align: left; cursor: pointer;
  font: 500 var(--t-lead)/1.4 var(--font-text); letter-spacing: 0; outline: none;
}
.tv-faq__q > button::before {
  content: ""; position: absolute; inset: 6px calc(-1 * var(--s-3)); z-index: -1; border-radius: var(--r-md);
  background: var(--surface); opacity: 0; transition: opacity var(--m-out) var(--m-ease), box-shadow var(--m-out) var(--m-ease);
}
@media (hover: hover) and (pointer: fine) {
  .tv-faq__q > button:hover::before { opacity: 1; transition-duration: var(--m-in); }
}
.tv-faq__q > button:focus-visible::before { opacity: 1; box-shadow: 0 0 0 2px var(--action); }

/* the sign: a plus in a ring; open, its upright bar turns flat (a minus) and the ring fills */
.tv-faq__sign {
  position: relative; flex: none; width: 28px; height: 28px; border-radius: 999px;
  border: 1px solid var(--line-strong); color: var(--ink);
  transition: background-color var(--tv-open) var(--m-ease), border-color var(--tv-open) var(--m-ease), color var(--tv-open) var(--m-ease);
}
.tv-faq__sign::before, .tv-faq__sign::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 10px; height: 1.5px; margin: -0.75px 0 0 -5px;
  border-radius: 1px; background: currentColor; transition: transform var(--tv-open) var(--m-ease);
}
.tv-faq__sign::after { transform: rotate(90deg); }
@media (hover: hover) and (pointer: fine) {
  .tv-faq__q > button:hover .tv-faq__sign { border-color: color-mix(in oklab, var(--ink) 40%, transparent); }
}
.tv-faq__row[data-open] .tv-faq__sign { background: var(--action); border-color: var(--action); color: var(--action-ink); }
.tv-faq__row[data-open] .tv-faq__sign::after { transform: rotate(180deg); }
.tv-faq__row[data-open] .tv-faq__sign::before { transform: rotate(180deg); }

/* the answer: its row grows from 0fr to 1fr. Closed, it turns hidden once it has shut, so it leaves
   the accessibility tree and the tab order; it stays in the HTML */
.tv-faq__panel {
  display: grid; grid-template-rows: 0fr; visibility: hidden;
  transition: grid-template-rows var(--tv-open) var(--m-ease-io), visibility 0s linear var(--tv-open);
}
.tv-faq__row[data-open] .tv-faq__panel { grid-template-rows: 1fr; visibility: visible; transition: grid-template-rows var(--tv-open) var(--m-ease-io), visibility 0s; }
.tv-faq__body { min-height: 0; overflow: hidden; }
.tv-faq__body > p {
  max-width: 66ch; margin: 0; padding: 0 var(--s-7) var(--s-5) 0; color: var(--ink);
  opacity: 0; transform: translateY(-6px); transition: opacity 200ms var(--m-ease), transform var(--tv-open) var(--m-ease);
}
.tv-faq__row[data-open] .tv-faq__body > p { opacity: 1; transform: none; transition-delay: 80ms; }

/* the marked phrases: a band under the lower part of the words, drawn left to right once the answer
   has opened (a second mark follows 140ms later), then still. "slice" lets a mark that wraps draw
   along the first line, then the next. Closed, the band goes back to nothing after the row has shut */
.tv-mark {
  color: inherit; background: linear-gradient(var(--tv-hl), var(--tv-hl)) no-repeat 0 92% / 0% 58%;
  -webkit-box-decoration-break: slice; box-decoration-break: slice;
  transition: background-size 0s linear var(--tv-open);
}
.tv-faq__row[data-open] .tv-mark {
  background-size: 100% 58%;
  transition: background-size 520ms var(--m-ease) calc(200ms + var(--i, 0) * 140ms);
}

@media (max-width: 639px) {
  .tv-faq__q > button { padding: var(--s-4) 0; font-size: 17px; }
  .tv-faq__body > p { padding-right: 0; padding-bottom: var(--s-4); }
}

@media (prefers-reduced-motion: reduce) {
  .tv-faq__panel, .tv-faq__row[data-open] .tv-faq__panel, .tv-faq__body > p, .tv-faq__sign, .tv-faq__sign::before, .tv-faq__sign::after { transition: none; }
  .tv-faq__body > p { transform: none; }
  .tv-mark, .tv-faq__row[data-open] .tv-mark { background-size: 100% 58%; transition: none; }
}

/* ---------------------------------------------------------------- the close: one block on the dark ground
   the ask (heading, line, button), the link columns under a hairline, the name across the .wrap,
   the legal row */
/* the legal row closes the page: a short foot under it, not a section's padding */
#contact { padding-bottom: var(--s-6); }
#contact > .wrap { display: flex; flex-direction: column; gap: 0; }

#contact .tv-foot__top { align-items: end; row-gap: var(--s-6); }
#contact .tv-foot__top > h2 { font-size: var(--t-h1); line-height: 1.02; letter-spacing: var(--display-tracking-xl); max-width: 16ch; margin: 0; }
#contact .tv-foot__ask { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-5); }
#contact .tv-foot__ask > .t-lead { margin: 0; max-width: 34ch; color: var(--muted); }
@media (min-width: 1024px) {
  #contact .tv-foot__top > h2 { grid-column: 1 / span 8; }
  #contact .tv-foot__ask { grid-column: 9 / -1; }
}

/* the columns: one each for the product, the pricing and the contact, on the ask's lines */
#contact .tv-foot__nav { margin-top: var(--s-8); padding-top: var(--s-6); border-top: 1px solid var(--line); row-gap: var(--s-6); }
#contact .tv-foot__col { grid-column: auto / span 4; }
#contact .tv-foot__col h3 { margin: 0 0 var(--s-4); font: 500 var(--t-small)/1.4 var(--font-text); letter-spacing: 0; color: var(--muted); }
#contact .tv-foot__col ul { margin: 0; padding: 0; list-style: none; display: grid; justify-items: start; gap: var(--s-3); font-size: var(--t-body); }
@media (max-width: 639px) {
  #contact .tv-foot__col { grid-column: auto / span 6; }
}

/* the name across the .wrap, edge to edge: its size follows the container's width (cqi). The ratio is
   the word's ink width in em in Funnel Display at this tracking; the margin pulls the T's side bearing
   back onto the left line */
#contact .tv-foot__word { container-type: inline-size; margin-top: var(--s-7); user-select: none; pointer-events: none; }
#contact .tv-foot__word > span {
  /* "Tarvo" in Funnel Display at -0.02em: its ink is 2.4707em wide and starts 0.02em in */
  --em: calc(100cqi / 2.4707);
  display: block; width: max-content; white-space: nowrap; margin-left: calc(-0.02 * var(--em));
  font: var(--display-weight) var(--em) / 0.74 var(--font-display); letter-spacing: -0.02em;
  /* a step off the ground in the brand's violet: the name signs the page, the ask above stays the strong part */
  color: color-mix(in oklab, var(--p-accent) 30%, var(--bg));
}

#contact .footer__legal { margin-top: var(--s-6); align-items: center; }
#contact .footer__legal > :last-child { margin-left: auto; color: var(--ink); }
@media (max-width: 639px) {
  #contact .footer__legal { flex-direction: column; align-items: flex-start; gap: var(--s-2); }
  #contact .footer__legal > :last-child { margin-left: 0; margin-top: var(--s-2); }
}

/* ---------------------------------------------------------------- the calculator subpage (src/app/[lang]/calculator)
   One section: the heading, the mode switch and the controls on the left, the summary card on the
   right (sticky from 1024px). Under 1024px one column, the summary after the controls and a bar
   pinned to the bottom that keeps the total in view until the summary comes up.
   Everything renders from React state (src/components/site/configurator), so nothing here carries
   the kit's scripted hooks. */

/* the section clears the fixed header on its own: it is the page's first */
main > #calculator { padding-top: calc(var(--nav) + var(--s-7)); padding-bottom: var(--tv-sec); }
@media (max-width: 639px) { main > #calculator { padding-top: calc(var(--nav) + var(--s-5)); } }

.tv-cfg { display: grid; grid-template-columns: minmax(0, 1fr) 400px; column-gap: var(--s-8); align-items: start; }
.tv-cfg__side { position: sticky; top: calc(var(--nav) + var(--s-5)); }
/* a short screen: the card scrolls inside rather than run past the fold */
.tv-cfg__side {
  max-height: calc(100svh - var(--nav) - 2 * var(--s-5)); overflow-y: auto; overscroll-behavior: contain;
  border-radius: var(--r-lg); scrollbar-width: thin; scrollbar-color: rgb(255 255 255 / .25) transparent;
}

/* ---------------------------------------------------------------- the heading */
.tv-cfg__head h1 { font-size: clamp(34px, 1.9vw + 22px, 52px); line-height: 1.06; }
.tv-cfg__lead p { margin-top: var(--s-3); max-width: 58ch; color: color-mix(in oklab, var(--ink) 84%, var(--bg)); font-size: var(--t-lead); line-height: 1.5; }

/* ---------------------------------------------------------------- the mode switch
   Two real radios; a raised pill slides behind the chosen one. */
.tv-mode {
  position: relative; isolation: isolate; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px;
  max-width: 640px; margin-top: var(--s-6); padding: 4px; border-radius: var(--r-lg);
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
}
.tv-mode::before {
  content: ""; position: absolute; z-index: -1; top: 4px; bottom: 4px; left: 4px; width: calc(50% - 6px);
  border-radius: calc(var(--r-lg) - 4px); background: var(--bg);
  box-shadow: 0 0 0 1px var(--line), 0 2px 8px rgb(20 18 31 / .08);
  transition: transform 340ms var(--m-ease-io);
}
.tv-cfg[data-mode="custom"] .tv-mode::before { transform: translateX(calc(100% + 4px)); }
.tv-mode__opt {
  position: relative; display: grid; align-content: center; gap: 2px; min-height: 64px; padding: var(--s-3) var(--s-5);
  border-radius: calc(var(--r-lg) - 4px); cursor: pointer;
}
.tv-mode__opt > input { position: absolute; inset: 0; margin: 0; border-radius: inherit; opacity: 0; cursor: pointer; }
.tv-mode__title { color: var(--muted); font: 500 17px/1.3 var(--font-text); transition: color var(--m-out) var(--m-ease); }
.tv-mode__line { color: var(--muted); font-size: var(--t-small); line-height: 1.35; font-variant-numeric: tabular-nums; }
.tv-mode__opt:hover .tv-mode__title, .tv-mode__opt:has(> input:checked) .tv-mode__title { color: var(--ink); transition-duration: var(--m-in); }
.tv-mode__opt:has(> input:focus-visible) { outline: 2px solid var(--action); outline-offset: 2px; }

/* ---------------------------------------------------------------- the groups */
.tv-cfg__controls { margin-top: var(--s-6); }
.tv-grp { padding-block: var(--s-6); border-top: 1px solid var(--line); }
.tv-grp:last-child { padding-bottom: 0; }
.tv-grp__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s-3); margin-bottom: var(--s-4); }
.tv-grp__title { font: 500 var(--t-card)/1.3 var(--font-text); letter-spacing: -0.01em; }
.tv-grp__note { color: var(--muted); font-size: var(--t-small); }
.tv-grp__aside { margin-left: auto; }
.tv-grp__price { font-weight: 500; font-variant-numeric: tabular-nums; }
.tv-grp__sub { margin: calc(-1 * var(--s-2)) 0 var(--s-4); color: color-mix(in oklab, var(--ink) 84%, var(--bg)); font-size: var(--t-small); }
.tv-grp__limit { margin-top: var(--s-3); color: var(--muted); font-size: var(--t-small); }

/* ---------------------------------------------------------------- a stepper: minus, the number, plus */
.tv-step {
  display: inline-flex; flex: none; align-items: center; gap: 2px; padding: 3px; border-radius: 999px;
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
}
.tv-step__btn {
  display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 999px;
  background: var(--bg); color: var(--ink); cursor: pointer;
  box-shadow: 0 0 0 1px var(--line), 0 1px 2px rgb(20 18 31 / .06);
  transition: background-color var(--m-out) var(--m-ease), color var(--m-out) var(--m-ease), box-shadow var(--m-out) var(--m-ease), transform var(--m-press) var(--m-ease);
}
.tv-step__btn:hover { background: color-mix(in oklab, var(--action) 9%, var(--bg)); color: var(--action); transition-duration: var(--m-in); }
.tv-step__btn:active { transform: scale(.92); }
/* at its limit: it stays focusable (aria-disabled) and does nothing */
.tv-step__btn[aria-disabled="true"] { background: transparent; color: color-mix(in oklab, var(--ink) 28%, transparent); box-shadow: none; cursor: default; transform: none; }
.tv-step__field { display: block; overflow: clip; border-radius: var(--r-sm); }
.tv-step__field:has(> :focus-visible) { outline: 2px solid var(--action); outline-offset: 0; }
.tv-step__value {
  display: block; width: 3.4em; height: 44px; padding: 0; border: 0; background: none; color: var(--ink);
  font: 500 20px/44px var(--font-text); text-align: center; font-variant-numeric: tabular-nums;
}
.tv-step__value:focus-visible { outline: none; animation: none; }
.tv-step__unit { padding: 0 var(--s-4) 0 var(--s-2); color: var(--muted); font-size: var(--t-small); white-space: nowrap; }

/* ---------------------------------------------------------------- users: the stepper, the plan scale, the plan */
.tv-users { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-4) var(--s-5); }
/* not a control: it shows where the team falls; a raised pill slides to the plan */
.tv-scale {
  position: relative; isolation: isolate; flex: 1 1 340px; display: grid; grid-template-columns: repeat(var(--steps), minmax(0, 1fr));
  padding: 3px; border-radius: var(--r-md); background: var(--surface); box-shadow: inset 0 0 0 1px var(--line);
}
.tv-scale::before {
  content: ""; position: absolute; z-index: -1; top: 3px; bottom: 3px; left: 3px; width: calc((100% - 6px) / var(--steps));
  border-radius: calc(var(--r-md) - 3px); background: var(--bg); box-shadow: 0 0 0 1px var(--line), 0 1px 3px rgb(20 18 31 / .1);
  transform: translateX(calc(var(--at) * 100%)); transition: transform 340ms var(--m-ease-io);
}
.tv-scale__step { display: grid; justify-items: center; gap: 1px; padding: 7px 4px; color: var(--muted); text-align: center; transition: color var(--m-out) var(--m-ease); }
.tv-scale__name { font: 500 13px/1.3 var(--font-text); }
.tv-scale__range { font-size: 12px; line-height: 1.3; font-variant-numeric: tabular-nums; }
.tv-scale__step.is-at { color: var(--ink); }
.tv-scale__step.is-at:last-child { color: var(--action); }

.tv-plan-info { margin-top: var(--s-4); padding: var(--s-4) var(--s-5); border-radius: var(--r-md); background: var(--surface); }
.tv-plan-info__head { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--s-3); }
.tv-plan-info__head > .ic { width: 20px; height: 20px; color: var(--action); }
.tv-plan-info__name { font-weight: 500; }
.tv-plan-info__for { color: var(--muted); font-size: var(--t-small); font-variant-numeric: tabular-nums; }
.tv-plan-info__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-5); margin-top: var(--s-3); color: color-mix(in oklab, var(--ink) 84%, var(--bg)); font-size: var(--t-small); line-height: 1.45; }
.tv-plan-info__list li, .tv-core li { grid-template-columns: 18px 1fr; gap: var(--s-2); }
.tv-plan-info__list li::before, .tv-core li::before { width: 18px; height: 18px; margin-top: 1px; -webkit-mask-size: 18px; mask-size: 18px; }
.tv-plan-info__text { color: color-mix(in oklab, var(--ink) 84%, var(--bg)); font-size: var(--t-small); line-height: 1.5; }

/* ---------------------------------------------------------------- an option row: a pressed button */
.tv-opts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
.tv-opt {
  display: grid; grid-template-columns: 22px minmax(0, 1fr) auto 22px; align-items: center; gap: var(--s-3);
  min-height: 68px; padding: var(--s-3) var(--s-4); border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--bg); color: var(--ink); font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--m-out) var(--m-ease), border-color var(--m-out) var(--m-ease), transform var(--m-press) var(--m-ease);
}
.tv-opt__icon { display: grid; }
.tv-opt__icon > .ic { width: 22px; height: 22px; color: var(--muted); transition: color var(--m-out) var(--m-ease); }
.tv-opt__text { display: grid; gap: 2px; min-width: 0; }
.tv-opt__name { font-size: 15px; font-weight: 500; line-height: 1.3; }
.tv-opt__line { color: var(--muted); font-size: 13px; line-height: 1.35; }
.tv-opt__price { display: grid; justify-items: end; gap: 3px; font-size: var(--t-small); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; }
.tv-opt__tag {
  display: inline-flex; align-items: center; height: 20px; padding: 0 var(--s-2); border-radius: 999px;
  background: color-mix(in oklab, var(--action) 12%, var(--bg)); color: var(--action); font: 500 12px/1 var(--font-text);
}
.tv-opt.is-included .tv-opt__amount { color: var(--muted); font-weight: 400; text-decoration: line-through; }
.tv-opt__box {
  display: grid; place-items: center; width: 22px; height: 22px; border: 1.5px solid color-mix(in oklab, var(--ink) 36%, transparent);
  border-radius: 7px; transition: background-color var(--m-in) var(--m-ease), border-color var(--m-in) var(--m-ease);
}
.tv-opt__box > svg { width: 16px; height: 16px; fill: none; stroke: var(--action-ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transform: scale(0); transition: transform 180ms var(--m-ease); }
.tv-opt:hover { border-color: color-mix(in oklab, var(--ink) 40%, transparent); transition-duration: var(--m-in); }
.tv-opt:active { transform: scale(.985); }
.tv-opt[aria-pressed="true"] { border-color: var(--action); background: color-mix(in oklab, var(--action) 7%, var(--bg)); }
.tv-opt[aria-pressed="true"] .tv-opt__icon > .ic { color: var(--action); }
.tv-opt[aria-pressed="true"] .tv-opt__box, .tv-opt.is-static .tv-opt__box { border-color: var(--action); background: var(--action); }
.tv-opt[aria-pressed="true"] .tv-opt__box > svg, .tv-opt.is-static .tv-opt__box > svg { transform: none; }
/* always in: no button, the tinted ground */
.tv-opt.is-static { border-color: transparent; background: var(--surface); cursor: default; }
.tv-opt.is-static:active { transform: none; }

/* ---------------------------------------------------------------- developer hours, integrations, the core */
.tv-hours, .tv-count { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-4) var(--s-6); }
.tv-rate { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-3); font-variant-numeric: tabular-nums; }
.tv-rate__now { font-size: 17px; font-weight: 500; }
.tv-rate__was { color: var(--muted); font-size: var(--t-small); }
.tv-rate__off {
  display: inline-flex; align-items: center; height: 22px; padding: 0 var(--s-2); border-radius: 999px;
  background: color-mix(in oklab, var(--action) 12%, var(--bg)); color: var(--action); font: 500 var(--t-label)/1 var(--font-text);
}
.tv-tools { display: flex; flex: 1 1 300px; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4); }
.tv-tools__label { color: var(--muted); font-size: var(--t-small); }
.tv-tools__list { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); }
.tv-tools__item { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-small); white-space: nowrap; }
.tv-core { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-5); padding: var(--s-4) var(--s-5); border-radius: var(--r-md); background: var(--surface); font-size: 15px; line-height: 1.45; }

/* ---------------------------------------------------------------- the summary card
   The brand's dark ground with a violet light from the top corner; the total in display type. */
.tv-sum {
  --c-text: color-mix(in oklab, var(--ink) 86%, var(--bg));
  padding: var(--s-6); border-radius: var(--r-lg);
  background: radial-gradient(130% 55% at 100% 0%, color-mix(in oklab, var(--p-action) 34%, transparent), transparent 64%), var(--p-inv-bg);
}
.tv-sum__label { color: var(--muted); font: 500 var(--t-small)/1.4 var(--font-text); letter-spacing: .01em; }
.tv-sum__total {
  margin-top: var(--s-1); color: var(--ink);
  font: var(--display-weight) clamp(42px, 1.4vw + 28px, 54px)/1.08 var(--font-display); letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
}
.tv-sum__note { margin-top: var(--s-1); color: var(--muted); font-size: var(--t-small); line-height: 1.45; }
.tv-lines { margin-top: var(--s-4); border-bottom: 1px solid var(--line); }
.tv-line { display: grid; grid-template-rows: 1fr; }
.tv-line__in { min-height: 0; overflow: clip; }
.tv-line__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); padding: 8px 0; border-top: 1px solid var(--line); font-size: var(--t-small); line-height: 1.4; }
.tv-line__label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s-2); min-width: 0; color: var(--c-text); }
.tv-line__meta { color: var(--muted); font-size: var(--t-label); font-variant-numeric: tabular-nums; }
.tv-line__value { flex: none; color: var(--ink); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; }
.tv-line__value.is-text { color: color-mix(in oklab, var(--p-action) 40%, #ffffff); }
.tv-sum__apart { margin-top: var(--s-5); }
.tv-sum__apart > .tv-lines { margin-top: var(--s-2); }
.tv-sum__sub { color: var(--muted); font: 500 var(--t-label)/1.4 var(--font-text); letter-spacing: .01em; }
.tv-sum__subtotal { display: flex; justify-content: space-between; gap: var(--s-3); padding-top: 10px; color: var(--ink); font-size: var(--t-small); font-weight: 500; font-variant-numeric: tabular-nums; }
.tv-sum__hint { margin-top: var(--s-4); padding: 10px var(--s-3); border-radius: var(--r-sm); background: rgb(255 255 255 / .07); color: var(--c-text); font-size: var(--t-label); line-height: 1.45; }
.tv-sum__action { width: 100%; margin-top: var(--s-5); }
.tv-sum__fine { margin-top: var(--s-3); color: var(--muted); font-size: var(--t-label); line-height: 1.45; }
.tv-sum__over { color: var(--ink); font-size: clamp(26px, .8vw + 18px, 32px); line-height: 1.15; }

/* ---------------------------------------------------------------- the bar pinned to the bottom (under 1024px) */
.tv-bar { display: none; }

/* ---------------------------------------------------------------- motion: brief, and at rest
   A swapped block (the mode's controls, the summary, a plan, a note) rises in; a breakdown line opens
   or closes its row; the plan scale and the mode pill slide (above). Reduced motion: all instant. */
@media (prefers-reduced-motion: no-preference) {
  html:not([data-motion="off"]) .tv-cfg .is-swapped { animation: tv-swap-in 300ms var(--m-ease) both; }
  html:not([data-motion="off"]) .tv-line.is-in { animation: tv-line-in 300ms var(--m-ease) both; }
  html:not([data-motion="off"]) .tv-line.is-out { animation: tv-line-out 240ms var(--m-ease) both; }
  html:not([data-motion="off"]) .tv-opt__tag { animation: tv-tag-in 220ms var(--m-ease) both; }
}
@keyframes tv-swap-in { from { opacity: 0; transform: translateY(6px); } }
@keyframes tv-line-in { from { grid-template-rows: 0fr; opacity: 0; } }
@keyframes tv-line-out { to { grid-template-rows: 0fr; opacity: 0; } }
@keyframes tv-tag-in { from { opacity: 0; transform: scale(.85); } }
.tv-line.is-out { pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .tv-line.is-out { display: none; }
  .tv-mode::before, .tv-scale::before { transition: none; }
  .tv-opt:active, .tv-step__btn:active { transform: none; }
}
html[data-motion="off"] .tv-line.is-out { display: none; }
html[data-motion="off"] :is(.tv-mode, .tv-scale)::before { transition: none; }

/* ---------------------------------------------------------------- at each width */
@media (min-width: 1024px) and (max-width: 1279px) {
  .tv-cfg { grid-template-columns: minmax(0, 1fr) 340px; column-gap: var(--s-7); }
  .tv-cfg__side { top: calc(var(--nav) + var(--s-4)); max-height: calc(100svh - var(--nav) - 2 * var(--s-4)); }
  .tv-sum { padding: var(--s-5); }
  .tv-opts { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1023px) {
  .tv-cfg { grid-template-columns: minmax(0, 1fr); row-gap: var(--s-7); }
  .tv-cfg__side { position: static; max-height: none; overflow: visible; scroll-margin-top: calc(var(--nav) + var(--s-4)); }
  .tv-mode { max-width: none; }

  .tv-bar {
    position: fixed; z-index: 40; left: var(--s-3); right: var(--s-3); bottom: calc(var(--s-3) + env(safe-area-inset-bottom));
    display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); min-height: 64px; padding: 10px 10px 10px var(--s-5);
    border-radius: var(--r-lg); background: var(--p-inv-bg); color: var(--ink);
    box-shadow: 0 18px 40px -16px rgb(20 18 31 / .55);
    transform: translateY(calc(100% + var(--s-5))); visibility: hidden;
    transition: transform 320ms var(--m-ease), visibility 0s linear 320ms;
  }
  .tv-bar[data-shown="true"] { transform: none; visibility: visible; transition: transform 320ms var(--m-ease), visibility 0s; }
  .tv-bar__text { display: grid; gap: 1px; min-width: 0; }
  .tv-bar__label { color: var(--muted); font-size: var(--t-label); line-height: 1.3; }
  .tv-bar__label--over { color: var(--ink); font-size: var(--t-small); font-weight: 500; }
  .tv-bar__total { color: var(--ink); font: var(--display-weight) 24px/1.15 var(--font-display); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
  .tv-bar .btn { flex: none; height: 44px; }
}
@media (max-width: 1023px) and (prefers-reduced-motion: reduce) {
  .tv-bar, .tv-bar[data-shown="true"] { transition: none; }
}
@media (max-width: 639px) {
  .tv-mode__opt { padding: var(--s-3); }
  .tv-mode__title { font-size: 16px; }
  .tv-opts, .tv-plan-info__list, .tv-core { grid-template-columns: minmax(0, 1fr); }
  .tv-opt { padding: var(--s-3); }
  .tv-scale { flex-basis: 100%; }
  .tv-plan-info, .tv-core { padding: var(--s-4); }
  .tv-sum { padding: var(--s-5); }
}
