/* ============================================================================
   vecka.ai, the homepage's own shapes.

   Everything structural rides /shared/auth.css (the tokens, the Inter face,
   the lockup). What lives here is what no other page has: the sticky nav, a
   hero whose artefact is the real product window, three card miniatures, a
   project page, one quiet row, the close and tab.bot's footer, and the
   product's own row registers restated locally.

   ROUND 2 OF THE TAB PASS (2026-09-23). David kept the direction of round
   one ("white and black, but white majority. Subtle shadows", Tab's glow)
   and asked for three things on this page.
     - LESS OF IT. "There's way too much to scroll ... cut things out that
       don't matter, and just make it as concise as possible." Ten screens
       under the hero became about three.
     - ONE SCROLL ANIMATION. "Remove all scroll animations other than the
       one that I asked you to make. No fade in animations or anything like
       that." The hero window rises into place and fills as the page
       scrolls (THE REVEAL, below), and that is the only thing on the page
       that moves with the scroll or on its own. Every other rule in this
       sheet draws a final state. The pinned stage, the reveals, the card
       loops, the drifting marks and the nav's fading hairline are gone,
       with their keyframes.
     - THE TYPE OF ROUND ONE, and the app's own type inside every product
       picture (THE TYPE, below).

   THE SURFACE LADDER. The <head> writes data-theme="light" before first
   paint and this sheet never asks the OS, so a visitor on a dark system
   gets the same page, as tab.bot does.
       --dd-canvas  #fdfdfc   the page, Tab's own white
       --dd-panel   #ffffff   a card, a picture's pane
       --dd-ground  #f7f7f5   the app's ground and rail, inside every window

   EVERY COMPOSITION HAS A CEILING. 1200px, centred, with --dd-pad-x
   gutters: the nav, the hero window, the cards, the project page, the row
   and the footer. Every picture area has a fixed shape, so nothing
   stretches into a letterbox on a 2560 by 1440 display.

   CONTROLS (ref SPEC, "Signed-out and marketing"). One large size for every
   button on the page, 44px tall at radius 12 (--home-radius-ctl), the same
   as the sign-in pages and the gateway. Primary is ink with white words,
   secondary is white with a hairline, both flat (no shadow, David: the
   buttons carry none on this page). No pills.
   ============================================================================ */

/* THE SCHEME, stated twice on purpose. The <head> writes data-theme="light"
   before first paint, and this rule is the belt for a blocked script: this
   sheet is loaded by this page and no other, so declaring the scheme here
   cannot reach anything else, and a visitor with no JavaScript on a dark
   system still lands on white rather than on the OS's dark palette. */
:root { color-scheme: light; }

/* ------------------------------------------------- the missing primitives
   Present in system.css, absent from auth.css, same values. */
.home-body {
  --dd-w-regular: 450;
  --dd-w-medium: 500;
  --dd-w-semibold: 550;
  --dd-w-bold: 600;
  --dd-w-heavy: 650;
  --dd-lh-ui: 1.45;
  --dd-lh-body: 1.55;
  --dd-ls-tighter: -.02em;
  --dd-ls-caps: .05em;
  --dd-ls-caps-wide: .08em;
  --dd-ease-glide: cubic-bezier(.22, 1, .36, 1);
  --dd-pad-x: clamp(16px, 3vw, 24px);
  --dd-ground: light-dark(#f7f7f5, #0b0c0c);
  --dd-ground-wash-2: light-dark(#e7e7e3, #242526);
  --dd-flag: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 21V4.5h11l-2 3.5 2 3.5H6'/%3E%3C/svg%3E");

  /* The nav's height, in one place. */
  --nav-h: 72px;

  /* THE ONE CEILING. Every composition on the page is this wide and no
     wider, and every one of them is centred inside it. */
  --shelf: 1200px;

  /* TAB'S SURFACES, measured off tab.bot. The edge is ink at 9 percent
     rather than a grey, so it reads the same on the white page, a white
     card and the app's ground. The card shadow is Tab's low, wide,
     blue-slate haze (0 24px 80px at 10 percent of #2d375a) under a 1px
     contact shadow, so a card lifts without a drop line. */
  --home-edge: rgb(17 17 18 / .09);
  --home-shadow: 0 1px 2px rgb(40 45 70 / .04), 0 24px 80px rgb(45 55 90 / .10);

  /* The one literal radius the spec allows besides the tokens: the large
     control's 12px, shared with the sign-in pages and the gateway. */
  --home-radius-ctl: 12px;

  margin: 0;
  color: var(--dd-ink);
  background: var(--dd-canvas);
  -webkit-font-smoothing: antialiased;
}

/* ================================================================ THE TYPE
   ROUND ONE'S TYPE, KEPT (David, round 2). The headlines (the h1, every h2
   and a card's title) are Tab's serif at weight 400 with tight tracking;
   everything else on the marketing layer (the nav, the doors, the ledes
   and lines, a card's sentence, the security band, the footer) is Inter,
   which the page already self-hosts. Nothing is downloaded for the serif:
   it is a SYSTEM stack, Iowan Old Style on a Mac or an iPhone, Palatino
   Linotype on Windows, Georgia elsewhere.

   The stack and its tracking are declared HERE, not borrowed from
   shared/auth.css: the app's page titles are going back to Inter, the
   shared --dd-font-display token goes with them, and this page keeps the
   serif on its own.

   THE MINIATURES ARE THE APP, SO THEY ARE THE APP'S TYPE. Every product
   picture on the page (the hero window, the three card pictures, the
   project page) is set in Inter at the product's own sizes and weights by
   inheriting it from the body, with no serif anywhere inside them: the
   project page's title is the app's Inter title (1.625rem, bold, -.02em),
   as the real project page draws it.

   Tab's numbers: h1 76px at -2.66px (-.035em) and 1.16 leading, body Inter
   at 17px in a quiet grey. The h1 here tops out at 72px because the real
   product window has to stand under it in the same viewport. Every
   typographic decision goes through the --home-* properties below. */
:root {
  --home-font-display: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Palatino, Georgia, serif;
  --home-font-text: var(--dd-font-sans);
  --home-feat-display: "kern", "liga";
  --home-feat-text: "kern";
  --home-h1-size: clamp(2.625rem, 5vw, 4.5rem);
  --home-h1-w: 400;
  --home-h1-ls: -.035em;
  --home-h1-lh: 1.08;
  --home-h2-size: clamp(2.125rem, 3.7vw, 3.375rem);
  --home-h2-w: 400;
  --home-h2-ls: -.03em;
  --home-h2-lh: 1.1;
  --home-h3-size: clamp(1.375rem, 1.75vw, 1.625rem);
  --home-h3-w: 400;
  --home-h3-ls: -.02em;
  --home-h3-lh: 1.2;
  --home-lede-size: clamp(1.0625rem, 1.3vw, 1.1875rem);
  --home-lede-w: 400;
  --home-lede-ls: -.006em;
  --home-lede-lh: 1.6;
  --home-line-size: clamp(1rem, 1.15vw, 1.0625rem);
  --home-line-w: 400;
  --home-line-ls: -.004em;
  --home-text-w: 400;
  --home-btn-size: .9375rem;
  --home-btn-w: 600;
  --home-btn-ls: -.006em;
  --home-nav-size: .875rem;
  --home-nav-w: 500;
  --home-nav-ls: -.003em;
}

.home-title, .home-h2, .fc-name {
  font-family: var(--home-font-display);
  font-feature-settings: var(--home-feat-display);
  font-synthesis: none;
}
.home-body .btn, .home-lede, .home-line, .home-foot, .fc-say, .home-ground .sec-sec, .home-skip {
  font-family: var(--home-font-text);
  font-feature-settings: var(--home-feat-text);
  font-synthesis: none;
}

.home-main { position: relative; padding: 0; margin: 0; }
.home-main:focus { outline: none; }

/* Focus speaks with TWO rings, never an outline glow and never on a text
   field. The inner ring is the page, so the ink ring reads against the
   button rather than against itself on the primary door, whose fill IS
   ink. */
.home-body :is(a, button, [tabindex]):focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--dd-canvas), 0 0 0 4px var(--dd-ink);
}

.home-skip {
  position: fixed; left: 16px; top: -96px; z-index: 30;
  padding: 8px 12px; border-radius: var(--dd-radius-m);
  background: var(--dd-panel); color: var(--dd-ink); border: 1px solid var(--home-edge);
  box-shadow: var(--dd-shadow-pop);
  font-size: var(--dd-fs-sm-); text-decoration: none;
}
/* Parked well above the viewport, so its shadow never shows at the top
   of the page while it waits for focus. */
.home-skip:focus { top: 12px; }

/* ------------------------------------------------------------- the nav
   AT THE TOP OF THE PAGE, AND IT STAYS THERE (David, round 2: the bar
   "shouldn't follow" the scroll). An ordinary block, the body's first
   child after the skip link, that scrolls away with the page. It has no
   rule under it and no fill of its own, so it stands on the hero's ground
   and the two read as one surface. Its contents sit on the 1200 shelf: the
   logo at the left with the site's pages beside it ("Pricing"), and at the
   right only the account's doors, "Sign in" (a quiet text link) and "Join
   the waitlist" (primary, ink). */
.home-nav {
  position: relative; z-index: 20;
  height: var(--nav-h);
  display: flex; align-items: center; gap: 16px;
  padding: 0 max(var(--dd-pad-x), calc((100% - var(--shelf)) / 2));
}
.home-nav .auth-mark { flex: none; color: var(--dd-ink); }
/* The logo's hit area is 44px tall and a little wider, drawn as padding and
   taken back as margin, so the bar lays out exactly as it draws. */
.home-nav > .auth-mark { display: flex; align-items: center; padding: 12px 6px; margin: -12px -6px; }
/* A step larger than the sign-in pages' 20px mark, near Tab's wordmark in
   its bar. */
.home-nav .auth-mark .brand-logo { height: 22px; filter: none; }
.home-nav-actions { margin-left: auto; display: flex; align-items: center; gap: 20px; }
/* THE SITE'S PAGES (2026-09-28), beside the logo and apart from the
   account's doors: the nav's own type role (a step under the buttons'),
   each a pill of 34px drawn only on hover and on the page it names, with
   a 44px hit area drawn round it. The pill's inset lines its words up
   with nothing: they stand a clear gap from the logo. */
.home-nav-site { display: flex; align-items: center; gap: 4px; margin-left: 18px; }
.home-nav-page {
  --pill: rgb(17 17 18 / .055);
  --pill-on: rgb(17 17 18 / .07);
  position: relative;
  display: inline-flex; align-items: center; height: 34px; padding: 0 12px; border-radius: 17px;
  font-family: var(--home-font-text); font-feature-settings: var(--home-feat-text);
  font-size: var(--home-nav-size); font-weight: var(--home-nav-w); letter-spacing: var(--home-nav-ls);
  line-height: 1; white-space: nowrap; text-decoration: none;
  color: var(--dd-ink-light);
  transition: color var(--dd-dur) var(--dd-ease), background-color var(--dd-dur) var(--dd-ease);
}
.home-nav-page::after { content: ""; position: absolute; inset: -5px 0; }
@media (hover: hover) {
  .home-nav-page:hover { color: var(--dd-ink); background-color: var(--pill); }
}
/* the page it names: in ink, on its pill */
.home-nav-page[aria-current="page"] { color: var(--dd-ink); background-color: var(--pill-on); }
/* "Sign in" is a quiet TEXT LINK (2026-09-24): the button's words, in
   ink-light at a medium weight, with no box, no border and no fill, ink on
   hover, and a 44px tall hit area drawn as its own height so it stays a
   thumb's target and shares the button's midline. "Join the waitlist"
   beside it is the bar's one filled control, the page's one button. */
.home-nav-link {
  display: inline-flex; align-items: center; height: 44px; padding: 0 2px;
  font-family: var(--home-font-text); font-feature-settings: var(--home-feat-text);
  font-size: var(--home-btn-size); font-weight: var(--dd-w-medium); letter-spacing: var(--home-btn-ls);
  line-height: 1; white-space: nowrap; text-decoration: none;
  color: var(--dd-ink-light);
  transition: color var(--dd-dur) var(--dd-ease);
}
@media (hover: hover) {
  .home-nav-link:hover { color: var(--dd-ink); }
}

/* THE NAV ON THE SKY (the dusk hero, 2026-09-28). On the homepage the bar
   stands on the hero's sky, so it is drawn in light. The logo and the
   links are white (the links at three quarters), and "Join the waitlist"
   is the page's one filled control in white with the sky's own navy for
   its words, as the reference's solid white door is. Its focus ring is
   the same two rings, navy then white. It is the bar's own four colours,
   set here and read by the rules below, so a phone's bar (THE NATIVE PASS)
   can hand them back to ink once the page under it is white. /pricing has
   no sky and keeps the ink bar. */
.home-dusk .home-nav {
  --nav-ink: #fff;
  --nav-quiet: rgb(255 255 255 / .74);
  --nav-fill: #fff;
  --nav-fill-hover: rgb(255 255 255 / .86);
  --nav-on-fill: #0c1636;
  --nav-ring: #0c1636;
}
.home-dusk .home-nav .auth-mark { color: var(--nav-ink); transition: color 240ms var(--dd-ease); }
.home-dusk .home-nav :is(.home-nav-link, .home-nav-page) { color: var(--nav-quiet); }
.home-dusk .home-nav .home-nav-page { --pill: rgb(255 255 255 / .12); --pill-on: rgb(255 255 255 / .16); }
.home-body.home-dusk .home-nav .btn-primary { background: var(--nav-fill); color: var(--nav-on-fill); }
.home-body.home-dusk .home-nav :is(a, button):focus-visible { box-shadow: 0 0 0 2px var(--nav-ring), 0 0 0 4px var(--nav-ink); }
@media (hover: hover) {
  .home-dusk .home-nav :is(.home-nav-link, .home-nav-page):hover { color: var(--nav-ink); }
  .home-body.home-dusk .home-nav .btn-primary:hover { background: var(--nav-fill-hover); }
}

/* ---------------------------------------------------------- the buttons
   Written in full here rather than borrowed from auth.css's .btn, so the
   sign-in pages' own button can change without moving this page's doors.
   ONE BUTTON (ref SPEC): 44 tall at radius 12, 15px words at 600 and 20px
   of padding either side, everywhere on the page, the nav's included.
   Secondary is the panel with a hairline, primary is ink with white words
   (--dd-accent is ink on this page), and both are FLAT: no shadow at rest,
   on hover or pressed. Hover is one step, a grey wash on the secondary, the
   ink mixed 88 percent with the panel on the primary. */
.home-body .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 20px;
  border: 1px solid var(--dd-border); border-radius: var(--home-radius-ctl);
  background: var(--dd-panel); color: var(--dd-ink);
  font-size: var(--home-btn-size); font-weight: var(--home-btn-w); letter-spacing: var(--home-btn-ls);
  line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background var(--dd-dur) var(--dd-ease), border-color var(--dd-dur) var(--dd-ease), transform var(--dd-dur-pop) var(--dd-ease);
}
.home-body .btn:active { transform: scale(.97); }
/* A press gives under the hand only where the control can answer: a
   disabled button (the form's, while its request is out) stays still,
   here and against the sign-in pages' own press (shared/auth.css). */
.home-body .btn:disabled:active { transform: none; }
.home-body .btn-primary { border-color: transparent; background: var(--dd-accent); color: var(--dd-on-accent); }
/* Hover only where there is a pointer that hovers: on a touch screen a
   tapped button would otherwise keep its hover wash after the finger has
   gone. The press (the scale above) is the touch screen's feedback. */
@media (hover: hover) {
  .home-body .btn:hover { background: var(--dd-gray-50); }
  .home-body .btn-primary:hover { background: color-mix(in srgb, var(--dd-accent) 88%, var(--dd-panel)); }
}

/* ============================================================== THE HERO
   The copy, then the window, in the page's flow. Nothing is pinned or
   sticky and the section is as tall as its contents.

   THE COPY IS CENTRED between the nav and the window (David: the words
   were "not centered between the navigation bar and the UI itself"). The
   block the eye reads, from the top of the headline's capitals to the
   subline's baseline (the hero has no doors since 2026-09-24: the nav's
   and the form's carry the action), has one gap above it and the same
   gap below it, --hero-g,
   measured to the window's top edge as the FIRST frame draws it:
     - above, the copy's padding from the nav's box, with the headline's
       box trimmed to its capitals (text-box, below) so the padding ends
       where the ink starts rather than at the top of the line's leading
     - below, the copy's padding, to the window's top edge as drawn: while
       the reveal is on (html.hw-on) the slot sits --hw-par lower and the
       window is drawn that much higher on the first frame (THE REVEAL),
       so its top edge lands exactly one gap under the subline either way.
       With no reveal (reduced motion, no script) the window simply stands
       one gap down.
   The gap follows the viewport's height (about a tenth of it), so the
   first frame always shows the headline, the subline and the window's
   top edge, at 1024 by 768, at 2560 by 1440 and on a phone.

   It clips SIDEWAYS only (clip, not hidden, so nothing inside it becomes a
   scroll container), since the sky and the paper are the whole page's
   width. It is its own stacking layer above the ground. */
.home-hero {
  --hero-pb: clamp(24px, 4vh, 48px);
  position: relative; z-index: 2;
  /* Its foot is a hard stop: nothing of the sky or the paper paints over
     the section after it (the top stays open, for the sky behind the nav).
     The stop is a hair under the foot, where the sky is already the page's
     white, since a clip edge that falls between device pixels lets a
     row of the sky under the white show through. */
  clip-path: inset(-100vh 0 -2px 0);
  --hero-g: clamp(40px, 10.5vh, 150px);
  --hero-g: clamp(40px, 10.5svh, 150px);
  padding: 0 var(--dd-pad-x) var(--hero-pb);
  overflow-x: clip;
  text-align: center;
  /* THE FIRST SCREEN IS ALL SKY (David, 2026-09-28: "hero when user opens
     page shouldn't even be able to see the fading or dissolving"). The
     hero is at least the first screen and the fade under it, measured
     from the screen: the fade starts at the first screen's foot and ends
     --hero-fade below it (THE WHITE, below). */
  --hero-top: calc(var(--nav-h) + env(safe-area-inset-top, 0px));
  --hero-fade: clamp(420px, 56svh, 600px);
  box-sizing: border-box;
  min-height: calc(100svh - var(--hero-top) + var(--hero-fade));
}
/* Over the sky, the window and the paper (THE SKY): the words are the one
   thing no scrap passes in front of. */
.home-herocopy { position: relative; z-index: 3; padding: var(--hero-g) 0; }
/* THE TRIM. The headline's box starts at its capitals' top (text-box
   trim, where the browser has it), so the gap above is the gap to the ink.
   Iowan's ascenders stand a hair over its capitals, and the margin gives
   that hair back, so the tallest glyph ('h', 'k') is where the gap ends. A
   browser without text-box gets the same top from a negative margin the
   size of the half leading and the face's ascent over its capitals. */
.home-title {
  max-width: 900px; margin: 0 auto;
  font-size: var(--home-h1-size);
  font-weight: var(--home-h1-w); line-height: var(--home-h1-lh); letter-spacing: var(--home-h1-ls);
  text-wrap: balance;
  color: var(--dd-ink);
}
@supports (text-box: trim-start cap alphabetic) {
  .home-title { text-box: trim-start cap alphabetic; margin-top: .052em; }
}
@supports not (text-box: trim-start cap alphabetic) {
  .home-title { margin-top: -.2em; }
}
/* The reference's roman then italic, in the same serif. */
.home-title em { font-style: italic; }
/* ON THE SKY the words are white, the subline at four fifths, each with a
   wide soft shade of the sky's own navy under it, so they hold their
   contrast wherever a scrap or the sunset's warmth passes behind them. */
.home-dusk .home-title { color: #fff; text-shadow: 0 1px 28px rgb(9 16 46 / .34); }
.home-dusk .home-title em { color: #fff4e6; }
.home-dusk .home-lede { color: rgb(255 255 255 / .82); text-shadow: 0 1px 16px rgb(9 16 46 / .42); }
.home-lede {
  max-width: 620px; margin: clamp(12px, 1.6vh, 18px) auto 0;
  font-size: var(--home-lede-size); font-weight: var(--home-lede-w);
  line-height: var(--home-lede-lh); letter-spacing: var(--home-lede-ls);
  color: var(--dd-ink-quiet);
  text-wrap: pretty;
}
/* The block ends at the subline's baseline (text-box trims the line's
   half leading and descent), so the gap below is measured from the ink,
   as the gap above is. A browser without text-box gets the same end from
   a negative margin. */
@supports (text-box: trim-end text alphabetic) {
  .home-lede { text-box: trim-end text alphabetic; }
}
@supports not (text-box: trim-end text alphabetic) {
  .home-lede { margin-bottom: -.5em; }
}

/* THE WINDOW'S PLACE. .hw is the static slot (it never moves, and it is
   the container the window's width and the sky's depth are sized from),
   holding the sky and the paper's canvas behind .hw-rise, the ONE element
   the rise moves. */
.hw {
  position: relative;
  display: flex; justify-content: center;
  container-type: inline-size;
}
@media (prefers-reduced-motion: no-preference) {
  html.hw-on .hw { margin-top: var(--hw-par); }
}
.hw-rise { position: relative; z-index: 1; width: min(var(--shelf), 100%); transform-origin: 50% 0; }
/* THE WINDOW'S SHAPE is the 1200/660 shape at every width it is drawn
   (720px and up; under that the hero is the phone, THE PHONE below).
   (100cqi is the slot's width, and the window is min(1200px, 100%) of it.) */
.home-heroshot {
  position: relative;
  height: calc(min(var(--shelf), 100cqi) * 0.55);
  container-type: inline-size;
}
/* The window stands on the glow the way Tab's invite card does: its long
   blue-slate haze, with the edge drawn as a 1px alpha ring inside the
   shadow rather than a border (SPEC3), at radius xl. */
.home-heroshot .vx-frame {
  height: 100%;
  border-radius: var(--dd-radius-xl);
  box-shadow:
    0 0 0 1px rgb(17 17 18 / .07),
    0 1px 2px rgb(40 45 70 / .06),
    0 12px 32px -14px rgb(60 78 135 / .22),
    0 -10px 70px -20px rgb(60 78 135 / .16);
}

/* Tab's dome (shared/auth.css --dd-dome, tab.bot's own values), a blurred
   ellipse, 1.5 wide to 1 tall, whose white heart and periwinkle rim fade
   to nothing at its edge. It rises behind the close and the footer (THE
   GLOW AT THE FOOT); the hero has the sky instead. */
.home-dome {
  position: absolute; z-index: 0; pointer-events: none;
  aspect-ratio: 1.5 / 1;
  border-radius: 50%;
  background: var(--dd-dome);
  filter: blur(5px);
}

/* =============================================================== THE SKY
   DUSK ABOVE THE CLOUDS, BEHIND THE HERO AS IT IS (David, 2026-09-28,
   sending a hero at dusk above a sea of lit cloud with paper spiralling to
   its centre; then "the text and ui stay the same it's just the background
   you're changing ... ui should overlay the sun and the paper and stuff
   should fly into the ui"; then, on review, a sky filling the screen and
   the sun wholly behind the UI). The hero's words and window stand exactly where they always
   have (THE HERO, THE REVEAL); only what is behind them is new, and it is
   the hero's alone: while the hero fills the screen the screen is sky and
   cloud edge to edge, and it melts into the page's white only over the
   hero's last stretch, whose foot clips anything that would reach further
   (.home-hero, below), so nothing of it paints over a later section.

   ONE STILL, baked (tools/gen-hero-sky.mjs, a volumetric render made once
   in Chromium): the sky from deep blue through violet to the gold horizon
   and a sea of cumulus under it, gold on the crests that face the low sun
   and blue grey in the gaps. The sun itself is not drawn: it is behind
   the app, and only its light shows, on the clouds. hero-wide.webp (2400
   by 3000) for screens wider than tall, hero-tall.webp (900 by 2880) for
   phones, both preloaded.

   THE HORIZON sits --hz-drop under the window's top edge as the first
   frame draws it (the foot of the copy's block, THE HERO), so the window
   stands in front of where the sun is, and the clouds lie behind and
   around its lower part. .hs is laid out from that line. --sky-at is where the
   line is in the slot (the slot sits --hw-par under it while the rise is
   on), --hs-up the sky above it (more than a viewport, so the sky runs up
   past the page's top behind the nav). The still is as wide as the page
   and placed so its own horizon (--img-f of its height) falls on the
   line; above its top the sky's own navy carries on. The sky scrolls with
   the page; the window, rising slower, sinks into the clouds.

   THE PAPER is the canvas (.hs-paper), in front of the window and behind
   the words, drawn by behaviours/paper.ts after the page has loaded. It is
   placed and sized by the script, and not drawn at all without one. */
.hw { --sky-at: 0px; }
@media (prefers-reduced-motion: no-preference) {
  html.hw-on .hw { --sky-at: calc(-1 * var(--hw-par)); }
}
.hs {
  --img-r: 1.25;
  --img-f: .2;
  --hz-drop: 28px;
  --hs-up: calc(100vh + 200px);
  --hs-up: calc(100lvh + 200px);
  --img-h: calc(100vw * var(--img-r));
  position: absolute; z-index: 0; pointer-events: none;
  left: 50%; width: 100vw; margin-left: -50vw;
  top: calc(var(--sky-at) - var(--hs-up));
  bottom: calc(-1 * var(--hero-pb));
  background:
    url("/home/sky/hero-wide.webp") no-repeat 50% calc(var(--hs-up) + var(--hz-drop) - var(--img-h) * var(--img-f)) / 100% auto,
    linear-gradient(to bottom, #4a4e8c, #4a4e8c calc(var(--hs-up) - 400px), #654d58);
}
@media (max-aspect-ratio: 4 / 5) {
  .hs {
    --img-r: 3.2;
    --img-f: .26;
    background:
      url("/home/sky/hero-tall.webp") no-repeat 50% calc(var(--hs-up) + var(--hz-drop) - var(--img-h) * var(--img-f)) / 100% auto,
      linear-gradient(to bottom, #2d3e87, #2d3e87 calc(var(--hs-up) - 400px), #644d5a);
  }
}
/* THE WHITE COMES IN ONLY BELOW THE FIRST SCREEN (David, 2026-09-28:
   "smoother gradient to the white", then "hero when user opens page
   shouldn't even be able to see the fading or dissolving"). On load the
   whole screen is sky and cloud at every size; the fade starts at the
   first screen's foot, wherever the window is, and runs --hero-fade (420
   to 600px, a phone's shorter) on a smoothstep curve, mixed in oklab so
   the clouds dissolve into the page's white rather than greying on the
   way. It is the hero's own layer over the sky and under the window, and
   under it, down to the hero's foot, the page's white. The sky itself runs
   on under it to the hero's foot, and the hero's clip ends both. */
/* (the hero is a column whose slot takes any height the first screen
   adds, so the sky, laid out from the slot, reaches the hero's foot) */
.home-hero { display: flex; flex-direction: column; }
.home-hero > .hw { flex: 1 0 auto; }
.home-hero::after {
  content: ""; position: absolute; z-index: 0; left: 0; right: 0; bottom: -2px; pointer-events: none;
  top: calc(100svh - var(--hero-top));
  background: linear-gradient(in oklab to bottom,
    rgb(253 253 252 / 0) 0,
    rgb(253 253 252 / .028) calc(var(--hero-fade) * .1),
    rgb(253 253 252 / .104) calc(var(--hero-fade) * .2),
    rgb(253 253 252 / .216) calc(var(--hero-fade) * .3),
    rgb(253 253 252 / .352) calc(var(--hero-fade) * .4),
    rgb(253 253 252 / .5) calc(var(--hero-fade) * .5),
    rgb(253 253 252 / .648) calc(var(--hero-fade) * .6),
    rgb(253 253 252 / .784) calc(var(--hero-fade) * .7),
    rgb(253 253 252 / .896) calc(var(--hero-fade) * .8),
    rgb(253 253 252 / .972) calc(var(--hero-fade) * .9),
    #fdfdfc var(--hero-fade));
}
.hs-paper { display: none; }
/* The paper's canvas is the size of the screen and stays on it (fixed),
   inside the hero's layer: in front of the window, behind the words, and
   clipped by the hero's foot like everything else in it. */
html:is(.hw-on, .hw-calm) .hs-paper { display: block; position: fixed; z-index: 2; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; }
/* The stream is already turning when it starts, so the canvas fades in
   once, as the paper arrives, rather than popping in. */
html:is(.hw-on, .hw-calm) .hs-paper { opacity: 0; transition: opacity .9s var(--dd-ease); }
html:is(.hw-on, .hw-calm) .hs-paper[data-on] { opacity: 1; }

/* ============================================================ THE REVEAL
   THE ONE SCROLL ANIMATION ON THE PAGE, the window's rise over the first
   --hw-run of scroll, about one viewport of it (useHeroRise measures it).
   The window is drawn --hw-par (57 percent of the run) above its slot on
   the first frame, at 94 percent, and closes that as the page scrolls. It
   travels up the viewport at 15 percent of the page's pace at first,
   picking up to the page's own pace by the end of the run, when its top
   has come up near the top of the view (the easing, cubic-bezier(1/3, .5,
   2/3, 1), is exactly 1.5u - .5u^3, whose slope is 1.5 at the start and 0
   at the end). So the window stays in view through the whole rise, the
   page's own scroll is never held, and after the run it scrolls on with
   the page from its slot. It follows the scroll exactly, in CSS on the
   compositor where the browser has scroll-driven animations, and from
   --hw-u (useHeroRise, html.hw-js) where it has not.

   THE FILL is not the scroll's. As each carrier in the paper sinks into
   the row it brings (THE SKY, behaviours/paper.ts), that row, block or
   count fades up where it belongs, and the others it brings after it, a step apart (--a on each
   .vx-add is its start, .07 its length), on --p, the stream's clock, which
   useHeroStream writes onto each piece every frame for the first seven
   seconds or so. Transform and opacity only, so no frame of it touches
   layout.

   Only on a page the head script marked hw-on (motion welcome, script
   running). Under reduced motion or with no script every rule below is
   off: the slot has no parallax and the window stands full one gap under
   the subline. */
.home-body {
  --hw-run: min(max(100vh, 480px), 1600px);
  --hw-par: calc(var(--hw-run) * .5667);
}
/* Until the script measures them the two are this estimate, and the
   parallax is taken to the whole pixel as the script's is, so the slot's
   margin and the window's lift cancel on the same pixel before and after:
   with a fraction left over (453.36px at 1280 by 800) the window was drawn
   a part of a pixel off and every word in it redrawn as the script
   hydrated (the audit of 2026-09-26). */
@supports (width: round(1.5px, 1px)) {
  .home-body { --hw-par: round(calc(var(--hw-run) * .5667), 1px); }
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    html.hw-on:not(.hw-js) .hw-rise {
      animation: hw-rise linear both;
      animation-timeline: scroll(root block);
      animation-range: 0px var(--hw-run);
    }
  }
  html.hw-js .hw-rise {
    --hw-f: calc(1.5 * var(--hw-u, 0) - .5 * var(--hw-u, 0) * var(--hw-u, 0) * var(--hw-u, 0));
    transform: translateY(calc((var(--hw-f) - 1) * var(--hw-par))) scale(calc(.94 + .06 * var(--hw-f)));
  }
  html.hw-on #vx-hero .vx-add {
    --q: clamp(0, (var(--p, 0) - var(--a)) / .07, 1);
    opacity: var(--q);
    transform: translateY(calc((1 - var(--q)) * 6px));
  }
}
/* --hw-u is read by .hw-rise alone, so it does not inherit: writing it each
   frame restyles that one element, not the window inside it. The same goes
   for --hw-f, the eased rise worked out from it on the same element: an
   unregistered property there changed every frame and was inherited by
   every element in the window, so each frame of the fallback restyled all
   of them (the audit of 2026-09-26). */
@property --hw-u { syntax: "<number>"; inherits: false; initial-value: 0; }
@property --hw-f { syntax: "<number>"; inherits: false; initial-value: 0; }
@property --hw-pt { syntax: "<number>"; inherits: false; initial-value: 0; }
@keyframes hw-rise {
  from { transform: translateY(calc(-1 * var(--hw-par))) scale(.94); animation-timing-function: cubic-bezier(.333, .5, .667, 1); }
}

/* ============================================================= THE PHONE
   ROUND 4 (David, 2026-09-23): "If it's a mobile screen, all the different
   animations and stuff are especially created for a mobile screen too, but
   keep the desktop screen the same ... the hero part will show the mobile
   UI on mobile instead of the desktop UI or a cut of the desktop UI."

   So the hero has two pictures and draws exactly one. From 720px up it is
   the desktop window (THE SHELL), exactly as before, and nothing in this
   block reaches it: every rule for the phone either styles the phone's own
   classes, which are not displayed there, or sits inside the one
   max-width query below. Under 720px the window is not drawn at all, and
   the phone (hero/Phone.tsx) is, and the paper streams into it instead
   (hero/phoneFill.ts has its story).

   THE CARD is the app's phone screen, not a device, and since the native
   pass not a phone drawn inside the visitor's phone either: no bezel, no
   status line, no home indicator, just the app's head, its screen and its
   tab bar on a white card at the page's large radius (--dd-radius-xl) with
   the window's own ring and haze (THE WINDOW'S SHAPE). It takes the
   column, edge to edge with the gutters, and it is shaped like the app's
   screen between its head and its tab bar, 390 by 660, so through the
   story it stands whole in the view under the sticky header at 390 by
   844, at 430 by 932 and at 375 by 667.

   ONE UNIT. The screen is drawn in an iPhone's own points at 390 wide
   (the tab bar's 24pt glyphs and 10pt words, a row's 17pt title) and
   scaled to the card by --pu, one design pixel: 100cqi of the card over
   390, registered as a length so it is computed once on the screen and
   inherited as a plain px value. At 330px wide a row's title is 14.4px. */
@property --pu { syntax: "<length>"; inherits: true; initial-value: 1px; }
.ph { display: none; }
@media (max-width: 719.98px) {
  #vx-hero { display: none; }
  .hw-rise { width: 100%; }
  .home-heroshot { height: auto; }
  /* Inset from the gutters by 12px a side (2026-09-26, David: "not enough
     padding on the sides for the app so it feels less crammed"), so the
     card stands on the page with air either side, not edge to edge with
     the column. Everything inside is in --pu, so it scales with the card. */
  .ph { display: block; position: relative; container-type: inline-size; width: calc(100% - 24px); margin-inline: auto; }
}
.ph-scr {
  --pu: calc(100cqi / 390);
  --ph-fill: rgb(17 17 18 / .04);
  --ph-fill-2: rgb(17 17 18 / .065);
  --ph-line: rgb(17 17 18 / .08);
  --ph-peri: #6f86e0;
  --ph-hour: calc(48 * var(--pu));
  /* Its own stacking context, so nothing inside it (the tab bar, the
     button) reaches out of the card. */
  position: relative; overflow: hidden; isolation: isolate;
  aspect-ratio: 390 / 660;
  border-radius: var(--dd-radius-xl);
  background: var(--dd-panel);
  box-shadow:
    0 0 0 1px rgb(17 17 18 / .07),
    0 1px 2px rgb(40 45 70 / .06),
    0 12px 32px -14px rgb(60 78 135 / .22),
    0 -10px 70px -20px rgb(60 78 135 / .16);
  font-family: var(--dd-font-sans); color: var(--dd-ink); text-align: left;
  font-size: calc(17 * var(--pu)); line-height: 1.29; letter-spacing: -.012em;
}
.ph-scr svg { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.ph-scr p { margin: 0; }

/* AT AN iPHONE'S OWN PROPORTIONS (the native pass, round three, David:
   "some things look oversized"). Every size below is a point on a 390
   point iPhone, from Apple's HIG: a 44pt bar of plain glyphs, a large
   title, 17pt rows at least 44pt tall with a hairline inset past the
   check, 13 to 15pt secondary words, and a tab bar of 24pt glyphs over
   10pt words. Scaled to the card by --pu, so on a 390 screen the whole
   screen is the app at 92 percent, calm and precise rather than chunky.

   The bar: the workspace's small dark tile, the drawer and search as bare
   glyphs, no filled squares. */
.ph-head { height: calc(52 * var(--pu)); padding: calc(8 * var(--pu)) calc(20 * var(--pu)) 0; display: flex; align-items: center; gap: calc(14 * var(--pu)); }
.ph-tile, .ph-btn { display: grid; place-items: center; flex: none; width: calc(30 * var(--pu)); height: calc(30 * var(--pu)); }
.ph-tile { border-radius: calc(8 * var(--pu)); background: #1f2937; color: #fff; }
.ph-tile svg { width: calc(17 * var(--pu)); height: calc(17 * var(--pu)); stroke-width: 1.9; }
.ph-btn { color: var(--dd-ink); }
.ph-btn svg { width: calc(22 * var(--pu)); height: calc(22 * var(--pu)); stroke-width: 1.7; }
.ph-search { margin-left: auto; }

/* THE TWO SCREENS share one place between the bar and the tab bar. The
   day is the finished state; Tasks is where the reveal starts. */
.ph-view { position: absolute; left: 0; right: 0; top: calc(52 * var(--pu)); bottom: calc(56 * var(--pu)); padding: 0 calc(20 * var(--pu)); overflow: hidden; background: var(--dd-panel); }
.ph-tasks { visibility: hidden; opacity: 0; }
/* The large title, 32pt bold, and a quiet count beside it. */
.ph-title { padding-top: calc(2 * var(--pu)); font-size: calc(32 * var(--pu)); font-weight: var(--dd-w-bold); letter-spacing: -.022em; line-height: 1.2; }
.ph-title :is(b, span) { margin-left: calc(6 * var(--pu)); font-size: calc(17 * var(--pu)); font-weight: var(--dd-w-regular); letter-spacing: 0; color: var(--dd-ink-quiet); }
/* A section's head, 15pt semibold. */
.ph-label { margin: calc(16 * var(--pu)) 0 calc(2 * var(--pu)); font-size: calc(15 * var(--pu)); font-weight: var(--dd-w-semibold); color: var(--dd-ink); letter-spacing: -.008em; }
.ph-label b { margin-left: calc(6 * var(--pu)); font-weight: var(--dd-w-regular); color: var(--dd-ink-quiet); }
/* The suggestions: the periwinkle sparkle and head, one faint rounded wash
   under the pair, never a slab per row (SPEC3's declutter). */
.ph-sug { margin: calc(10 * var(--pu)) calc(-8 * var(--pu)) 0; padding: 0 calc(8 * var(--pu)) calc(2 * var(--pu)); border-radius: calc(12 * var(--pu)); background: rgb(111 134 224 / .055); }
.ph-suglabel { margin-top: calc(8 * var(--pu)); padding-top: calc(8 * var(--pu)); color: var(--ph-peri); }
/* A row: 44pt, 17pt words, a hairline over it from past the check. */
.ph-row { display: flex; align-items: center; gap: calc(12 * var(--pu)); min-height: calc(44 * var(--pu)); }
.ph-row + .ph-row { background: linear-gradient(var(--ph-line), var(--ph-line)) no-repeat calc(34 * var(--pu)) 0 / 100% 1px; }
.ph-row2 { min-height: calc(54 * var(--pu)); }
.ph-rowtitle { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ph-rowtitle small { display: block; margin-top: calc(1 * var(--pu)); font-size: calc(14 * var(--pu)); color: var(--dd-ink-quiet); letter-spacing: 0; }
.ph-meta { flex: none; font-size: calc(15 * var(--pu)); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }
/* The check is a round one, as iOS draws it. */
.ph-box { flex: none; width: calc(22 * var(--pu)); height: calc(22 * var(--pu)); border-radius: 50%; box-shadow: inset 0 0 0 calc(1.5 * var(--pu)) rgb(17 17 18 / .26); }
.ph-spark { display: inline-flex; flex: none; margin-left: calc(-4 * var(--pu)); color: var(--ph-peri); }
.ph-spark svg { width: calc(14 * var(--pu)); height: calc(14 * var(--pu)); stroke-width: 1.75; }

/* The day: the week strip (11pt letters over 17pt days, today in ink),
   then 9:00 to 17:00 on the app's faint hour lines (the one set of lines,
   because they carry the hours), and the blocks in their projects'
   colours. */
.ph-weekstrip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); margin: calc(10 * var(--pu)) calc(-4 * var(--pu)) 0; }
.ph-wd { display: flex; flex-direction: column; align-items: center; gap: calc(4 * var(--pu)); }
.ph-wd i { font-style: normal; font-size: calc(11 * var(--pu)); font-weight: var(--dd-w-semibold); color: var(--dd-ink-quiet); letter-spacing: .02em; }
.ph-wd b { display: grid; place-items: center; width: calc(32 * var(--pu)); height: calc(32 * var(--pu)); border-radius: 50%; font-size: calc(17 * var(--pu)); font-weight: var(--dd-w-semibold); font-variant-numeric: tabular-nums; }
.ph-wd.is-today i { color: var(--dd-ink); }
.ph-wd.is-today b { background: var(--dd-ink); color: #fff; }
.ph-day { display: grid; grid-template-columns: calc(30 * var(--pu)) minmax(0, 1fr); margin-top: calc(14 * var(--pu)); }
.ph-hours { display: flex; flex-direction: column; }
.ph-hours i {
  flex: none; height: var(--ph-hour); padding-right: calc(8 * var(--pu));
  font-style: normal; font-size: calc(11 * var(--pu)); line-height: 1; text-align: right;
  color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; transform: translateY(calc(-5 * var(--pu)));
}
.ph-lane {
  position: relative; height: calc(8 * var(--ph-hour));
  background-image: linear-gradient(to bottom, var(--ph-line) 0 1px, transparent 1px);
  background-size: 100% var(--ph-hour);
}
.ph-blk {
  position: absolute; left: calc(2 * var(--pu)); right: 0;
  top: calc(var(--s) * var(--ph-hour) + 1px); height: calc((var(--e) - var(--s)) * var(--ph-hour) - 2px);
  display: flex; flex-direction: column; overflow: hidden;
  padding: calc(4 * var(--pu)) calc(8 * var(--pu)) 0 calc(13 * var(--pu));
  border-radius: calc(6 * var(--pu));
  background: color-mix(in srgb, var(--id) 14%, #fff);
  color: color-mix(in srgb, var(--id) 85%, var(--dd-ink));
}
.ph-blk::before { content: ""; position: absolute; left: calc(5 * var(--pu)); top: calc(4 * var(--pu)); bottom: calc(4 * var(--pu)); width: calc(3 * var(--pu)); border-radius: 2px; background: var(--id); }
.ph-blktitle { font-size: calc(13 * var(--pu)); font-weight: var(--dd-w-semibold); letter-spacing: -.004em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ph-blktime { font-size: calc(12 * var(--pu)); color: color-mix(in srgb, var(--id) 61%, var(--dd-ink)); font-variant-numeric: tabular-nums; white-space: nowrap; letter-spacing: 0; }
/* A half-hour block has room for one line: its time goes beside its title. */
.ph-blk.is-short { flex-direction: row; align-items: center; gap: calc(6 * var(--pu)); padding-top: 0; }
.ph-now { position: absolute; left: calc(-4 * var(--pu)); right: 0; top: calc(1.75 * var(--ph-hour)); z-index: 2; border-top: 1.5px solid var(--dd-ink); }
.ph-now::before { content: ""; position: absolute; left: -3px; top: -4.5px; width: 7.5px; height: 7.5px; border-radius: 50%; background: var(--dd-ink); }

/* The new-item button, the app's one floating control on a phone, 50pt. */
.ph-fab {
  position: absolute; right: calc(20 * var(--pu)); bottom: calc(70 * var(--pu)); z-index: 2;
  display: grid; place-items: center; width: calc(50 * var(--pu)); height: calc(50 * var(--pu));
  border-radius: 50%; background: var(--dd-ink); color: #fff;
  box-shadow: 0 1px 2px rgb(17 17 18 / .12), 0 8px 20px -8px rgb(17 17 18 / .38);
}
.ph-fab svg { width: calc(20 * var(--pu)); height: calc(20 * var(--pu)); stroke-width: 2; }

/* THE TAB BAR, the app's (system.css, the phone block): six places, a
   24pt glyph over a 10pt word, quiet, the current one in ink, on the panel
   with the one hairline a phone's chrome carries. It closes the card, with
   no room kept for a home indicator. */
.ph-tabbar {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  height: calc(56 * var(--pu)); padding: calc(6 * var(--pu)) calc(4 * var(--pu)) calc(4 * var(--pu));
  display: flex; background: var(--dd-panel); border-top: 1px solid var(--ph-line);
}
.ph-tab {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: calc(3 * var(--pu));
  font-size: calc(10 * var(--pu)); font-weight: var(--dd-w-medium); letter-spacing: .01em; color: var(--dd-ink-quiet); white-space: nowrap;
}
.ph-tab[data-tab="calendar"] { color: var(--dd-ink); }
.ph-tabico { position: relative; display: grid; place-items: center; width: calc(26 * var(--pu)); height: calc(26 * var(--pu)); }
.ph-tabico svg { position: relative; width: calc(24 * var(--pu)); height: calc(24 * var(--pu)); stroke-width: 1.6; }
.ph-badge {
  position: absolute; top: calc(-3 * var(--pu)); left: calc(16 * var(--pu)); z-index: 1;
  display: grid; place-items: center; min-width: calc(16 * var(--pu)); height: calc(16 * var(--pu)); padding: 0 calc(4.5 * var(--pu));
  border-radius: 99px; background: var(--dd-ink); color: #fff; box-shadow: 0 0 0 calc(2 * var(--pu)) var(--dd-panel);
  font-size: calc(10 * var(--pu)); font-weight: var(--dd-w-bold); font-variant-numeric: tabular-nums; letter-spacing: 0;
}
/* The thumb's press on the Calendar tab, only ever seen mid-reveal. */
.ph-press { position: absolute; inset: calc(-6 * var(--pu)) calc(-14 * var(--pu)); border-radius: calc(10 * var(--pu)); background: var(--ph-fill-2); opacity: 0; }

/* THE PHONE'S FILL, on the stream's clock --p that useHeroStream writes
   on every piece that reads it (data-p), exactly like the window's fill.
     - a piece a carrier brings (.ph-add, --a its start) fades up from a
       step below and settles, swelling a hair past its size and back (a
       sine over its own progress), a block settles from a step above, a
       badge pops from 40 percent with the same small overshoot
     - the switch (--s0 to --s1, smoothstepped as --e) is a push, as iOS
       moves between screens: the day slides in from the right edge over
       Tasks on its own white, while Tasks drifts a third of the way left
       and dims under it, so at every step of the scroll one whole screen
       or the two edge to edge are on show, never a blank card or a muddle
       of words (the old cross-fade left the card empty at its middle);
       the ink moves from the Tasks tab to Calendar, and the press peaks as
       the switch starts
   Only on a page marked hw-on with motion welcome; otherwise the phone
   stands on the finished day. */
@media (prefers-reduced-motion: no-preference) {
  html.hw-on #vx-phone .ph-add {
    --q: clamp(0, (var(--p, 0) - var(--a)) / .07, 1);
    opacity: var(--q);
    transform: translateY(calc((1 - var(--q)) * 8 * var(--pu)));
    scale: calc(1 + .03 * sin(var(--q) * 180deg));
  }
  html.hw-on #vx-phone .ph-blk.ph-add { transform-origin: 50% 0; transform: translateY(calc((1 - var(--q)) * -6 * var(--pu))) scale(calc(.96 + .04 * var(--q))); }
  html.hw-on #vx-phone .ph-badge.ph-add { transform: scale(calc(.4 + .6 * var(--q))); scale: calc(1 + .22 * sin(var(--q) * 180deg)); }
  html.hw-on #vx-phone :is(.ph-view, .ph-tab)[data-p] {
    --w: clamp(0, (var(--p, 0) - var(--s0)) / (var(--s1) - var(--s0)), 1);
    --e: calc(var(--w) * var(--w) * (3 - 2 * var(--w)));
  }
  html.hw-on #vx-phone .ph-tasks {
    visibility: visible;
    opacity: calc((1 - .3 * var(--e)) * clamp(0, (1 - var(--e)) / .08, 1));
    transform: translateX(calc(var(--e) * -30%));
  }
  html.hw-on #vx-phone .ph-cal {
    opacity: clamp(0, var(--e) * 50, 1);
    transform: translateX(calc((1 - var(--e)) * 100%));
    box-shadow: calc(-10 * var(--pu)) 0 calc(24 * var(--pu)) calc(-12 * var(--pu)) rgb(17 17 18 / .16);
  }
  html.hw-on #vx-phone .ph-tab[data-tab="tasks"] { color: color-mix(in srgb, var(--dd-ink) calc((1 - var(--e)) * 100%), var(--dd-ink-quiet)); }
  html.hw-on #vx-phone .ph-tab[data-tab="calendar"] { color: color-mix(in srgb, var(--dd-ink) calc(var(--e) * 100%), var(--dd-ink-quiet)); }
  html.hw-on #vx-phone .ph-press {
    --k: max(0, min((var(--p, 0) - var(--s0) + .03) / .04, (var(--s0) + .08 - var(--p, 0)) / .07));
    opacity: var(--k);
    transform: scale(calc(.85 + .15 * var(--k)));
  }
  /* THE PHONE'S RISE (useHeroRise.ts THE TWO RISES): flat for the first
     fifth of the run, so the phone comes up at the page's own pace until
     it stands whole in the view, then a smoothstep to its slot, the
     slowest in the middle of the story, from 96 percent. */
  @media (max-width: 719.98px) {
    @supports (animation-timeline: scroll()) {
      html.hw-on:not(.hw-js) .hw-rise { animation-name: ph-rise; }
    }
    /* Registered and not inherited, as the window's --hw-f is (below):
       unregistered, the two changed every frame and every element in the
       phone inherited them, so each frame of the fallback restyled the
       whole phone (the animation audit's P1, 2026-09-26). */
    html.hw-js .hw-rise {
      --hw-pt: clamp(0, (var(--hw-u, 0) - .2) / .8, 1);
      --hw-f: calc(var(--hw-pt) * var(--hw-pt) * (3 - 2 * var(--hw-pt)));
      transform: translateY(calc((var(--hw-f) - 1) * var(--hw-par))) scale(calc(.96 + .04 * var(--hw-f)));
    }
  }
  @keyframes ph-rise {
    0% { transform: translateY(calc(-1 * var(--hw-par))) scale(.96); }
    20% { transform: translateY(calc(-1 * var(--hw-par))) scale(.96); animation-timing-function: cubic-bezier(.333, 0, .667, 1); }
  }
}

/* ============================================================ THE GROUND
   Everything below the hero, on the same white, so there is no edge and no
   seam where the two meet. It is the positioning box for the glow at its
   foot, and it does NOT clip: the glow clips itself (THE GLOW AT THE
   FOOT), so no section's edge can cut it. */
.home-ground { position: relative; background: var(--dd-canvas); }
.home-ground > :not(.home-glow) { position: relative; z-index: 1; }

/* THE RHYTHM, set once here and read by every section below the hero
   (round 4, David: "I want all the sections to have a bit more breathing
   room ... 'It does your busy work' and 'It knows your team' are too close
   to each other, and all the other sections as well").
     --home-sec-pad    each section's padding above and below, so two
                       sections stand twice this apart: 184px at 1440
                       (round 3 had 72), 127 at 1024, 96 on a phone. Tab's
                       own sections stand about 300 apart; this is the air
                       of theirs a page of pictures can carry.
     --home-line-gap   the heading to its one line.
     --home-head-gap   the head (heading and line) to what it introduces,
                       whatever that is (a grid of cards, the project
                       page, the field of marks, the badges, the close's
                       card), by the one rule under .home-line, so every
                       section's head has the same inner rhythm and no
                       section sets its own.
   They scale with the width rather than the height, so a short laptop
   window does not squeeze the page's air while a phone keeps enough. */
.home-ground {
  --home-sec-pad: clamp(48px, 6.4vw, 92px);
  --home-line-gap: clamp(14px, 1.25vw, 18px);
  --home-head-gap: clamp(32px, 3.6vw, 52px);
}
.home-sec {
  width: min(calc(var(--shelf) + 2 * var(--dd-pad-x)), 100%);
  margin: 0 auto;
  padding: var(--home-sec-pad) var(--dd-pad-x);
  text-align: center;
}
.home-h2 {
  margin: 0 auto; max-width: 16em;
  font-size: var(--home-h2-size);
  font-weight: var(--home-h2-w); line-height: var(--home-h2-lh); letter-spacing: var(--home-h2-ls);
  color: var(--dd-ink);
  text-wrap: balance;
}
.home-line {
  margin: var(--home-line-gap) auto 0; max-width: 56ch;
  font-size: var(--home-line-size); font-weight: var(--home-line-w);
  line-height: var(--dd-lh-body); letter-spacing: var(--home-line-ls);
  color: var(--dd-ink-quiet);
  text-wrap: pretty;
}
/* The head's one gap to its content. Three classes deep on purpose, so it
   outranks the single-class margin a section's content may carry for its
   other sides (.fg, .eg, .pj, .tl-band, .end-card centre themselves with
   the margin shorthand) without any of them repeating this value. */
.home-sec > :is(.home-h2, .home-line) + :not(.home-line) { margin-top: var(--home-head-gap); }

/* ========================================================== THE PRODUCT'S
   OWN ROWS, restated. Same numbers as system.css. */

/* The project mark: a rounded TILE with a white glyph, never a circle. */
.dd-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.3em; height: 1.3em; border-radius: 26%;
  color: #fff; flex: none;
}
.dd-mark > svg { width: 72%; height: 72%; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; fill: none; }

/* The project code chip: one neutral outline everywhere. */
.dd-ptag {
  display: inline-block; flex: none; max-width: 96px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border: 1px solid var(--dd-border); border-radius: var(--dd-radius-s);
  background: none; font-weight: var(--dd-w-medium); letter-spacing: .02em;
  color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums;
}
.dd-ptag-sm { height: 16px; line-height: 14px; padding: 0 5px; font-size: var(--dd-fs-3xs); }
.dd-ptag-lg { height: 20px; line-height: 18px; padding: 0 7px; font-size: var(--dd-fs-2xs); }

/* The checkbox face. 17px at radius 5 with a 1.5px edge on the panel,
   checked in ink. */
.check-face {
  position: relative; display: block; flex: none;
  width: 17px; height: 17px;
  border: 1.5px solid var(--dd-gray-300); border-radius: var(--dd-radius-s);
  background: var(--dd-panel);
}
.check-face::after {
  content: ""; position: absolute; inset: 0;
  background: var(--dd-on-accent);
  -webkit-mask: var(--dd-tick) center / 10px 10px no-repeat;
  mask: var(--dd-tick) center / 10px 10px no-repeat;
  clip-path: inset(0 100% 0 0);
}
.check-face.is-on { background: var(--dd-accent); border-color: var(--dd-accent); }
.check-face.is-on::after { clip-path: inset(0 0 0 0); }

/* The to-do row. 7 + 7 padding plus one 20px line is 34px, and the list gap
   is 2px, so the pitch is 36px. Rows are WASHES, never brackets. */
.t-row {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 10px; min-height: 34px; line-height: 20px;
  border-radius: var(--dd-radius-m);
  font-size: var(--dd-fs-sm); font-weight: var(--dd-w-regular);
}
.t-row .row-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-row.is-done .row-title {
  color: var(--dd-ink-quiet);
  text-decoration: line-through; text-decoration-color: var(--dd-gray-300); text-decoration-thickness: 1px;
}
.t-meta {
  display: flex; align-items: center; gap: 8px; flex: none;
  font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); white-space: nowrap;
}
/* The deadline wears a flag, not a dot, and it is the row's one date. */
.status-pill.t-dl {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium); color: var(--dd-ink-quiet);
  font-variant-numeric: tabular-nums;
}
.status-pill.t-dl::before {
  content: ""; width: 9px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--dd-flag) center / 11px 11px no-repeat;
  mask: var(--dd-flag) center / 11px 11px no-repeat;
}
/* A suggestion is a to-do row, checkbox and all, on an 8 percent accent
   wash with the spark right of the checkbox. No ring, no banner. */
.t-row.t-rec { background: color-mix(in srgb, var(--dd-accent) 8%, var(--dd-canvas)); }
.dd-sugmark { display: inline-flex; align-items: center; justify-content: center; flex: none; color: var(--dd-ink-quiet); }
.dd-sugmark svg { width: 13px; height: 13px; stroke-width: 1.75; fill: none; }
.t-moon { display: inline-flex; align-items: center; color: var(--dd-ink-quiet); }
.t-moon svg { width: 12px; height: 12px; stroke-width: 1.75; fill: none; }
.mail-when { flex: none; margin-left: auto; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }
.done-undo { font-weight: var(--dd-w-medium); color: var(--dd-ink-quiet); text-decoration: underline; text-decoration-color: var(--dd-hairline); text-underline-offset: 3px; }

/* The calendar block. border: 0 on all four sides; the identity is a 3px
   rounded rule standing 5px in from the left and clear of top and bottom. */
.tg-ev {
  position: relative; display: flex; flex-direction: column; justify-content: center;
  min-height: 34px; padding: 5px 8px 5px 13px;
  border: 0; border-radius: var(--dd-radius-s);
  background: color-mix(in srgb, var(--id) 16%, var(--dd-canvas));
  color: color-mix(in srgb, var(--id) 85%, var(--dd-ink));
  line-height: 1.3; overflow: hidden;
}
.tg-ev::before {
  content: ""; position: absolute; left: 5px; top: 5px; bottom: 5px;
  width: 3px; border-radius: 2px; background: var(--id); pointer-events: none;
}
.tg-ev-title {
  font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-medium);
  /* flex: none, or a block too short for its rows shrinks its own TITLE to
     nothing and draws a headless time. */
  flex: none; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tg-ev-time {
  font-size: 11px; line-height: 14px;
  color: color-mix(in srgb, var(--id) 61%, var(--dd-ink));
  font-variant-numeric: tabular-nums;
}
/* The all-day chip: the same identity, drawn as one flat 24px band. */
.tg-chip {
  display: flex; align-items: center; gap: 8px;
  height: 24px; padding: 0 8px 0 13px;
  position: relative; border-radius: var(--dd-radius-s);
  background: color-mix(in srgb, var(--id) 16%, var(--dd-canvas));
  color: color-mix(in srgb, var(--id) 85%, var(--dd-ink));
  overflow: hidden;
}
.tg-chip::before {
  content: ""; position: absolute; left: 5px; top: 5px; bottom: 5px;
  width: 3px; border-radius: 2px; background: var(--id);
}
.tg-ev-row {
  display: flex; align-items: center; gap: 3px; min-width: 0; flex: none;
  font-size: 9.5px; line-height: 13px;
  color: color-mix(in srgb, var(--id) 61%, var(--dd-ink));
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.tg-ev-row svg { width: 10px; height: 10px; flex: none; stroke-width: 1.8; fill: none; }
.tg-ev-row .tg-ev-time { overflow: hidden; text-overflow: ellipsis; }
.tg-ev-people { display: flex; align-items: center; gap: 3px; margin-top: 3px; flex: none; }
.tg-ev-people .dd-ptag { height: 15px; line-height: 13px; margin-left: 1px; }

/* The avatar tile, the product's rounded square: the agent's mark (a
   person, in the hero's window as on the ground, is the round face, "A
   PERSON"). */
.av {
  display: inline-grid; place-items: center; flex: none;
  width: 19px; height: 19px;
  border-radius: 26%; background: var(--id); color: #fff;
  font-size: 9px; font-weight: var(--dd-w-heavy); letter-spacing: 0; line-height: 1;
}
/* The app's small button, as it stands in a pane bar or a held card,
   flat like every button on this page. The go button is the ink fill. */
.dd-ai-btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 26px; padding: 0 10px;
  border: 1px solid var(--dd-border); border-radius: var(--dd-radius-m);
  background: var(--dd-panel);
  font: inherit; font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium);
  color: var(--dd-ink-light);
}
.dd-ai-btn-go { border-color: transparent; background: var(--dd-ink); color: var(--dd-on-inverse); }

/* The chat's pieces: your message as a quiet bubble, the agent's face as
   an outlined tile, and the composer. */
.vx-said { margin: 0; max-width: 94%; font-size: var(--dd-fs-sm-); line-height: var(--dd-lh-body); color: var(--dd-ink); text-wrap: pretty; }
.vx-said.is-me { align-self: flex-end; max-width: 82%; padding: 8px 11px; border-radius: var(--dd-radius-m); background: var(--dd-gray-50); }
.co-av-ai { background: none; border: 1px solid var(--dd-border); color: var(--dd-ink-quiet); }
.co-av-ai svg { width: 12px; height: 12px; stroke-width: 1.75; fill: none; }
.vx-composer {
  flex: none; padding: 9px 10px 7px;
  border: 1px solid var(--dd-border); border-radius: var(--dd-radius-l); background: var(--dd-canvas);
}
.vx-composer-ask { display: block; font-size: var(--dd-fs-sm-); color: var(--dd-ink-quiet); }
.vx-composer-send {
  margin-left: auto; display: inline-grid; place-items: center;
  width: 26px; height: 26px; border-radius: var(--dd-radius-m);
  background: var(--dd-gray-100); color: var(--dd-ink-quiet);
}
.vx-composer-send svg { width: 14px; height: 14px; stroke-width: 1.9; fill: none; }

/* ============================================================ THE SHELL
   The product's window in miniature, drawn as the light app in round 3's
   Tab language (ref SPEC3), which the app itself is taking on: soft white
   cards floating on a warm ground, separated by a wide, low shadow with a
   1px alpha ring inside it rather than by lines; hairlines only where a
   line carries meaning (the calendar's hours), and then alpha; filled,
   quiet controls; periwinkle for what the assistant suggests. David, on
   the round 2 window: "There are just some things that seem a bit
   cluttered ... the bottom corners here should be rounded just like the
   top. Just refine this too."

   The tokens are SPEC3's, read through var() with SPEC3's own values as
   the fallback, so the picture already matches the app now and follows
   shared/auth.css the day it carries them.

   THE CARDS FLOAT. The panes' track is inset by one gap on every side
   (--vx-gap: top, right AND bottom), so each pane card is whole, rounded
   at all four corners (radius l, concentric inside the window's xl), and
   stands on the ground rather than running off the window's foot. The
   rail sits on the ground itself, as in the app. */
#vx-hero {
  --vx-ground: #f5f5f3;
  --vx-fill: var(--dd-fill, rgb(17 17 18 / .04));
  --vx-fill-2: var(--dd-fill-hover, rgb(17 17 18 / .065));
  --vx-line: rgb(17 17 18 / .06);
  --vx-card: var(--dd-shadow-card-3, 0 0 0 1px rgb(17 17 18 / .04), 0 1px 2px rgb(40 45 70 / .03), 0 8px 28px -12px rgb(45 55 90 / .09));
  --vx-chip: var(--dd-shadow-chip, 0 0 0 1px rgb(17 17 18 / .05), 0 1px 3px rgb(40 45 70 / .08));
  --vx-peri: var(--dd-periwinkle, #6f86e0);
  --vx-r-card: 16px;
}
.vx-frame {
  display: flex; align-items: stretch;
  border-radius: var(--vx-r-card);
  background: var(--vx-ground);
  overflow: hidden;
  font-family: var(--dd-font-sans); color: var(--dd-ink);
  text-align: left;
}
.vx-rail { flex: none; display: flex; flex-direction: column; overflow: hidden; }
.vx-ws { display: flex; align-items: center; gap: 8px; font-weight: var(--dd-w-heavy); font-size: var(--dd-fs-sm); padding: 0 8px; }
.vx-wsname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vx-wsmark-tile { width: 22px; height: 22px; border-radius: var(--dd-radius-m); }
.vx-ws > svg { width: 14px; height: 14px; stroke-width: 2; color: var(--dd-ink-quiet); margin-left: auto; fill: none; }
/* The search is a filled field on the ground: no edge, the same left
   edge and height rhythm as the rows under it. */
.vx-search {
  display: flex; align-items: center; gap: 8px;
  border-radius: var(--dd-radius-m);
  background: var(--vx-fill); color: var(--dd-gray-500); font-size: var(--dd-fs-sm-);
}
.vx-search svg { width: 14px; height: 14px; flex: none; stroke-width: 1.75; fill: none; }
.vx-search kbd { margin-left: auto; font-family: inherit; font-size: var(--dd-fs-3xs); color: var(--dd-ink-quiet); }
.vx-nav, .vx-sec { display: flex; flex-direction: column; gap: 1px; }
.vx-navrow {
  display: flex; align-items: center;
  border-radius: var(--dd-radius-m);
  font-size: var(--dd-fs-sm); font-weight: var(--dd-w-medium); color: var(--dd-ink-light);
}
.vx-navrow svg { flex: none; stroke-width: 1.75; fill: none; }
/* The focused pane's row is the WHITE CHIP (round 1's, which David liked):
   the panel with the chip shadow, ink words. The second open pane is ink
   with no chip, which is how the real rail marks a split. */
.vx-navrow.active { background: var(--dd-panel); box-shadow: var(--vx-chip); color: var(--dd-ink); font-weight: var(--dd-w-bold); }
.vx-navrow.is-open { color: var(--dd-ink); font-weight: var(--dd-w-bold); }
/* Counts are plain quiet text. */
.vx-count {
  margin-left: auto; font-size: var(--dd-fs-xs); font-weight: var(--dd-w-regular);
  color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums;
}
.vx-seclabel {
  font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium);
  letter-spacing: 0; color: var(--dd-ink-quiet); padding: 4px 8px 3px;
}
.vx-rec { display: flex; align-items: center; gap: 10px; border-radius: var(--dd-radius-m); white-space: nowrap; font-size: var(--dd-fs-sm); color: var(--dd-ink-light); }
.vx-recname { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.vx-rec .dd-mark { width: 16px; height: 16px; border-radius: 5px; }
/* The chat history: a title and when, both quiet but the title in the
   rows' ink-light. */
.vx-when { flex: none; margin-left: auto; font-size: var(--dd-fs-3xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }

.vx-panes { flex: 1; min-width: 0; display: grid; grid-template-columns: .9fr var(--vx-gap) 1.35fr; }
/* A pane card: white, radius l at all four corners, the card shadow with
   its alpha ring, no border. */
.vx-card {
  min-width: 0; display: flex; flex-direction: column; overflow: hidden;
  border-radius: var(--vx-r-card);
  background: var(--dd-panel);
  box-shadow: var(--vx-card);
}
.vx-seam { min-width: 0; }
/* The pane's head: no rule under it, the body starts after whitespace. */
.vx-topbar {
  flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-bold);
}
.vx-topbar-page { display: flex; align-items: center; gap: 8px; min-width: 0; overflow: hidden; white-space: nowrap; }
.vx-topbar-page svg { width: 15px; height: 15px; flex: none; stroke-width: 1.75; color: var(--dd-ink-light); fill: none; }
.vx-topbar-help { flex: none; color: var(--dd-ink-quiet); font-weight: var(--dd-w-medium); }
.vx-topico { display: inline-flex; align-items: center; flex: none; }
.vx-body { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 2px; overflow: hidden; }

/* THE ROWS in the window, restyled here for the window alone (the page's
   other pictures keep THE PRODUCT'S rows above). A suggestion is marked
   by the periwinkle sparkle and its group's periwinkle label, with one
   faint periwinkle wash under the pair, never a slab per row. A checkbox
   keeps its edge (a checkbox needs one), in alpha. A tag is a filled chip
   with no border. */
#vx-hero .t-row { background: none; }
#vx-hero .check-face { border-color: rgb(17 17 18 / .22); background: var(--dd-panel); }
#vx-hero .check-face.is-on { border-color: var(--dd-accent); background: var(--dd-accent); }
#vx-hero .dd-sugmark { color: var(--vx-peri); }
.vx-sug {
  display: flex; flex-direction: column; gap: 2px;
  /* 10px inside the window's 16px corner: small is the concentric corner
     (it was a literal 12px). */
  border-radius: var(--dd-radius-s);
  background: rgb(111 134 224 / .055);
}
.vx-suglabel { color: var(--vx-peri); }
.vx-tag {
  display: inline-block; flex: none; max-width: 96px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-radius: var(--dd-radius-s);
  background: var(--vx-fill-2);
  font-weight: var(--dd-w-medium); letter-spacing: .01em; color: var(--dd-ink-quiet);
}

/* ------------------------------------------------- THE WEEK, in miniature
   The grid is the one set of lines in the window, because its lines carry
   the days and the hours; they are alpha and faint. */
.vx-cal {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  --vx-rule: rgb(17 17 18 / .05);
}
.vx-calhead, .vx-allday, .vx-week { display: grid; grid-template-columns: var(--vx-gut) repeat(5, minmax(0, 1fr)); }
.vx-dayhead {
  display: flex; flex-direction: column; align-items: center; min-width: 0;
  padding: 2px 2px 5px; font-size: var(--dd-fs-3xs);
  letter-spacing: var(--dd-ls-caps); color: var(--dd-ink-quiet);
}
.vx-dayhead b {
  display: grid; place-items: center; width: 20px; height: 20px; margin-top: 2px;
  font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-bold); color: var(--dd-ink);
  font-variant-numeric: tabular-nums; letter-spacing: 0; border-radius: 50%;
}
.vx-dayhead.is-today { color: var(--dd-ink); }
.vx-dayhead.is-today b { background: var(--dd-accent); color: var(--dd-on-accent); }
.vx-allday { border-bottom: 1px solid var(--vx-line); min-height: 28px; align-items: center; padding-bottom: 4px; overflow: clip; }
.vx-gutlabel {
  align-self: center; padding-right: 6px; text-align: right; min-width: 0; overflow: hidden;
  font-size: var(--dd-fs-3xs); font-weight: var(--dd-w-medium);
  text-transform: uppercase; letter-spacing: var(--dd-ls-caps-wide); color: var(--dd-ink-quiet);
}
.vx-adcell { min-width: 0; padding: 0 3px; }
.vx-adcell .tg-chip { height: 20px; padding: 0 6px 0 11px; }
.vx-adcell .tg-ev-title { font-size: 10px; }
.vx-week { flex: 1; min-height: 0; overflow: hidden; }
.vx-gutter { display: flex; flex-direction: column; }
.vx-gutter i {
  height: var(--vx-hour); padding-right: 5px; flex: none;
  font-style: normal; font-size: var(--dd-fs-3xs); line-height: 1;
  color: var(--dd-ink-quiet); text-align: right; font-variant-numeric: tabular-nums;
  transform: translateY(-3px);
}
.vx-day {
  position: relative; min-width: 0;
  border-left: 1px solid var(--vx-rule);
  background-image: linear-gradient(to bottom, var(--vx-rule) 0 1px, transparent 1px);
  background-size: 1px var(--vx-hour); background-repeat: repeat; background-position: 0 -1px;
}
/* A block is its title and its time: the tint, the identity bar, radius
   s, and one row of faces only where the block asks for it. */
.vx-blk {
  position: absolute; left: 2px; right: 2px;
  top: calc(var(--s) * var(--vx-hour));
  height: calc((var(--e) - var(--s)) * var(--vx-hour) - 2px);
  min-height: 0; padding: 3px 3px 3px 11px;
  justify-content: flex-start; gap: 0;
  container-type: size;
}
.vx-blk::before { left: 3.5px; top: 4px; bottom: 4px; width: 2.5px; }
.vx-blk .tg-ev-title { line-height: 1.25; white-space: normal; overflow: hidden; text-overflow: clip; }
.vx-blk .tg-ev-row, .vx-blk .tg-ev-people { display: none; }
@container (min-height: 30px) { .vx-blk .tg-ev-row { display: flex; } }
@container (min-height: 60px) { .vx-blk .tg-ev-people { display: flex; } }

/* The now line is MONOCHROME: a 2px ink rule with an 8px ink dot. */
.vx-now {
  position: absolute; left: 0; right: 0;
  top: calc(4.33 * var(--vx-hour));
  border-top: 2px solid var(--dd-ink); z-index: 4; pointer-events: none;
}
.vx-now::before {
  content: ""; position: absolute; left: -3px; top: -5px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--dd-ink);
}

/* THE ONE UNIT. The window scales off one container unit: --u is one
   "design pixel", 1px when the window is at its 1200 design width and no
   less than .86px when the page is narrow, so the type never goes under
   about 10.7px. Everything structural in the window is calc(N * var(--u)),
   so the same window is the same window at 2560 and at 1024. */
.vx-frame { --u: clamp(.86px, .08333cqi, 1px); --vx-gap: calc(10 * var(--u)); font-size: calc(12.5 * var(--u)); }
.vx-rail {
  width: calc(216 * var(--u)); gap: calc(12 * var(--u));
  padding: calc(16 * var(--u)) calc(10 * var(--u)) calc(14 * var(--u)) calc(12 * var(--u));
}
.vx-search { height: calc(32 * var(--u)); padding: 0 calc(10 * var(--u)); }
.vx-navrow { padding: calc(6 * var(--u)) calc(8 * var(--u)); gap: calc(10 * var(--u)); }
.vx-navrow svg { width: calc(16 * var(--u)); height: calc(16 * var(--u)); }
.vx-rec { padding: calc(5 * var(--u)) calc(8 * var(--u)); }
.vx-panes { padding: var(--vx-gap) var(--vx-gap) var(--vx-gap) 0; }
.vx-topbar { height: calc(46 * var(--u)); padding: 0 calc(16 * var(--u)); }
.vx-body { padding: 0 calc(10 * var(--u)) calc(8 * var(--u)); }
.vx-sug { padding: calc(2 * var(--u)) 0 calc(4 * var(--u)); margin-bottom: calc(8 * var(--u)); }
.vx-tag { height: calc(18 * var(--u)); line-height: calc(18 * var(--u)); padding: 0 calc(6 * var(--u)); font-size: calc(10.5 * var(--u)); }
.vx-cal { --vx-gut: calc(24 * var(--u)); --vx-hour: calc(50 * var(--u)); padding: 0 calc(8 * var(--u)) calc(8 * var(--u)); }
.vx-frame .t-row { min-height: calc(34 * var(--u)); padding: calc(7 * var(--u)) calc(10 * var(--u)); }
.vx-blk .tg-ev-title { font-size: calc(10.5 * var(--u)); }
.vx-frame .tg-ev-row { font-size: calc(9.5 * var(--u)); line-height: calc(13 * var(--u)); }

/* ============================================ THE PICTURES' ONE STYLE
   ROUND 3 OF THE TAB PASS (David: "give all the UI the same style ... I
   want you to give all those UI elements the same tab style pass as
   well"). Every product picture below the hero (the busywork cards, the
   team's cards, the project page) speaks the app's round 3 language, the
   one ref SPEC3 sets for the signed-in app, and they all share ONE FRAME:
     - THE GROUND CARD. Each picture stands on a card of the app's warm
       ground (#f5f5f3) at radius 24, with no edge and no shadow of its
       own; a card's serif title and its one sentence sit on it too. This
       replaces round 2's three layers (a white outlined card, a grey
       plate inside it, a white outlined pane inside that) with the two the
       app itself has: the ground, and white panes floating on it.
     - THE PANE. White at radius 16, separated from the ground by the
       app's card shadow (a 1px alpha ring inside a wide, low, blue-slate
       haze), never a border. Inside, no decorative rules: the pane head
       has no line under it and regions part by space.
     - FILLS, NOT OUTLINES. Chips, tags, inputs and secondary buttons are
       ink at 4 percent; the primary button is ink; a selected thing on a
       fill is the white chip; what the agent made or suggests is
       periwinkle (its wash, its sparkle), and nothing else is.
     - RADII s 6, m 10, l 16, concentric where they nest.
   The tokens live on .home-ground so none of this can reach the hero's
   window, which its own lane draws. They are local rather than borrowed
   from shared/auth.css because that sheet's copy of the tokens belongs to
   the sign-in pages and moves on its own schedule. */
.home-ground {
  --mk-ground: #f5f5f3;
  --mk-fill: rgb(17 17 18 / .04);
  --mk-fill-2: rgb(17 17 18 / .065);
  --mk-faint: rgb(17 17 18 / .018);
  --mk-line: rgb(17 17 18 / .06);
  --mk-ring: rgb(17 17 18 / .22);
  --mk-shadow: 0 0 0 1px rgb(17 17 18 / .04), 0 1px 2px rgb(40 45 70 / .03), 0 8px 28px -12px rgb(45 55 90 / .09);
  --mk-chip: 0 0 0 1px rgb(17 17 18 / .05), 0 1px 2px rgb(40 45 70 / .05);
  --mk-peri: #6f86e0;
  --mk-peri-ink: #4358a6;
  --mk-peri-wash: rgb(111 134 224 / .1);
  --mk-peri-wash-2: rgb(111 134 224 / .17);
  --mk-rs: 6px;
  --mk-rm: 10px;
  --mk-rl: 16px;
  --mk-rx: 24px;
}

/* The ground card, and the pane on it. */
/* The card clips: with the pane standing only the concentric 8px in, the
   pane's haze would otherwise run past the card's bottom edge onto the
   page as a grey smudge. Inside the card it still lifts the pane. */
.home-ground .fc { border: 0; border-radius: var(--mk-rx); background: var(--mk-ground); box-shadow: none; overflow: clip; }
.home-ground :is(.sr, .sc, .st, .cx, .pr, .mk-pane) {
  border: 0; border-radius: var(--mk-rl);
  background: var(--dd-panel); --dd-canvas: var(--dd-panel);
  box-shadow: var(--mk-shadow);
  overflow: hidden;
}

/* The product's pieces in this language, for the pictures only. */
.home-ground .dd-ptag { border: 0; background: var(--mk-fill); color: var(--dd-ink-light); }
.home-ground .dd-ptag-sm { line-height: 16px; }
.home-ground .dd-ptag-lg { line-height: 20px; }
.home-ground .check-face { border-color: var(--mk-ring); background: transparent; }
.home-ground .check-face.is-on { border-color: var(--dd-ink); background: var(--dd-ink); }
.home-ground .dd-sugmark { color: var(--mk-peri); }
.home-ground .dd-ai-btn { border: 0; background: var(--mk-fill); color: var(--dd-ink); }
.home-ground .dd-ai-btn-go { background: var(--dd-ink); color: #fff; }
.home-ground .vx-said.is-me { background: var(--mk-fill); }
.home-ground .co-av-ai { border: 0; background: var(--mk-peri-wash); color: var(--mk-peri); }
.home-ground .vx-composer { border: 0; border-radius: var(--mk-rm); background: var(--mk-fill); }
.home-ground .vx-composer-send { background: var(--mk-fill-2); }
/* A done thing is a green disc with a tick. */
.home-ground :is(.sr-sent, .tt-booked) .check-face { width: 14px; height: 14px; border-radius: 50%; background: var(--dd-green); border-color: var(--dd-green); }
.home-ground :is(.sr-sent, .tt-booked) .check-face::after { -webkit-mask-size: 9px 9px; mask-size: 9px 9px; }
/* A PERSON (components/Face.tsx). Every face on the ground is ONE mark,
   the one the project card settled on (2026-09-24): a small round face on
   a soft tint of the person's colour, the first initial in a deeper shade
   of it, never the bright square with white letters. The hero's window
   draws it too, on its standup, at 15px (2026-09-24). Sized by where it
   stands, on one scale: 20px on
   a row (a sender, the composer, a lane, a source, the hand that ticks a
   task), 18px in the booked line's stack, which sits in a line of small
   type, and 22px in the project's bar, where it stands beside the page's
   own controls; the initial is the same share of the face at every step.
   The tint is mixed into the pane's white, so a face
   is opaque on a filled surface (the composer, a source tile) and reads
   the same there as on white.
   A STACK overlaps the same way everywhere: each face after the first
   tucks 5px under the one before and wears a 2px ring of the pane's white,
   so the overlap reads as a stack and not as a smudge. */
:is(.home-ground, #vx-hero) .face {
  --face: 20px;
  position: relative; display: inline-grid; place-items: center; flex: none;
  width: var(--face); height: var(--face); border-radius: 50%;
  background: color-mix(in srgb, var(--id) 15%, var(--dd-panel));
  color: color-mix(in srgb, var(--id) 80%, var(--dd-ink));
  font-size: calc(var(--face) * .455); font-weight: var(--dd-w-bold); letter-spacing: 0; line-height: 1;
}
:is(.home-ground, #vx-hero) .faces { display: flex; flex: none; }
:is(.home-ground, #vx-hero) .faces > .face { box-shadow: 0 0 0 2px var(--dd-panel); }
:is(.home-ground, #vx-hero) .faces > .face + .face { margin-left: -5px; }
/* In the hero window's calendar block, at the block's small size. */
#vx-hero .tg-ev-people .face { --face: 15px; }
#vx-hero .tg-ev-people .faces > .face { box-shadow: 0 0 0 1.5px var(--dd-panel); }
#vx-hero .tg-ev-people .faces > .face + .face { margin-left: -4px; }
/* The agent is not a person: its mark keeps the tile, on the periwinkle
   wash, at the faces' size so a reply lines up with the rows round it. */
.home-ground .co-av-ai { width: 20px; height: 20px; }

/* The pane head every picture wears, the product's own at picture size:
   the module's glyph and a name on the left (a crumb after a chevron where
   the pane is a sub-page), what the pane says on the right. No rule under
   it (SPEC3: regions part by space). */
.mb {
  flex: none; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  min-height: 40px; padding: 0 12px 0 14px;
  font-size: var(--dd-fs-xs); font-weight: var(--dd-w-bold); color: var(--dd-ink);
}
.mb-page { display: flex; align-items: center; gap: 7px; min-width: 0; overflow: hidden; white-space: nowrap; }
.mb-ico { display: inline-flex; flex: none; color: var(--dd-ink-light); }
.mb-ico svg { width: 13px; height: 13px; stroke-width: 1.75; fill: none; }
.mb-crumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--dd-ink-quiet); font-weight: var(--dd-w-medium); }
.mb-crumb::before { content: "\203A"; margin: 0 6px 0 1px; }
.mb-help {
  flex: none; display: flex; align-items: center; gap: 6px; min-width: 0;
  font-weight: var(--dd-w-medium); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ==================================================== 2. THE BUSYWORK
   Three cards in a row at the 1200 ceiling, one column (up to 560 wide)
   under 1000, each a ground card (THE PICTURES' ONE STYLE).

   ONE GRID FOR THE THREE (David: the titles, the sentences and the
   pictures line up "by construction, not by luck"). Each card spans three
   rows of the row's grid and takes them as a SUBGRID, so the title row is
   as tall as the tallest title, the three sentences start on one line and
   the three pictures at one y, whatever wraps. The title is two lines on
   purpose, each half a block ("Emails that" / "answer themselves."), so
   the three break at the same word. The team's four cards below use the
   same subgrid. The gap above the grid is the section head's
   (--home-head-gap), so the grid sets no margin of its own. */
.fg, .eg {
  list-style: none; margin: 0; padding: 0;
  display: grid; column-gap: clamp(14px, 1.4vw, 20px); row-gap: 0;
  text-align: left;
}
.fg { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* THE PANE SITS IN ITS CARD CONCENTRICALLY (the details pass). The card's
   corner is --mk-rx and the pane's --mk-rl, so the pane stands their
   difference in (8px) on the sides and the bottom and the two curves share
   a centre; at 18px in, the pane's 16px corner was rounder than the card's
   curve around it and the grey band swelled at every bottom corner. The
   words keep their old left edge (--fc-text from the card's edge), so
   only the picture moved. */
.fc {
  --fc-bezel: calc(var(--mk-rx) - var(--mk-rl));
  --fc-text: clamp(20px, 1.8vw, 26px);
  grid-row: span 3;
  display: grid; grid-template-rows: subgrid; row-gap: 0;
  padding: clamp(18px, 1.8vw, 24px) var(--fc-bezel) var(--fc-bezel);
}
.fc > .fc-name, .fc > .fc-say { margin-left: calc(var(--fc-text) - var(--fc-bezel)); margin-right: calc(var(--fc-text) - var(--fc-bezel)); }
.fc-name {
  margin: 0; font-size: var(--home-h3-size);
  font-weight: var(--home-h3-w); letter-spacing: var(--home-h3-ls);
  line-height: var(--home-h3-lh); text-wrap: balance;
}
.fc-l { display: block; }
.fc-say {
  margin: 8px 0 0; max-width: 46ch;
  font-size: var(--dd-fs-md); font-weight: var(--home-text-w); line-height: var(--dd-lh-body);
  color: var(--dd-ink-quiet); text-wrap: pretty;
}
/* THE PICTURE IS THE APP: the pane stands straight on the card's ground,
   with no plate of its own. */
.fc-face {
  min-height: 280px; margin-top: clamp(16px, 1.6vw, 22px);
  display: flex; flex-direction: column;
  container-type: inline-size;
}
.fc-face > * { flex: 1 1 auto; min-height: 0; }
.sr, .st, .cx, .pr { display: flex; flex-direction: column; }

/* a. emails that answer themselves. The three replies are the agent's, so
   they stand on its periwinkle wash; the picked one deepens and takes a
   ring of the same hue, drawn on a layer under it so the play can light
   it; the other two step back. */
.sr-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 7px; padding: 4px 14px 14px; }
.sr-from { display: flex; align-items: center; gap: 7px; margin: 0; font-size: var(--dd-fs-sm-); }
.sr-from b { font-weight: var(--dd-w-heavy); }
.sr-msg { margin: 0; font-size: var(--dd-fs-sm-); line-height: var(--dd-lh-body); color: var(--dd-ink-light); text-wrap: pretty; }
.sr-label {
  display: flex; align-items: center; gap: 6px; margin: 5px 0 0;
  font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-medium);
  text-transform: uppercase; letter-spacing: .07em; color: var(--dd-ink-quiet);
}
.sr-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.sr-opt {
  position: relative; z-index: 0;
  padding: 7px 10px; border-radius: var(--mk-rs);
  background: var(--mk-peri-wash);
  font-size: var(--dd-fs-sm-); line-height: 1.35; color: var(--dd-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sr-opt::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: var(--mk-peri-wash-2);
  box-shadow: inset 0 0 0 1px rgb(111 134 224 / .35);
  opacity: 0;
}
.sr-opt.is-pick::before { opacity: 1; }
.sr-opt:not(.is-pick) { opacity: .45; }
.sr-sent { display: flex; align-items: center; gap: 7px; margin: auto 0 0; font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium); color: var(--dd-ink-light); }
.sr-sent .done-undo, .st-note .done-undo { margin-left: auto; }

/* b. meetings that book themselves: the ask over the afternoon it lands
   in (side by side only where the pane is wide enough for two readable
   halves, which in the three-across row is never). The ask the agent read
   is lit in periwinkle; travel is a quiet hatch, not an outline; the
   proposal keeps the product's dashed edge in its calendar's colour,
   because in the product dashed MEANS not yet approved. */
.sc { display: grid; grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr); }
.sc-mail { min-width: 0; display: flex; flex-direction: column; }
.sc-msg { position: relative; z-index: 0; margin: 0; padding: 12px 14px; font-size: var(--dd-fs-sm-); line-height: var(--dd-lh-body); color: var(--dd-ink-light); text-wrap: pretty; }
/* The ask is lit on a layer under its words, so the play can light it
   without touching the text. */
.sc-ask { position: relative; background: transparent; color: var(--dd-ink); white-space: nowrap; }
.sc-ask::before {
  content: ""; position: absolute; inset: -1px -3px; z-index: -1;
  border-radius: var(--mk-rs);
  background: var(--mk-peri-wash-2);
}
.sc-reply { margin: auto 10px 10px; padding: 8px 10px 9px; border-radius: var(--mk-rm); background: var(--mk-peri-wash); }
.sc-replyhead {
  display: flex; align-items: center; gap: 6px; margin: 0 0 3px;
  font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-medium);
  text-transform: uppercase; letter-spacing: .07em; color: var(--dd-ink-quiet);
}
.sc-replyline { margin: 0; font-size: var(--dd-fs-xs); line-height: var(--dd-lh-ui); color: var(--dd-ink); text-wrap: pretty; }
.sc-day { min-width: 0; display: flex; flex-direction: column; }
.sc-grid { position: relative; flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: 26px minmax(0, 1fr); padding: 6px 12px 6px 4px; }
.sc-gutter { display: grid; grid-template-rows: repeat(4, minmax(0, 1fr)) minmax(0, .5fr); }
.sc-gutter i { padding-right: 6px; font-style: normal; font-size: var(--dd-fs-3xs); line-height: 1; color: var(--dd-ink-quiet); text-align: right; font-variant-numeric: tabular-nums; transform: translateY(-4px); }
/* The hour rules are information, so they stay, as faint as the app's. */
.sc-col {
  position: relative; min-width: 0;
  background-image: linear-gradient(to bottom, var(--mk-line) 0 1px, transparent 1px);
  background-size: 100% calc(100% / 4.5); background-repeat: repeat-y;
}
.tg-ev.sc-blk, .sc-trav {
  position: absolute; left: 2px; right: 0;
  top: calc(var(--t) * 100% / 4.5 + 1px); height: calc(var(--h) * 100% / 4.5 - 2px);
}
.tg-ev.sc-blk { z-index: 2; min-height: 0; padding: 3px 6px 3px 11px; justify-content: flex-start; gap: 1px; }
.sc-blk::before { left: 3.5px; top: 4px; bottom: 4px; width: 2.5px; }
.sc-blk .tg-ev-title { font-size: 10.5px; line-height: 1.25; }
.sc-sug { outline: 1.5px dashed color-mix(in srgb, var(--id) 62%, transparent); outline-offset: -1.5px; }
.sc-trav {
  z-index: 1; display: flex; align-items: center; padding: 0 8px;
  border-radius: var(--mk-rs);
  background: repeating-linear-gradient(135deg, var(--mk-fill-2) 0 3px, transparent 3px 7px);
  font-size: 9.5px; line-height: 1; color: var(--dd-ink-quiet); white-space: nowrap; overflow: hidden;
}
.sc-why {
  flex: none; display: flex; align-items: center; gap: 6px; margin: 0;
  padding: 8px 12px 10px 14px;
  font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet);
}
.sc-whyline { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-booked { font-weight: var(--dd-w-medium); color: var(--dd-green); }
@container (max-width: 480px) {
  .sc { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .sc-mail .mb, .sc-reply { display: none; }
  .sc-msg { padding: 14px 14px 6px; }
  .sc-grid { min-height: 176px; }
  .sc-blk .tg-ev-row { display: none; }
}

/* c. to-dos that write themselves: two new rows on the agent's periwinkle
   wash, the list sorted by what is due. The pitch is the row (30px) plus
   the gap (4px), and the play's sort is drawn in pitches (--from, in
   rows). */
.st { --pitch: 34px; }
.st-count { font-weight: var(--dd-w-medium); }
.st-list { display: flex; flex-direction: column; gap: 4px; padding: 2px 8px 0; }
.st .st-row { height: 30px; min-height: 30px; padding: 0 8px; gap: 9px; font-size: var(--dd-fs-sm-); }
.st-row .t-meta { gap: 7px; }
.st-new { background: var(--mk-peri-wash); }
.st-src { font-size: var(--dd-fs-2xs); color: var(--dd-ink-quiet); }
.st-note { display: flex; align-items: center; gap: 6px; margin: auto 0 0; padding: 8px 14px 12px; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); }
@container (max-width: 400px) {
  .st-src { display: none; }
}
@container (max-width: 340px) {
  .st .dd-ptag { display: none; }
}

/* ============================================ 3. IT KNOWS YOUR TEAM
   FOUR CARDS in the busywork cards' family, in three rows (round 5,
   David: "'A time everyone's free' section should be the same as it was
   before. It would be two columns wide, with one wide one. Ask about any
   client and recommendations would just be two separate ones on that
   line, and the projects would be one big one below as well"):
     - 1000 AND WIDER. The time and the project are .fc-wide, each a whole
       row, the first and the last: their title and sentence share one
       baseline across the top of the card (which keeps a long card short)
       and the picture takes the full width under them, so the time's two
       panes stand side by side (round 3's composition) and the project
       page keeps its two columns. Between them the client and the pricing
       call share a row, each spanning three rows of the list's grid as a
       subgrid, exactly as the busywork cards do, so their two titles, two
       sentences and two pictures start on one line whatever wraps. Every
       card but the last carries the gap to the next row as a bottom
       margin (the list's own row gap stays 0, or it would open inside the
       pair's subgrids too).
     - UNDER 1000 one column in the same order (the responsive block at the
       foot): the pair's pictures need more than half of a narrower row,
       and each wide picture folds on its own container queries (the time
       stacks its panes under 760, the project page moves its head across
       the top under 880).
   The pictures fill their row: each face stretches, and the panes in it
   with it. */
.eg { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.eg > .fc:not(:last-child) { margin-bottom: clamp(14px, 1.4vw, 20px); }
.eg .fc-face { min-height: 0; }
@media (min-width: 1000px) {
  .fc-wide {
    grid-column: 1 / -1; grid-row: auto;
    grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto;
    align-items: baseline; column-gap: clamp(16px, 2vw, 28px);
  }
  .fc-wide > .fc-say { margin-top: 0; max-width: none; }
  .fc-wide > .fc-face { grid-column: 1 / -1; }
}

/* a. a time everyone's free: the team's Wednesday and the agent, two
   panes on the card's ground with the app's 10px seam between them. */
.tt { display: grid; grid-template-columns: minmax(0, 1.72fr) minmax(0, 1fr); gap: 10px; }
.tt-cal, .tt-chat { min-width: 0; display: flex; flex-direction: column; }

/* The day switcher in the team pane's head: a filled track, the day shown
   as the white chip (SPEC3's selected thing on a fill). */
.tt-days { display: inline-flex; padding: 2px; border-radius: calc(var(--mk-rs) + 2px); background: var(--mk-fill); }
.tt-day {
  height: 22px; padding: 0 8px; border-radius: var(--mk-rs);
  font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-medium); line-height: 22px; color: var(--dd-ink-quiet);
}
.tt-day.is-on { background: var(--dd-panel); color: var(--dd-ink); box-shadow: var(--mk-chip); }

/* THE DAY. A name column, then nine hour columns 9:00 to 18:00 (--span),
   five lanes. The hour rules are the grid's information and run down
   through every lane; nothing else is drawn but the busy time, one quiet
   grey, so the free hours read as clear columns. */
.tg { --who: 104px; flex: 1 1 auto; display: flex; flex-direction: column; padding: 0 14px 14px; }
.tg-hours { display: grid; grid-template-columns: var(--who) minmax(0, 1fr); height: 20px; }
.tg-hrow { display: grid; grid-template-columns: repeat(var(--span), minmax(0, 1fr)); }
.tg-hrow > span { padding-left: 4px; font-size: var(--dd-fs-3xs); line-height: 1; color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }
.tg-body { position: relative; flex: 1 1 auto; display: grid; grid-auto-rows: minmax(42px, 1fr); }
.tg-lane { position: relative; z-index: 1; display: grid; grid-template-columns: var(--who) minmax(0, 1fr); }
.tg-who { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium); color: var(--dd-ink-light); }
/* The ring on the face whose calendar is being read, in the play, round
   like the face it rings. */
.tg-who .face::after {
  content: ""; position: absolute; inset: -3px; border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--mk-peri); opacity: 0;
}
.tg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-track {
  position: relative; min-width: 0;
  background-image: linear-gradient(to right, var(--mk-line) 0 1px, transparent 1px);
  background-size: calc(100% / var(--span)) 100%;
  box-shadow: inset -1px 0 var(--mk-line);
}
.tg-b {
  position: absolute; top: 8px; bottom: 8px;
  left: calc(var(--t) * 100% / var(--span) + 3px); width: calc(var(--h) * 100% / var(--span) - 6px);
  border-radius: var(--mk-rs);
  background: rgb(17 17 18 / .075);
}
/* Over the tracks, the agent's layer: the three hours that work, lit as
   columns with their rank (only in the play; at rest they are gone), the
   booked review, and the scan. No z-index on the layer itself, so its
   pieces sit in the day's own stack: the columns under the lanes (a busy
   block shows through the third), the review and the scan over them. */
.tg-over { position: absolute; top: 0; bottom: 0; left: var(--who); right: 0; pointer-events: none; }
.tg-opt, .tg-book { position: absolute; left: calc(var(--t) * 100% / var(--span) + 2px); width: calc(100% / var(--span) - 4px); }
.tg-opt { z-index: 0; top: 2px; bottom: 2px; border-radius: var(--mk-rs); background: var(--mk-peri-wash-2); opacity: 0; }
.tg-opt > b {
  position: absolute; left: 50%; top: 6px; width: 16px; height: 16px; margin-left: -8px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--mk-peri); color: #fff; font-size: 9px; font-weight: var(--dd-w-bold); line-height: 1;
}
/* THE ONE STRIPE, the review the agent booked, down all five lanes. */
.tg-book {
  z-index: 2; top: 3px; bottom: 3px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  border-radius: var(--mk-rs);
  background: color-mix(in srgb, var(--mk-peri) 20%, var(--dd-panel));
  box-shadow: inset 0 0 0 1.5px var(--mk-peri);
  color: var(--mk-peri-ink);
}
.tg-book-tick { width: 16px; height: 16px; flex: none; border-radius: 50%; background: var(--mk-peri); position: relative; }
.tg-book-tick::after {
  content: ""; position: absolute; inset: 0; background: #fff;
  -webkit-mask: var(--dd-tick) center / 10px 10px no-repeat; mask: var(--dd-tick) center / 10px 10px no-repeat;
}
.tg-book-name { font-size: 10.5px; font-weight: var(--dd-w-bold); line-height: 1.25; text-align: center; overflow-wrap: anywhere; }
.tg-scan { position: absolute; inset: 0; z-index: 3; opacity: 0; }
.tg-scan::before { content: ""; position: absolute; left: -1px; top: 0; bottom: 0; width: 2px; border-radius: 1px; background: var(--mk-peri); }
.tg-scan::after { content: ""; position: absolute; right: 100%; top: 0; bottom: 0; width: 36px; background: linear-gradient(to right, transparent, rgb(111 134 224 / .14)); }

/* The agent: the ask, its answer (a live line while it reads, the finding
   once it has), the ranked hours on a filled track with the chosen one as
   the white chip, and the booking. */
.tt-thread { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 12px; padding: 4px 12px 10px; }
.tt-merow { display: flex; justify-content: flex-end; margin: 0; }
.tt-thread .vx-said.is-me { max-width: 92%; }
.tt-answer { display: flex; flex-direction: column; gap: 8px; }
.tt-reply { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--dd-fs-sm-); color: var(--dd-ink); }
.tt-say { flex: 1 1 auto; min-width: 0; display: grid; }
.tt-say > * { grid-area: 1 / 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tt-stat { color: var(--dd-ink-quiet); opacity: 0; }
.tt-tick { display: grid; flex: none; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }
.tt-tk { grid-area: 1 / 1; white-space: nowrap; opacity: 0; }
.tt-opts { list-style: none; margin: 0; padding: 3px; display: flex; flex-direction: column; gap: 1px; border-radius: var(--mk-rm); background: var(--mk-fill); }
.tt-opt {
  position: relative; z-index: 0; display: flex; align-items: center; gap: 9px;
  height: 30px; padding: 0 10px 0 6px; border-radius: calc(var(--mk-rm) - 3px);
  font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tt-opt::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--dd-panel); box-shadow: var(--mk-chip); opacity: 0; }
.tt-opt.is-pick::before { opacity: 1; }
.tt-rank {
  display: inline-grid; place-items: center; flex: none; width: 18px; height: 18px; border-radius: 5px;
  background: var(--mk-fill-2); color: var(--dd-ink-light); font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-bold);
}
.tt-opt.is-pick .tt-rank { background: var(--mk-peri); color: #fff; }
.tt-when { font-weight: var(--dd-w-medium); color: var(--dd-ink-light); }
.tt-opt.is-pick .tt-when { color: var(--dd-ink); }
.tt-who { margin-left: auto; }
.tt-booked { display: flex; align-items: center; gap: 7px; margin: 0; padding: 0 2px; font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium); color: var(--dd-green); }
.tt-bookline { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-faces { margin-left: auto; padding-left: 4px; }
/* The booked line's stack sits in a line of small type, so its faces are
   the scale's smallest step. */
.tt-faces > .face { --face: 18px; }
/* THE COMPOSER, ONE LINE (round 4, David: "it just has a big forehead and
   the text types above that"). The face, the field and the send button on
   one row, centred, 40px tall (7px round a 26px button), the size of the
   app's composer holding a single line. The placeholder and the typed ask
   share the field's one cell and its one 20px line, so the ask types in
   place. The typed line keeps its END in view like a real text field:
   the field is a flex row packed to its end, and the line's auto right
   margin keeps it at the start while it fits (an auto margin takes free
   space first; with none left it is 0 and the end packing wins), so a
   narrow pane scrolls the line left as the letters arrive instead of
   pushing them out of sight. Letters not yet typed take no room at all in
   the play (tm-ch shows each one's display with its opacity), so the
   line's width is always what has been typed. The caret stands after the
   last letter while the ask is being typed. */
/* The composer stands l minus m in from the pane's corner so its medium
   corner is concentric with it; its send button, 7px inside that, floors
   at small. */
.tt-comp { display: flex; align-items: center; gap: 8px; margin: 0 calc(var(--mk-rl) - var(--mk-rm)) calc(var(--mk-rl) - var(--mk-rm)); padding: 7px 7px 7px 9px; }
.tt-comp .vx-composer-send { border-radius: var(--mk-rs); }
.tt-field { flex: 1 1 auto; min-width: 0; display: grid; align-items: center; font-size: var(--dd-fs-sm-); line-height: 20px; }
.tt-field > * { grid-area: 1 / 1; min-width: 0; white-space: nowrap; }
.tt-ph { overflow: hidden; text-overflow: ellipsis; }
.tt-typed { display: flex; justify-content: flex-end; overflow: hidden; color: var(--dd-ink); opacity: 0; }
.tt-line { flex: none; margin-right: auto; white-space: pre; }
.tt-line::after {
  content: ""; display: inline-block; width: 1.5px; height: 16px; margin-left: 1px;
  vertical-align: -3px; border-radius: 1px; background: var(--dd-ink);
}
.tt-comp .vx-composer-send { position: relative; z-index: 0; flex: none; }
.tt-comp .vx-composer-send::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit; background: var(--dd-ink); opacity: 0;
}
/* Narrower (the whole-row card between 720 and 1000), the agent takes a
   larger share, so its lines (the finding, "Booked. Invites sent to 5."
   and the five faces) keep their words, and the day's name column gives
   up 20px so each hour stays about 40px and the stripe still holds
   "Design review" as two whole words; under 760 the two panes stack, the
   day first, and under 520 the lanes keep their faces without names and
   the stripe its tick without words. */
@container (max-width: 900px) {
  .tt { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
  .tg { --who: 84px; }
  .tg-book-name { font-size: 10px; }
}
@container (max-width: 760px) {
  .tt { grid-template-columns: minmax(0, 1fr); }
  .tt-thread { min-height: 0; }
}
/* In a swiped card's narrower picture (a phone, the native pass) the day
   switcher keeps the days round the one shown, so the team's name is never
   cut by it. */
@container (max-width: 300px) {
  .tt-day:first-child, .tt-day:last-child { display: none; }
}
@container (max-width: 240px) {
  .tt-day:not(.is-on) { display: none; }
}
@container (max-width: 520px) {
  .tg { --who: 30px; padding: 0 10px 12px; }
  .tg-name, .tg-book-name { display: none; }
  .tg-hrow > span { padding-left: 2px; font-size: 9px; }
  .tg-b { left: calc(var(--t) * 100% / var(--span) + 1.5px); width: calc(var(--h) * 100% / var(--span) - 3px); border-radius: 4px; }
  .tg-opt, .tg-book { left: calc(var(--t) * 100% / var(--span) + 1px); width: calc(100% / var(--span) - 2px); }
  .tg-opt > b { width: 14px; height: 14px; margin-left: -7px; font-size: 8px; }
  .tt-day { padding: 0 6px; }
}

/* ON A PHONE THE DAY STANDS UP (round 4, David: "optimize the website for
   mobile ... just optimize for native mobile experience"). Nine hour
   columns across a 300px pane are 30px each, too narrow to read, so under
   720 the day is drawn the way a phone calendar draws one: the hours run
   DOWN the left edge, one 28px row each, and the five people stand across
   the top as five columns under their faces. The data and the markup are
   the same; each lane's face and track become cells of one grid (the lane
   itself is display: contents, so the play's per-lane selectors still
   find them), and every block, lit hour and the booked review take their
   --t and --h on the vertical axis. The booked review is a band across all
   five columns at 10:00 with room for its name again, the scan comes DOWN
   the day instead of across it (tm-scan-v), and nothing else in the play
   changes. At 720 and up the day is exactly the desktop's. */
@media (max-width: 719.98px) {
  .tg {
    --hw: 30px; --top: 34px; --rh: 28px;
    display: grid; grid-template-columns: var(--hw) minmax(0, 1fr);
    padding: 0 12px 14px 6px;
  }
  .tg-hours { grid-area: 1 / 1; display: block; height: auto; padding-top: var(--top); }
  .tg-hours > span:first-child { display: none; }
  .tg-hrow { display: grid; grid-template-columns: none; grid-template-rows: repeat(var(--span), var(--rh)); }
  .tg-hrow > span { padding: 0 7px 0 0; margin-top: -5px; text-align: right; font-size: 10px; }
  .tg-body {
    grid-area: 1 / 2; display: grid; grid-auto-flow: column;
    grid-template-columns: repeat(5, minmax(0, 1fr)); grid-template-rows: var(--top) calc(var(--span) * var(--rh));
    grid-auto-rows: auto;
  }
  .tg-lane { display: contents; }
  .tg-who { position: relative; z-index: 1; justify-content: center; align-items: flex-start; padding-top: 2px; }
  .tg-name { display: none; }
  .tg-track {
    z-index: 1;
    background-image: linear-gradient(to bottom, var(--mk-line) 0 1px, transparent 1px);
    background-size: 100% calc(100% / var(--span));
    box-shadow: inset 0 -1px var(--mk-line);
  }
  .tg-b {
    left: 3px; right: 3px; width: auto; bottom: auto;
    top: calc(var(--t) * 100% / var(--span) + 2px); height: calc(var(--h) * 100% / var(--span) - 4px);
    border-radius: 5px;
  }
  .tg-over { top: var(--top); left: 0; right: 0; bottom: 0; }
  .tg-opt, .tg-book {
    left: 1px; right: 1px; width: auto; bottom: auto;
    top: calc(var(--t) * 100% / var(--span) + 1px); height: calc(100% / var(--span) - 2px);
  }
  .tg-opt > b { left: 6px; top: 50%; width: 16px; height: 16px; margin: -8px 0 0; font-size: 9px; }
  .tg-book { flex-direction: row; gap: 7px; }
  .tg-book-name { display: block; font-size: var(--dd-fs-2xs); }
  .tg-scan::before { left: 0; right: 0; top: -1px; bottom: auto; width: auto; height: 2px; }
  .tg-scan::after { left: 0; right: 0; top: auto; bottom: 100%; width: auto; height: 30px; background: linear-gradient(to bottom, transparent, rgb(111 134 224 / .14)); }
}

/* b. context on a client: its three sources as filled rows, then the
   question and the grounded answer. A source lights periwinkle as its
   chip leaves it, in the play. */
.cx-count, .pr-srcs { font-weight: var(--dd-w-medium); }
.cx-in { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 2px 12px 12px; }
.cx-src { flex: none; display: flex; flex-direction: column; gap: 4px; }
.cx-tile {
  position: relative; z-index: 0; min-width: 0;
  display: flex; align-items: center; gap: 9px; min-height: 36px; padding: 5px 10px 5px 8px;
  /* 12px inside the pane's 16px corner: the concentric corner is 4px, which
     the scale floors at small (the details pass; it was medium). */
  border-radius: var(--mk-rs); background: var(--mk-fill);
}
.cx-tile::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  background: var(--mk-peri-wash-2);
  opacity: 0;
}
.cx-ico {
  display: inline-grid; place-items: center; flex: none;
  width: 20px; height: 20px; border-radius: var(--mk-rs);
  background: var(--dd-panel); color: var(--dd-ink-light); box-shadow: var(--mk-chip);
}
.cx-ico svg { width: 13px; height: 13px; stroke-width: 1.8; fill: none; }
.cx-bar { flex: none; align-self: stretch; width: 3px; margin: 2px 8.5px; border-radius: 2px; background: var(--id); }
.cx-tt { flex: 1 1 auto; display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.cx-tt b, .cx-tt span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-tt b { flex: none; max-width: 60%; font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-semibold); color: var(--dd-ink); line-height: 1.35; }
.cx-tt span { min-width: 0; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); line-height: 1.35; }
.cx-when { flex: none; margin-left: auto; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; white-space: nowrap; }
.cx-chat { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 10px; }
.cx-me, .pr-me { align-self: flex-end; }
.cx-next {
  flex: none; display: flex; align-items: center; gap: 7px; margin: 0;
  padding: 6px 6px 6px 10px; border-radius: var(--mk-rs);
  background: var(--mk-peri-wash);
  font-size: var(--dd-fs-xs); font-weight: var(--dd-w-medium); color: var(--dd-ink);
}
.cx-next .dd-ai-btn { height: 26px; border-radius: var(--mk-rs); }
.cx-nextline { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-ans { display: flex; align-items: flex-start; gap: 8px; }
.cx-ans > .av { margin-top: 1px; }
.cx-lines {
  list-style: none; margin: 0; padding: 0; min-width: 0;
  display: flex; flex-direction: column; gap: 5px;
  font-size: var(--dd-fs-sm-); line-height: var(--dd-lh-body); color: var(--dd-ink); text-wrap: pretty;
}
.cx-chip {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: 1px;
  height: 18px; padding: 0 6px; white-space: nowrap;
  border-radius: var(--mk-rs); background: var(--mk-fill);
  font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-medium); line-height: 1; color: var(--dd-ink-light);
}
.cx-chip svg { width: 11px; height: 11px; flex: none; stroke-width: 1.8; fill: none; color: var(--dd-ink-quiet); }
@container (max-width: 440px) {
  .cx-tt span { display: none; }
}
@container (max-width: 340px) {
  .cx-when { display: none; }
}

/* c. the recommendation, which shows its work: three tiers on one filled
   track, the recommended one lifted as the white chip (the selected thing)
   and badged in the agent's periwinkle. Concentric: a 16px track with a
   4px inset holds 12px tiers. */
.pr-in { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: 2px 12px 12px; }
.pr-body { position: relative; flex: 1 1 auto; min-height: 0; }
.pr-think {
  position: absolute; left: 2px; top: 6px; margin: 0;
  display: flex; align-items: center; gap: 6px;
  font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet);
  opacity: 0;
}
/* 12px inside the pane, so small (it was the pane's own large corner, a
   16px curve nested flush-parallel in a 16px one); the tiers inside it
   stand 4px in, so theirs is small too. */
.pr-card { padding: 4px; border-radius: var(--mk-rs); background: var(--mk-fill); }
.pr-head {
  display: flex; align-items: center; gap: 6px; padding: 6px 8px 5px;
  font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-medium);
  text-transform: uppercase; letter-spacing: .07em; color: var(--dd-ink-quiet);
}
.pr-tier {
  position: relative; z-index: 0;
  display: flex; flex-direction: column; gap: 3px; padding: 8px 10px 9px;
  border-radius: var(--mk-rs);
}
.pr-tier + .pr-tier { margin-top: 2px; }
.pr-tier.is-rec::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  background: var(--dd-panel); box-shadow: var(--mk-chip);
}
.pr-l1 { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px; }
.pr-name { font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-bold); color: var(--dd-ink); }
.pr-badge {
  display: inline-flex; align-items: center; height: 18px; padding: 0 7px;
  border-radius: var(--mk-rs); background: var(--mk-peri-wash-2); color: var(--mk-peri-ink);
  font-size: var(--dd-fs-3xs); font-weight: var(--dd-w-bold); letter-spacing: .02em;
}
.pr-price { margin-left: auto; font-size: var(--dd-fs-xs); font-weight: var(--dd-w-semibold); color: var(--dd-ink-light); font-variant-numeric: tabular-nums; }
.pr-why { margin: 0; font-size: var(--dd-fs-xs); line-height: var(--dd-lh-ui); color: var(--dd-ink-quiet); text-wrap: pretty; }
.pr-chip { margin-left: 2px; }
.pr-tier:not(.is-rec) .pr-chip { background: var(--mk-fill-2); }

/* d. manage projects together (round 4 made it a team card; until then it
   was section 4, a section of its own). The best case of one company
   project, drawn as the product's project page (app/src/project/app.css is
   the source of its look): one white pane on the card's ground, like every
   picture on the page, in SPEC3's language (2026-09-24, the declutter pass,
   ProjectPage.tsx says what changed and why). Soft, borderless, filled
   quiet chips, periwinkle only for what the agent made, and air.

   The page is three blocks, the HEAD (the soft mark, the title and its
   code, one meta line, one progress line with one label, the agent's
   sparkle line), the TASKS (one plain head, the open rows with one fact
   each, the Completed line) and a SIDE on a barely-there fill (Mail, Next,
   Connected, parted by space). The pane is its own container and places
   the three by its width:
     - 880 and wider (the whole-row card at 1000 and up): the product's
       two columns, the head over the tasks on the left and the side down
       the right, the two about one height so neither ends in an empty box;
     - 520 to 880 (the same card on a screen from 720 to 1000): the head
       across the top, the tasks and the side side by side under it;
     - under 520 (a phone): one column.

   Rows have FIXED heights, because the one play (THE DEMONSTRATIONS) moves
   them by a pitch: a task row is 38 and its pitch 42, a mail row 44 (pitch
   48) and a connected item 40 (pitch 44).

   THE TASK LIST KEEPS ONE SLOT IN HAND. Before the play the ticked task is
   still an open row and Completed stands a pitch lower; in the play the
   task folds into Completed and Completed rises into its place. So the
   list reserves that one pitch under Completed (its padding) and nothing
   below it moves, the play being transform and opacity only. The ticked
   row is drawn over Completed's resting slot (--pj-at, the count of open
   rows), invisible at rest. */
.pj-win {
  --pj-p: 42px; --pj-mp: 48px; --pj-cp: 44px;
  --pj-pl: clamp(22px, 3.6cqi, 44px); --pj-pr: clamp(16px, 2cqi, 22px);
  display: flex; flex-direction: column;
  container-type: inline-size;
}
.pj-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  height: 54px; padding: 0 calc(var(--pj-pr) + 10px) 0 var(--pj-pl);
}
.pj-crumb { display: flex; align-items: center; gap: 8px; min-width: 0; overflow: hidden; white-space: nowrap; font-size: var(--dd-fs-sm-); color: var(--dd-ink-quiet); }
.pj-crumb .dd-mark { font-size: .9rem; margin-right: 2px; }
.pj-crumb-sep { opacity: .5; }
.pj-share { flex: none; display: flex; align-items: center; gap: 10px; }
/* The people it is shared with, one stack of the page's faces ("A
   PERSON"), a size up in the bar. */
.pj-faces > .face { --face: 22px; }
/* Share is a ghost, the words alone, the page's quietest control. */
.pj-share-btn {
  display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border-radius: var(--mk-rm);
  font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-medium); color: var(--dd-ink-light);
}

.pj-page {
  flex: 1 1 auto;
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(280px, 30%, 336px);
  grid-template-rows: auto 1fr; grid-template-areas: "head side" "tasks side";
  gap: 0 clamp(32px, 4.4cqi, 56px); align-items: start;
  padding: clamp(10px, 1.4cqi, 16px) var(--pj-pr) var(--pj-pr) var(--pj-pl);
}
.pj-head { grid-area: head; min-width: 0; padding-top: 10px; }
.pj-tasks { grid-area: tasks; min-width: 0; }
.pj-side { grid-area: side; }
.pj-titlerow { display: flex; align-items: center; gap: 12px; min-width: 0; }
/* The project's mark, the app's soft one: a quiet filled tile with the
   glyph in ink, not a black square. */
.pj-mark {
  display: inline-grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--mk-rm);
  background: var(--mk-fill); color: var(--dd-ink-light);
}
.pj-mark > svg { width: 19px; height: 19px; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.pj-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1.5rem; font-weight: var(--dd-w-bold); letter-spacing: var(--dd-ls-tighter); line-height: 1.2; color: var(--dd-ink); }
.pj-code { margin-left: -2px; }
.pj-meta { margin: 12px 0 0; font-size: var(--dd-fs-sm-); line-height: 18px; color: var(--dd-ink-quiet); }
/* One calm line and one label. The line is thin and not quite black. */
.pj-progress {
  display: flex; align-items: center; gap: 14px; max-width: 520px;
  margin: 22px 0 0; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.pj-track { position: relative; flex: 1 1 auto; min-width: 80px; height: 4px; border-radius: 2px; background: var(--mk-fill-2); overflow: hidden; }
.pj-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: inherit; background: rgb(17 17 18 / .72); transform-origin: 0 50%; }
.pj-count b { font-weight: var(--dd-w-semibold); color: var(--dd-ink); }
/* The agent's note, the one sentence on the page the agent wrote: its
   sparkle says so, no box. */
.pj-activity {
  display: flex; align-items: center; gap: 8px; margin: 18px 0 0;
  font-size: var(--dd-fs-sm-); color: var(--dd-ink-light); text-wrap: balance;
}
.pj-activity .dd-sugmark { width: 15px; height: 15px; flex: none; }
.pj-activity .dd-sugmark > svg { width: 100%; height: 100%; }
/* A value that changes in the play: the served one, and the one before it
   stacked in the same cell, hidden at rest. */
.pj-swap { display: inline-grid; }
.pj-swap > * { grid-area: 1 / 1; }
.pj-swap-was { opacity: 0; }

/* The rows' washes hang 10px outside the column, so a box stands under the
   project's mark and Tasks under its title. */
.pj-tasks { margin: 34px -10px 0; }
.pj-sechead { font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-semibold); line-height: 18px; color: var(--dd-ink); }
.pj-tasks > .pj-sechead { margin: 0 0 8px 10px; }
.pj-tlist { position: relative; display: flex; flex-direction: column; gap: 4px; padding-bottom: var(--pj-p); }
.pj-task, .pj-doneline {
  position: relative; display: flex; align-items: center; gap: 12px;
  height: 38px; padding: 0 10px; border-radius: var(--mk-rm);
}
.pj-task { z-index: 1; background: var(--dd-panel); font-size: var(--dd-fs-sm); color: var(--dd-ink); }
.pj-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The row's one fact, quiet, at its end. */
.pj-due { flex: none; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pj-fact { display: grid; flex: none; }
.pj-fact > * { grid-area: 1 / 1; justify-self: end; align-self: center; }
.pj-due-was { opacity: 0; }
.pj-link {
  display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 7px;
  border-radius: var(--mk-rs); background: var(--mk-fill);
  font-size: var(--dd-fs-2xs); font-weight: var(--dd-w-medium); color: var(--dd-ink-light); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pj-link img { width: 12px; height: 12px; display: block; }
/* The done tasks, folded to one line, a chevron where a box would be. */
.pj-doneline { font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-medium); color: var(--dd-ink-quiet); }
.pj-chev { position: relative; flex: none; width: 17px; height: 17px; }
.pj-chev::before {
  content: ""; position: absolute; left: 4px; top: 5.5px; width: 5px; height: 5px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg);
}
.pj-moved { position: absolute; left: 0; right: 0; top: calc(var(--pj-at) * var(--pj-p)); z-index: 2; opacity: 0; }
.pj-box { position: relative; display: grid; flex: none; }
.pj-box > * { grid-area: 1 / 1; }
.pj-box-was { opacity: 0; }
/* Hana's face comes onto the webhook task's box in the play, and nowhere
   else: the page's face ("A PERSON"), lifted off the row by a white ring
   and a small shadow while it is there. */
.home-ground .pj-hand {
  position: absolute; left: 19px; top: 50%;
  box-shadow: 0 0 0 2px var(--dd-panel), 0 2px 6px rgb(40 45 70 / .18);
  opacity: 0;
}

.pj-side {
  min-width: 0; display: flex; flex-direction: column; gap: 20px;
  /* The in-pane panel's large corner (a literal 14px before the details
     pass, off the scale); its rows stand 12px in, so theirs is small. */
  padding: 16px 12px 12px; border-radius: var(--mk-rl);
  background: var(--mk-faint);
}
.pj-sec > .pj-sechead { margin: 0 8px 6px; }
.pj-list { position: relative; display: flex; flex-direction: column; gap: 4px; }
.pj-list > * { flex: none; }
/* A box that keeps its length, exactly its shown rows tall, the oldest
   row drawn under the foot and clipped (the play slides it out). */
.pj-mails, .pj-conns { overflow: hidden; }
.pj-mails { height: calc(3 * var(--pj-mp) - 4px); }
.pj-conns { height: calc(3 * var(--pj-cp) - 4px); }
.pj-mail {
  position: relative; z-index: 1; display: flex; flex-direction: column; justify-content: center; gap: 2px;
  height: 44px; padding: 0 8px; border-radius: var(--mk-rs);
}
/* The new mail wears the wash while it lands, then hands it to the PR. */
.pj-mail.pj-new::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--mk-peri-wash); opacity: 0; }
.pj-mail-l1 { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.pj-from { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-medium); color: var(--dd-ink); }
.pj-when { flex: none; font-size: var(--dd-fs-2xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }
.pj-subject { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); }
/* An event: its colour as a small dot, the title, the time. */
.pj-ev { display: flex; align-items: center; gap: 10px; height: 32px; padding: 0 8px; }
.pj-dot { flex: none; width: 7px; height: 7px; margin: 0 4px 0 5px; border-radius: 50%; background: var(--id); }
.pj-ev-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-medium); color: var(--dd-ink); }
.pj-ev-when { flex: none; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); font-variant-numeric: tabular-nums; }
.pj-conn {
  position: relative; z-index: 1; display: flex; align-items: center; gap: 10px;
  height: 40px; padding: 0 8px; border-radius: var(--mk-rs);
}
.pj-conn-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pj-conn-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-medium); color: var(--dd-ink); }
.pj-conn-meta { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--dd-fs-xs); color: var(--dd-ink-quiet); }
.pj-logo { flex: none; width: 16px; height: 16px; margin: 0 1px; display: block; object-fit: contain; }
/* The PR, the last thing that filed itself, is the one row on the wash. */
.pj-conn.pj-new { background: var(--mk-peri-wash); }

/* Narrower (the card on a screen from 720 to 1000), the page stacks: the
   head, the tasks across the pane, and the side under them with its three
   lists side by side, so neither column runs on past the other. */
@container (max-width: 879.98px) {
  .pj-bar, .pj-page { --pj-pl: 20px; --pj-pr: 16px; }
  .pj-page { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; grid-template-areas: "head" "tasks" "side"; padding-top: 8px; }
  .pj-name { font-size: 1.3rem; }
  .pj-tasks { margin-top: 28px; }
  .pj-side {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); align-items: start;
    gap: 18px 14px; margin-top: 4px; padding: 14px 8px 10px;
  }
  .pj-sec > .pj-sechead { margin: 0 6px 6px; }
  .pj-mail, .pj-conn, .pj-ev { padding: 0 6px; }
}
/* Under 460 the bar keeps the team's mark and three faces. */
@container (max-width: 460px) {
  .pj-bar, .pj-page { --pj-pl: 14px; --pj-pr: 12px; }
  .pj-bar { padding-right: calc(var(--pj-pr) - 8px); }
  .pj-crumb > span:not(.dd-mark) { display: none; }
  .pj-faces > .face:nth-child(n + 4) { display: none; }
  .pj-page { padding-top: 6px; }
  .pj-name { white-space: normal; font-size: 1.2rem; }
}
/* THE PHONE'S PROJECT VIEW (round 4, "optimize for native mobile
   experience"). Under 720 the page is what the product's project page is on
   a phone: one column that fits one phone screen and reads top to bottom
   IN THE ORDER THE PLAY HAPPENS. So the side comes up under the head, where
   the agent's note ("Filed 3 threads and linked PR #482 today") points
   at it: the mail that files itself (1.4s) and the PR that links itself
   (3.4s) first, then the tasks, where the PR takes the Apple Pay task's
   date (4.4s) and the ticked task folds into Completed (5.4 to 7.6s), with
   the progress it moves at the top in view the whole time. To fit, the
   head drops its meta line (the faces in the bar say who shares it), Next
   goes (the meetings have the card above to themselves), and Mail and
   Connected each show their two newest rows under a plain head, the way a
   phone previews a list; each box is still exactly its shown rows tall, so
   the newest lands on top and the next slides out at the foot as on the
   desktop. The sections part by space on the pane's white, not on a fill
   of their own. At 720 and up nothing here applies. */
@media (max-width: 719.98px) {
  .pj-bar { height: 48px; }
  .pj-page { grid-template-areas: "head" "side" "tasks"; padding-bottom: 4px; }
  .pj-meta { display: none; }
  .pj-progress { margin-top: 16px; }
  .pj-activity { margin-top: 14px; }
  .pj-side { display: flex; align-items: stretch; margin: 22px -8px 0; gap: 18px; padding: 0; border-radius: 0; background: none; }
  .pj-next { display: none; }
  .pj-sec > .pj-sechead, .pj-tasks > .pj-sechead { margin: 0 8px 6px; }
  .pj-mails { height: calc(2 * var(--pj-mp) - 4px); }
  .pj-conns { height: calc(2 * var(--pj-cp) - 4px); }
  .pj-tasks { margin-top: 22px; }
}

/* ============================================= 5. WORKS WITH YOUR TOOLS
   A band of real marks that reads as endless: four rows of bare marks,
   each row longer than the band and centred, so it runs past both of the
   band's ends, and the band fades out (and softens) towards each end.
   Under it the three other ways in as small filled chips.

   THE BAND KEEPS TO THE CONTENT COLUMN (round 5, David: "keep that within
   the constraints of the two sides. Blur it out before it gets to the
   side, not to the entire side of the web page, just within the content
   area"). Round 4 let this one section span the page; now it is a section
   like every other, and the band is exactly the column the privacy cards
   and the team's cards fill, so its fade finishes where their edges stand
   and the page's margins stay empty.

   THE BAND. Every mark sits in one CELL of the same width, so the rows are
   a true grid, and every other row is pushed half a cell over (its
   padding moves its centre by half of it), which weaves the rows. A row
   is exactly the band's width (its grid track may not grow to fit it) and
   centres marks that overflow it, so it spills past BOTH ends evenly, and
   the band clips them. A mark is drawn in --tl-m square units
   (content/connectors.ts sizes the tiles, discs and word marks from it,
   --w and --h).

   THE FADE is a mask, eased in three steps so it has no visible start,
   clear at each end of the band and at full strength --tl-fade in (a
   share of the band's own width, so it scales with the column rather
   than the screen). THE BLUR rides on the same ends: one layer each side
   that blurs what is behind it, itself masked from full at the end to
   nothing at the fade's inner edge, so the marks go soft as they go
   faint. The band's own mask makes it the backdrop root, so the blur only
   ever sees the marks. Still: nothing here moves. */
.tl-band {
  --tl-m: 32px;
  --tl-cell: 96px;
  --tl-fade: 22%;
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 28px;
  margin: 0;
  padding: 8px 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, rgb(0 0 0 / .22) calc(var(--tl-fade) * .38), rgb(0 0 0 / .72) calc(var(--tl-fade) * .72), #000 var(--tl-fade), #000 calc(100% - var(--tl-fade)), rgb(0 0 0 / .72) calc(100% - var(--tl-fade) * .72), rgb(0 0 0 / .22) calc(100% - var(--tl-fade) * .38), transparent);
  mask-image: linear-gradient(90deg, transparent, rgb(0 0 0 / .22) calc(var(--tl-fade) * .38), rgb(0 0 0 / .72) calc(var(--tl-fade) * .72), #000 var(--tl-fade), #000 calc(100% - var(--tl-fade)), rgb(0 0 0 / .72) calc(100% - var(--tl-fade) * .72), rgb(0 0 0 / .22) calc(100% - var(--tl-fade) * .38), transparent);
}
.tl-band::before, .tl-band::after {
  content: ""; position: absolute; z-index: 1; top: 0; bottom: 0; width: var(--tl-fade);
  pointer-events: none;
  -webkit-backdrop-filter: blur(2.5px);
  backdrop-filter: blur(2.5px);
}
.tl-band::before { left: 0; -webkit-mask-image: linear-gradient(90deg, #000, transparent); mask-image: linear-gradient(90deg, #000, transparent); }
.tl-band::after { right: 0; -webkit-mask-image: linear-gradient(270deg, #000, transparent); mask-image: linear-gradient(270deg, #000, transparent); }
.tl-row {
  list-style: none; margin: 0; padding: 0;
  display: flex; justify-content: center; align-items: center;
}
.tl-row:nth-child(even) { padding-left: var(--tl-cell); }
.tl-mark { flex: none; display: grid; place-items: center; width: var(--tl-cell); height: var(--tl-m); }
.tl-mark img {
  display: block; object-fit: contain;
  width: calc(var(--tl-m) * var(--w, 1)); height: calc(var(--tl-m) * var(--h, 1));
}
/* The Apple icons are white squircles: on a white page they need the
   faint edge a phone's home screen gives them, drawn from their own
   shape, never a tile behind them. */
.tl-edge img { filter: drop-shadow(0 0 .5px rgb(17 17 18 / .32)) drop-shadow(0 1px 2px rgb(40 45 70 / .10)); }

/* THE WAYS IN, the dark site's three chips in the light treatment: a
   quiet fill, no edge and no shadow, the glyph in periwinkle, the words
   in the page's Inter; centred in one row, wrapping as a group. */
.tl-ways {
  list-style: none; margin: clamp(28px, 3vw, 40px) auto 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
}
.tl-way {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 40px; padding: 8px 16px 8px 14px;
  border-radius: var(--mk-rm); background: var(--mk-fill);
  font-size: var(--dd-fs-sm); font-weight: var(--dd-w-medium); line-height: 1.3; color: var(--dd-ink);
  text-align: left;
}
.tl-way svg { display: block; flex: none; width: 16px; height: 16px; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; color: var(--mk-peri); }

.sec-ico {
  display: grid; place-items: center; flex: none; width: 36px; height: 36px;
  border-radius: var(--mk-rm); background: var(--dd-panel); box-shadow: var(--mk-chip); color: var(--dd-ink-light);
}
.sec-ico svg { display: block; width: 18px; height: 18px; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; fill: none; }

/* ============================================== 6. PRIVATE BY DEFAULT
   Round 4: the old dark security section's shape (ref 17: badges, a 4 by
   2 grid of commitments, a panel for larger teams) in this page's light
   language. White page, two ground cards like the pictures' (#f5f5f3,
   radius 24, no edge, no shadow), faint alpha hairlines only where they
   part the grid's cells, filled quiet pieces, and periwinkle as the one
   colour note (the shields, the glyphs, the ticks). The heading is the
   page's serif; everything else is Inter.

   THE STANDARDS are filled chips (ink at 4 percent on the white page,
   radius 10) holding a small periwinkle shield and the word in ink. They
   wrap, centred, on a narrow screen. */
.sec-std {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
}
.sec-std li {
  display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 13px 0 11px; border-radius: var(--mk-rm); background: var(--mk-fill);
  font-size: var(--dd-fs-sm); font-weight: var(--dd-w-semibold); color: var(--dd-ink); white-space: nowrap;
}
.sec-shield { display: block; flex: none; width: 15px; height: 15px; color: var(--mk-peri); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* THE COMMITMENTS, one ground card cut into eight cells. The cells meet
   with no gap, and each draws ONE hairline up and one to its left (a box
   shadow offset by -1px, which paints only outside the cell); the card
   clips, so the lines along its own edges fall away and only the lines
   BETWEEN cells show, whatever the column count. Each cell is its glyph on
   a small white tile (the tools section's tile, periwinkle ink), then the
   name, then its one sentence. Four across, two under 860. */
.sec-grid {
  list-style: none; margin: clamp(24px, 2.6vw, 32px) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  border-radius: var(--mk-rx); background: var(--mk-ground); overflow: hidden;
  text-align: left;
}
.sec-item {
  display: flex; flex-direction: column; min-width: 0;
  padding: clamp(22px, 2.3vw, 32px) clamp(20px, 2.1vw, 30px) clamp(24px, 2.5vw, 34px);
  box-shadow: -1px -1px 0 var(--mk-line);
}
.sec-ico { margin-bottom: clamp(16px, 1.5vw, 20px); color: var(--mk-peri); }
.sec-name { margin: 0; font-size: var(--dd-fs-md); font-weight: var(--dd-w-semibold); line-height: 1.35; letter-spacing: -.006em; color: var(--dd-ink); }
.sec-say { margin: 5px 0 0; font-size: var(--dd-fs-sm); line-height: var(--dd-lh-body); color: var(--dd-ink-quiet); text-wrap: pretty; }

/* THE PANEL FOR LARGER TEAMS, the second ground card. On the left its
   shield, a serif title at the cards' title size, one line and the page's
   one button (secondary: the panel with a hairline, flat); on the right the
   ten things a review asks for, two columns of five read row by row, each
   after a small periwinkle tick. Stacked under 1000 (the list's longest
   item keeps to one line down to there), one column of items on a
   phone. */
.sec-teams {
  margin-top: clamp(12px, 1.2vw, 16px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 28px clamp(28px, 4vw, 64px); align-items: center;
  padding: clamp(28px, 3.2vw, 44px) clamp(24px, 3.4vw, 48px);
  border-radius: var(--mk-rx); background: var(--mk-ground);
  text-align: left;
}
.sec-teams-head { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
/* The shield's drawing sits 5px inside its box; the negative margin lines its
   ink up with the title's left edge. */
.sec-teams-mark { display: block; width: 30px; height: 30px; margin: 0 0 18px -5px; color: var(--mk-peri); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.sec-teams-title {
  margin: 0; font-family: var(--home-font-display); font-feature-settings: var(--home-feat-display); font-synthesis: none;
  font-size: var(--home-h3-size); font-weight: var(--home-h3-w); letter-spacing: var(--home-h3-ls); line-height: var(--home-h3-lh);
  color: var(--dd-ink);
}
.sec-teams-line { margin: 8px 0 0; font-size: var(--dd-fs-md); line-height: var(--dd-lh-body); color: var(--dd-ink-quiet); text-wrap: pretty; }
.home-body .sec-talk { margin-top: 22px; }
.sec-ent {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px clamp(20px, 2.4vw, 36px);
  font-size: var(--dd-fs-sm); line-height: 1.4; color: var(--dd-ink-light);
}
.sec-ent li { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.sec-ent li::before {
  content: ""; width: 12px; height: 12px; flex: none; align-self: center; background: var(--mk-peri);
  -webkit-mask: var(--dd-tick) center / 12px 12px no-repeat; mask: var(--dd-tick) center / 12px 12px no-repeat;
}

/* PRIVACY ON NARROWER SCREENS, kept here with the section rather than in
   the page's shared breakpoints at the foot, so the section reads whole.
   Under 1000 the panel's head stands over its list; under 860 the
   commitments go two across. */
@media (max-width: 999.98px) {
  .sec-teams { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 859.98px) {
  .sec-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* ON A PHONE (under 720) the section is designed for a thumb, not
   squeezed from the desktop:
     - the badges are a small cloud, a size down, held to a width that
       always breaks them three over two, centred, from 360 to 719;
     - the commitments are ONE list on the card, a native settings list:
       each row its tile at the left, the name and its sentence beside it,
       a hairline between rows (the same one-line-up trick);
     - the panel stacks as a phone sheet does: the shield, the title and its
       line, the ten items in one column, then "Talk to us" last and the
       full width of the card, where a thumb ends up. The head's box steps
       aside (display: contents) so its button can be ordered after the
       list. */
@media (max-width: 719.98px) {
  .sec-std { max-width: 340px; margin-inline: auto; gap: 6px; }
  .sec-std li { height: 30px; gap: 6px; padding: 0 11px 0 9px; font-size: var(--dd-fs-sm-); }
  .sec-shield { width: 14px; height: 14px; }
  .sec-grid { grid-template-columns: minmax(0, 1fr); margin-top: 24px; }
  .sec-item {
    display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 14px; align-items: start;
    padding: 16px 18px 17px;
  }
  .sec-ico { grid-row: 1 / span 2; margin: 1px 0 0; width: 34px; height: 34px; }
  .sec-name { font-size: .9375rem; }
  .sec-say { margin-top: 2px; font-size: var(--dd-fs-sm-); }
  /* The sides and foot at the card's own corner radius, so the full-width
     button's corner is never inside the card's curve (it stood 20px in
     under 24). */
  .sec-teams { display: flex; flex-direction: column; align-items: stretch; gap: 0; padding: 26px var(--mk-rx) var(--mk-rx); }
  .sec-teams-head { display: contents; }
  .sec-teams-mark { align-self: flex-start; width: 26px; height: 26px; margin: 0 0 14px -4px; }
  .sec-ent { order: 1; grid-template-columns: minmax(0, 1fr); gap: 12px; margin-top: 22px; }
  .home-body .sec-talk { order: 2; width: 100%; margin-top: 24px; }
}

/* ================================================= THE DEMONSTRATIONS
   The product pictures below the hero that show a job being done play it
   ONCE (David: "instead of it looping, the animations will play once you
   scroll to that part"). Each is one timeline of transform and opacity,
   at the pace it had as a loop, and the rules here only exist where the
   head script marked <html> demo-js (motion welcome, and the browser can
   tell when a picture is seen) and motion is still welcome now.

   THE FIRST FRAME, THEN ONE PLAY, THEN STILL. Every animation is attached
   paused until its picture carries .is-play (usePlayOnce.ts), and fills
   both ways, so before the play the picture stands at its first keyframe:
   a real piece of the app before the job (the email before the replies,
   Priya's week before the team is read). Each keyframe list stops where
   its story does and names no 100% frame, so the last stretch runs into
   the element's own resting style, which is the finished state the markup
   draws; nothing loops, nothing fades back, and scrolling away and back
   does not restart it. With no demo-js, none of this exists and every
   picture stands finished. The cards themselves never move. */
@media (prefers-reduced-motion: no-preference) {
  /* a. the replies, 8s. The three rise 0.6s, the first is picked 2.7s (a
     press, then its wash), the other two step back 3.2s, sent 4.2s. */
  @keyframes sr-opt { 0%, 7% { opacity: 0; transform: translateY(6px); } 13%, 38% { opacity: 1; transform: none; } 44% { opacity: .45; transform: none; } }
  @keyframes sr-pick { 0%, 7% { opacity: 0; transform: translateY(6px); } 13%, 33% { opacity: 1; transform: none; } 35% { transform: scale(.97); } 39% { opacity: 1; transform: none; } }
  @keyframes sr-wash { 0%, 34% { opacity: 0; } 38% { opacity: 1; } }
  @keyframes sr-sent { 0%, 50% { opacity: 0; transform: translateY(6px); } 56% { opacity: 1; transform: none; } }
  html.demo-js .sr-opt { animation: sr-opt 8s var(--dd-ease-glide) both; animation-delay: calc(var(--n) * 110ms); }
  html.demo-js .sr-opt.is-pick { animation-name: sr-pick; }
  html.demo-js .sr-opt.is-pick::before { animation: sr-wash 8s var(--dd-ease) both; }
  html.demo-js .sr-sent { animation: sr-sent 8s var(--dd-ease-glide) both; }

  /* b. the meeting, 8.5s. The ask lights 0.4s, the travel lands 1.9s, the
     slot drops in 2.6s, the reply and the reason 3.3s. */
  @keyframes sc-ask { 0%, 4% { opacity: 0; } 12%, 30% { opacity: 1; } 40% { opacity: .7; } }
  @keyframes sc-trav { 0%, 21% { opacity: 0; transform: scaleY(.6); } 27% { opacity: 1; transform: none; } }
  @keyframes sc-drop { 0%, 29% { opacity: 0; transform: translateY(-8px) scale(.97); } 36% { opacity: 1; transform: none; } }
  @keyframes sc-why { 0%, 38% { opacity: 0; transform: translateY(4px); } 44% { opacity: 1; transform: none; } }
  html.demo-js .sc-ask::before { animation: sc-ask 8.5s var(--dd-ease) both; }
  html.demo-js .sc-trav { animation: sc-trav 8.5s var(--dd-ease-glide) both; animation-delay: calc(var(--n) * 120ms); }
  html.demo-js .sc-sug { animation: sc-drop 8.5s var(--dd-ease-glide) both; }
  html.demo-js :is(.sc-why > *, .sc-reply) { animation: sc-why 8.5s var(--dd-ease-glide) both; }

  /* c. the to-dos, 9s. The invoice's to-do lands under the three old rows
     0.5s, the note's under it 1.3s, and at 2.7s the list sorts itself (the
     old rows step down two, the new ones climb), then the line under it. */
  @keyframes st-a {
    0%, 5% { opacity: 0; transform: translateY(calc(var(--from) * var(--pitch) + 6px)); }
    10%, 30% { opacity: 1; transform: translateY(calc(var(--from) * var(--pitch))); }
    38% { opacity: 1; transform: none; }
  }
  @keyframes st-b {
    0%, 14% { opacity: 0; transform: translateY(calc(var(--from) * var(--pitch) + 6px)); }
    19%, 30% { opacity: 1; transform: translateY(calc(var(--from) * var(--pitch))); }
    38% { opacity: 1; transform: none; }
  }
  @keyframes st-old { 0%, 30% { transform: translateY(calc(var(--from) * var(--pitch))); } 38% { transform: none; } }
  @keyframes st-note { 0%, 40% { opacity: 0; } 45% { opacity: 1; } }
  html.demo-js .st-row { animation: st-old 9s var(--dd-ease-glide) both; }
  html.demo-js .st-row.st-new { animation-name: st-b; }
  html.demo-js .st-row.st-new + .st-new { animation-name: st-a; }
  html.demo-js .st-note { animation: st-note 9s var(--dd-ease) both; }

  /* d. the project, 14s. The new mail lands 1.4s on the wash while the
     oldest thread slides out at the box's foot. The PR lands 3.4s and the
     wash passes to it; at 4.4s the Apple Pay task's date gives way to the
     PR. Hana's face comes onto the webhook task at 5.4s, the box ticks
     6.2s, and from 7.0s the task folds into Completed as Completed rises
     into its place. The progress goes from 2 to 3 of 7 by 8.7s. */
  html.demo-js .pj-mails > :not(.pj-new) { --pj-by: var(--pj-mp); animation: pj-room-a 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-mail.pj-new { animation: pj-land-a 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-mail.pj-new::before { animation: pj-wash-out 14s var(--dd-ease) both; }
  html.demo-js .pj-conns > :not(.pj-new) { --pj-by: var(--pj-cp); animation: pj-room-b 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-conn.pj-new { animation: pj-land-b 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-due-was { animation: pj-date-out 14s var(--dd-ease) both; }
  html.demo-js .pj-linked { animation: pj-linked 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-hand { animation: pj-hand 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-moved .pj-box > .check-face.is-on { animation: pj-tick 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-moved .pj-box-was { animation: pj-untick 14s var(--dd-ease) both; }
  html.demo-js .pj-moved { animation: pj-fold 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-doneline { animation: pj-make-way 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-fill { animation: pj-fill 14s var(--dd-ease-glide) both; }
  html.demo-js .pj-count .pj-swap-was { animation: pj-was 14s var(--dd-ease) both; }
  html.demo-js .pj-count .pj-swap-now { animation: pj-now 14s var(--dd-ease) both; }
  @keyframes pj-room-a { 0%, 5% { transform: translateY(calc(-1 * var(--pj-by))); } 11% { transform: none; } }
  @keyframes pj-land-a { 0%, 8% { opacity: 0; transform: translateY(-10px) scale(.98); } 14% { opacity: 1; transform: none; } }
  @keyframes pj-wash-out { 0%, 24% { opacity: 1; } 29% { opacity: 0; } }
  @keyframes pj-room-b { 0%, 16% { transform: translateY(calc(-1 * var(--pj-by))); } 22% { transform: none; } }
  @keyframes pj-land-b { 0%, 19% { opacity: 0; transform: translateY(-10px) scale(.98); } 25% { opacity: 1; transform: none; } }
  /* The PR arrives on the Apple Pay task it belongs to, in its date's
     place, just after it lands in Connected. */
  @keyframes pj-date-out { 0%, 30% { opacity: 1; } 32% { opacity: 0; } }
  @keyframes pj-linked { 0%, 31% { opacity: 0; transform: scale(.6); } 35% { opacity: 1; transform: none; } }
  /* The ticked task stands in the slot above Completed until it folds:
     it fades and sinks a little into the line, which rises a pitch into
     the slot it leaves. Its resting style is invisible, so the last
     stretch runs out unseen. */
  @keyframes pj-hand { 0%, 36% { opacity: 0; transform: translateY(8px) scale(.8); } 40%, 45% { opacity: 1; transform: none; } 49% { opacity: 0; transform: none; } }
  @keyframes pj-tick { 0%, 43% { opacity: 0; transform: scale(.5); } 46% { opacity: 1; transform: none; } }
  @keyframes pj-untick { 0%, 44% { opacity: 1; } 46% { opacity: 0; } }
  @keyframes pj-fold { 0%, 50% { opacity: 1; transform: none; } 55% { opacity: 0; transform: translateY(10px) scale(.98); } }
  @keyframes pj-make-way { 0%, 51% { transform: translateY(var(--pj-p)); } 58% { transform: none; } }
  @keyframes pj-fill { 0%, 56% { transform: scaleX(var(--pj-was)); } 63% { transform: none; } }
  @keyframes pj-was { 0%, 58% { opacity: 1; } 60% { opacity: 0; } }
  @keyframes pj-now { 0%, 58% { opacity: 0; } 60% { opacity: 1; } }

  /* e. a time everyone's free, ONE 10s TIMELINE, every element on the same
     clock (a smooth ease-out, moves of 200 to 400ms, a small blur on the
     way in). Priya types 0.3 to 2.0s and sends 2.1s; the bubble lifts
     2.3s and the agent answers "Reading 5 calendars" 2.8s. The lanes are
     read 3.0 to 4.6s, one every 320ms (the ring on the face, its blocks up
     from faint, "1 of 5" to "5 of 5"). The scan crosses the day 4.8 to
     6.0s and each hour that works lights as it passes (10:00 at 5.0s,
     14:00 at 5.5s, 16:00 at 5.8s). The finding and the ranked list rise
     6.2s, the first is chosen 7.0s, the other two columns go 7.0s, the
     first condenses into the booked review 7.6s, and "Booked. Invites
     sent to 5" lands 8.4s with the five faces after it. Percentages are
     those times over 10s. */
  @keyframes tm-ph { 0%, 2.5% { opacity: 1; } 3%, 22% { opacity: 0; } 23.5% { opacity: 1; } }
  @keyframes tm-typed { 0%, 2.9% { opacity: 0; } 3%, 21.5% { opacity: 1; } 22.5% { opacity: 0; } }
  @keyframes tm-ch { 0%, 3% { opacity: 0; display: none; } 3.4% { opacity: 1; display: inline; } }
  @keyframes tm-send { 0%, 20% { opacity: 0; } 21%, 22.5% { opacity: 1; } 24% { opacity: 0; } }
  @keyframes tm-me { 0%, 22.5% { opacity: 0; transform: translateY(12px); filter: blur(4px); } 26% { opacity: 1; transform: none; filter: blur(0); } }
  @keyframes tm-reply { 0%, 27.5% { opacity: 0; transform: translateY(6px); filter: blur(3px); } 30.5% { opacity: 1; transform: none; filter: blur(0); } }
  @keyframes tm-stat {
    0%, 30% { opacity: 1; } 34% { opacity: .45; } 38% { opacity: 1; } 42% { opacity: .45; } 46% { opacity: 1; }
    50% { opacity: .45; } 54% { opacity: 1; } 60% { opacity: 1; } 62% { opacity: 0; }
  }
  @keyframes tm-found { 0%, 61.5% { opacity: 0; transform: translateY(4px); } 64.5% { opacity: 1; transform: none; } }
  @keyframes tm-tk0 { 0%, 30% { opacity: 0; transform: translateY(4px); } 31%, 32.6% { opacity: 1; transform: none; } 33.2% { opacity: 0; transform: translateY(-4px); } }
  @keyframes tm-tk1 { 0%, 33.2% { opacity: 0; transform: translateY(4px); } 34.2%, 35.8% { opacity: 1; transform: none; } 36.4% { opacity: 0; transform: translateY(-4px); } }
  @keyframes tm-tk2 { 0%, 36.4% { opacity: 0; transform: translateY(4px); } 37.4%, 39% { opacity: 1; transform: none; } 39.6% { opacity: 0; transform: translateY(-4px); } }
  @keyframes tm-tk3 { 0%, 39.6% { opacity: 0; transform: translateY(4px); } 40.6%, 42.2% { opacity: 1; transform: none; } 42.8% { opacity: 0; transform: translateY(-4px); } }
  @keyframes tm-tk4 { 0%, 42.8% { opacity: 0; transform: translateY(4px); } 43.8%, 60% { opacity: 1; transform: none; } 62% { opacity: 0; transform: none; } }
  @keyframes tm-ring0 { 0%, 30% { opacity: 0; transform: scale(.7); } 31%, 32% { opacity: 1; transform: none; } 33.2% { opacity: 0; transform: scale(1.15); } }
  @keyframes tm-ring1 { 0%, 33.2% { opacity: 0; transform: scale(.7); } 34.2%, 35.2% { opacity: 1; transform: none; } 36.4% { opacity: 0; transform: scale(1.15); } }
  @keyframes tm-ring2 { 0%, 36.4% { opacity: 0; transform: scale(.7); } 37.4%, 38.4% { opacity: 1; transform: none; } 39.6% { opacity: 0; transform: scale(1.15); } }
  @keyframes tm-ring3 { 0%, 39.6% { opacity: 0; transform: scale(.7); } 40.6%, 41.6% { opacity: 1; transform: none; } 42.8% { opacity: 0; transform: scale(1.15); } }
  @keyframes tm-ring4 { 0%, 42.8% { opacity: 0; transform: scale(.7); } 43.8%, 44.8% { opacity: 1; transform: none; } 46% { opacity: 0; transform: scale(1.15); } }
  @keyframes tm-read0 { 0%, 30% { opacity: .3; } 32.5% { opacity: 1; } }
  @keyframes tm-read1 { 0%, 33.2% { opacity: .3; } 35.7% { opacity: 1; } }
  @keyframes tm-read2 { 0%, 36.4% { opacity: .3; } 38.9% { opacity: 1; } }
  @keyframes tm-read3 { 0%, 39.6% { opacity: .3; } 42.1% { opacity: 1; } }
  @keyframes tm-read4 { 0%, 42.8% { opacity: .3; } 45.3% { opacity: 1; } }
  @keyframes tm-scan { 0%, 47% { opacity: 0; transform: translateX(0); } 48% { opacity: 1; transform: translateX(0); } 60% { opacity: 1; transform: translateX(100%); } 61.5% { opacity: 0; transform: translateX(100%); } }
  @keyframes tm-opt1 { 0%, 49.5% { opacity: 0; transform: scaleY(.9); } 52%, 76% { opacity: 1; transform: none; } 78.5% { opacity: 0; transform: none; } }
  @keyframes tm-opt2 { 0%, 54.8% { opacity: 0; transform: scaleY(.9); } 57.3%, 70% { opacity: 1; transform: none; } 73% { opacity: 0; transform: none; } }
  @keyframes tm-opt3 { 0%, 57.5% { opacity: 0; transform: scaleY(.9); } 60%, 70% { opacity: 1; transform: none; } 73% { opacity: 0; transform: none; } }
  @keyframes tm-list { 0%, 62% { opacity: 0; transform: translateY(6px); filter: blur(3px); } 65.5% { opacity: 1; transform: none; filter: blur(0); } }
  @keyframes tm-pick { 0%, 70% { opacity: 0; transform: scale(.96); } 72.5% { opacity: 1; transform: none; } }
  @keyframes tm-press { 0%, 70% { transform: none; } 71% { transform: scale(.97); } 72.5% { transform: none; } }
  @keyframes tm-book { 0%, 76% { opacity: 0; transform: scaleY(.7); } 78.5% { opacity: 1; transform: scaleY(1.015); } 80% { opacity: 1; transform: none; } }
  @keyframes tm-bookin { 0%, 78% { opacity: 0; transform: translateY(4px); } 80.5% { opacity: 1; transform: none; } }
  @keyframes tm-booked { 0%, 83.5% { opacity: 0; transform: translateY(6px); } 86.5% { opacity: 1; transform: none; } }
  @keyframes tm-face { 0%, 85% { opacity: 0; transform: scale(.6); } 87.5% { opacity: 1; transform: none; } }
  html.demo-js .tt-ph { animation: tm-ph 10s linear both; }
  html.demo-js .tt-typed { animation: tm-typed 10s linear both; }
  html.demo-js .tt-typed span { animation: tm-ch 10s linear both; animation-delay: calc(var(--c) * 36ms); }
  html.demo-js .tt-comp .vx-composer-send::before { animation: tm-send 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-me { animation: tm-me 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-reply { animation: tm-reply 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-stat { animation: tm-stat 10s ease-in-out both; }
  html.demo-js .tt-found { animation: tm-found 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-tk:nth-child(1) { animation: tm-tk0 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-tk:nth-child(2) { animation: tm-tk1 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-tk:nth-child(3) { animation: tm-tk2 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-tk:nth-child(4) { animation: tm-tk3 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-tk:nth-child(5) { animation: tm-tk4 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(1) .tg-who .face::after { animation: tm-ring0 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(2) .tg-who .face::after { animation: tm-ring1 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(3) .tg-who .face::after { animation: tm-ring2 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(4) .tg-who .face::after { animation: tm-ring3 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(5) .tg-who .face::after { animation: tm-ring4 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(1) .tg-track { animation: tm-read0 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(2) .tg-track { animation: tm-read1 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(3) .tg-track { animation: tm-read2 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(4) .tg-track { animation: tm-read3 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-lane:nth-child(5) .tg-track { animation: tm-read4 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-scan { animation: tm-scan 10s linear both; }
  /* The phone's day stands up, so its scan comes down it (THE DAY STANDS
     UP): the same beats on the other axis. */
  @keyframes tm-scan-v { 0%, 47% { opacity: 0; transform: translateY(0); } 48% { opacity: 1; transform: translateY(0); } 60% { opacity: 1; transform: translateY(100%); } 61.5% { opacity: 0; transform: translateY(100%); } }
  @media (max-width: 719.98px) { html.demo-js .tg-scan { animation-name: tm-scan-v; } }
  /* THE PHONE'S HOLD (behaviours/useHoldOnPhone.ts): the time card and the
     project card stay at their first frame on a phone until most of their
     picture is on screen, even once they are .is-play. */
  html.demo-js .fc.is-held *,
  html.demo-js .fc.is-held *::before,
  html.demo-js .fc.is-held *::after { animation-play-state: paused !important; }
  html.demo-js .tg-opt[data-rank="1"] { animation: tm-opt1 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-opt[data-rank="2"] { animation: tm-opt2 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-opt[data-rank="3"] { animation: tm-opt3 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-opts { animation: tm-list 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-opt.is-pick::before { animation: tm-pick 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-opt.is-pick { animation: tm-press 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-book { animation: tm-book 10s var(--dd-ease-glide) both; }
  html.demo-js .tg-book > * { animation: tm-bookin 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-booked { animation: tm-booked 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-faces .face { animation: tm-face 10s var(--dd-ease-glide) both; }
  html.demo-js .tt-faces .face:nth-child(2) { animation-delay: 70ms; }
  html.demo-js .tt-faces .face:nth-child(3) { animation-delay: 140ms; }
  html.demo-js .tt-faces .face:nth-child(4) { animation-delay: 210ms; }
  html.demo-js .tt-faces .face:nth-child(5) { animation-delay: 280ms; }

  /* f. the client, 7s. Asked 0.35s, three lines stream 1.0s, each chip
     leaves its source 1.7s (its source lights as it goes), and the next
     step it recommends lands last, 3.2s. */
  @keyframes cx-me { 0%, 5% { opacity: 0; transform: translateY(8px); } 10% { opacity: 1; transform: none; } }
  @keyframes cx-line { 0%, 14% { opacity: 0; transform: translateY(6px); } 19% { opacity: 1; transform: none; } }
  @keyframes cx-fly { 0%, 24% { opacity: 0; transform: translate(var(--fx, 0px), var(--fy, 0px)) scale(.9); } 29% { opacity: 1; } 36% { opacity: 1; transform: none; } }
  @keyframes cx-glow { 0%, 20% { opacity: 0; } 24%, 32% { opacity: 1; } 44% { opacity: 0; } }
  @keyframes cx-next { 0%, 44% { opacity: 0; transform: translateY(6px); } 50% { opacity: 1; transform: none; } }
  html.demo-js .cx-me { animation: cx-me 7s var(--dd-ease-glide) both; }
  html.demo-js .cx-line { animation: cx-line 7s var(--dd-ease-glide) both; animation-delay: calc(var(--n) * 140ms); }
  html.demo-js .cx .cx-chip { animation: cx-fly 7s var(--dd-ease-glide) both; animation-delay: calc(var(--n) * 220ms); }
  html.demo-js .cx-tile::before { animation: cx-glow 7s var(--dd-ease) both; animation-delay: calc(var(--n) * 220ms); }
  html.demo-js .cx-next { animation: cx-next 7s var(--dd-ease-glide) both; }

  /* g. the pricing call, 8s. It opens on the question; a moment reading
     0.8s, the card and its three tiers rise 1.7s, their reasons land 2.4s,
     Recommended is marked 3.4s. */
  @keyframes pr-think { 0%, 9% { opacity: 0; } 12% { opacity: 1; } 15.5% { opacity: .45; } 19% { opacity: 1; } 22% { opacity: 0; } }
  @keyframes pr-rise { 0%, 20% { opacity: 0; transform: translateY(6px); } 25% { opacity: 1; transform: none; } }
  @keyframes pr-tier { 0%, 22% { opacity: 0; transform: translateY(3px); } 27% { opacity: 1; transform: none; } }
  @keyframes pr-why { 0%, 30% { opacity: .35; } 34% { opacity: 1; } }
  @keyframes pr-rec { 0%, 42% { opacity: 0; } 47% { opacity: 1; } }
  @keyframes pr-badge { 0%, 43% { opacity: 0; transform: scale(.85); } 48% { opacity: 1; transform: none; } }
  html.demo-js .pr-think { animation: pr-think 8s var(--dd-ease) both; }
  html.demo-js .pr-card { animation: pr-rise 8s var(--dd-ease-glide) both; }
  html.demo-js .pr-tier { animation: pr-tier 8s var(--dd-ease-glide) both; animation-delay: calc(var(--n) * 120ms); }
  html.demo-js .pr-why { animation: pr-why 8s var(--dd-ease) both; animation-delay: calc(var(--n) * 120ms); }
  html.demo-js .pr-tier.is-rec::before { animation: pr-rec 8s var(--dd-ease) both; animation-delay: 240ms; }
  html.demo-js .pr-badge { animation: pr-badge 8s var(--dd-ease-glide) both; animation-delay: 240ms; }

  /* THE WAIT. Every rule above sets the animation shorthand, which resets
     the play state to running, and some of them are more specific than any
     one rule could be here (a moved task's tick, a group's head), so the
     wait is the one !important in this sheet: until its picture is seen,
     nothing in it runs. Spelled out three times because :is() cannot hold a
     pseudo-element, and the ::before and ::after layers (a reply's wash, a
     lit source, a face's ring) have to wait as well. */
  html.demo-js .fc:not(.is-play) *,
  html.demo-js .fc:not(.is-play) *::before,
  html.demo-js .fc:not(.is-play) *::after { animation-play-state: paused !important; }
}

/* ======================================================= 7. THE CLOSE
   Tab's last screen: one headline and one line, then a card in the middle
   of the glow holding the waitlist form, then the footer.

   THE CARD LETS THE GLOW THROUGH, as tab.bot's waitlist card does: white at
   68 percent over the page, Tab's 9 percent ink edge, the 24px corner and
   Tab's blue-slate card haze. The dome is placed (THE GLOW AT THE FOOT) so
   its periwinkle rim passes behind the card's lower half, which reads as a
   soft blue tint rising into the card rather than a slab of colour. No
   backdrop-filter: the glow is blurred already, and a blur on a surface the
   page scrolls over costs frames for nothing. The field and the button stay
   opaque. */
/* The close stands the page's one section gap under privacy, and its card
   stands the same gap over the footer's row (round 4, David: "there should
   be more spacing between the form field and the footer, if not the same
   spacing as it is from the private by default section to that section"):
   two --home-sec-pad, less the footer's own 18px above its row. The glow
   is placed from the same number (THE GLOW AT THE FOOT), so the arc still
   crosses the card. */
.home-end { padding-bottom: calc(2 * var(--home-sec-pad) - 18px); }
.end-card {
  width: min(420px, 100%); margin: 0 auto;
  padding: clamp(24px, 2.6vw, 32px);
  border: 1px solid var(--home-edge); border-radius: var(--dd-radius-xl);
  background: rgb(255 255 255 / .68);
  box-shadow: 0 24px 70px rgb(60 78 135 / .11);
  text-align: left;
}

/* THE FORM. The field is the spec's one input at the page's large size (44
   tall, radius 12): the panel, a hairline, no shadow; the hairline darkens
   on hover and goes ink-quiet on focus, never a ring. The note under it is
   always there and holds one line, so a message moves nothing. The ask and
   the confirmation share one grid cell and swap by visibility, and so do
   the button's two faces, so neither answer changes a height. */
.wl-stack { display: grid; }
.wl-stack > * { grid-area: 1 / 1; min-width: 0; }
.wl-ask[data-on="false"], .wl-done[data-on="false"] { visibility: hidden; }
/* THE SWAPS CROSS-FADE (the audit of 2026-09-26; they used to cut). The
   answer going leaves at once, a pop's length (--dd-dur-pop) with a 3px
   drop, and is hidden once it has faded; the one coming arrives after it
   in the same time, the app's text swap (.dd-swap in shared/auth.css)
   without the blur. The button's two faces trade this way, and so do the
   form and its confirmation. Under reduced motion shared/auth.css stops
   every transition, and each simply cuts. */
.wl-stack > *, .wl-go > .wl-face {
  transition: opacity var(--dd-dur-pop) var(--dd-ease) var(--dd-dur-pop), transform var(--dd-dur-pop) var(--dd-ease) var(--dd-dur-pop), visibility 0s linear 0s;
}
.wl-stack > [data-on="false"], .wl-go > .wl-face[data-on="false"] {
  opacity: 0; transform: translateY(3px);
  transition-delay: 0s, 0s, var(--dd-dur-pop);
}
.wl-label { display: block; margin: 0 0 8px; font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-bold); color: var(--dd-ink); }
.wl-label-2 { margin-top: 14px; }
.wl-input {
  display: block; width: 100%; height: 44px; margin: 0; padding: 0 14px;
  border: 1px solid var(--dd-border); border-radius: var(--home-radius-ctl);
  background: var(--dd-panel); color: var(--dd-ink); box-shadow: none; outline: none;
  font: inherit; font-size: var(--dd-fs-md);
  transition: border-color var(--dd-dur) var(--dd-ease), box-shadow var(--dd-dur) var(--dd-ease);
}
.wl-input::placeholder { color: var(--dd-gray-500); }
/* The signed-out fields' own hover and focus (shared/auth.css): the edge
   steps up once on hover, and focus LIFTS the field on a small blue-grey
   shadow rather than drawing a darker outline, so this form and /login/
   answer a hand identically. */
@media (hover: hover) { .wl-input:hover { border-color: var(--auth-field-edge-hover); } }
.wl-input:focus, .wl-input:focus-visible { border-color: var(--auth-field-edge-hover); box-shadow: var(--auth-field-lift); }
.wl-input.is-bad { border-color: var(--dd-red); }
.wl-note { min-height: 18px; margin: 6px 2px 10px; font-size: var(--dd-fs-xs); line-height: 18px; color: var(--dd-red); }
.home-body .wl-go { display: grid; place-items: center; width: 100%; }
.wl-go > .wl-face { grid-area: 1 / 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.wl-go > .wl-face[data-on="false"] { visibility: hidden; }
.home-body .wl-go:disabled { cursor: default; }
/* THE ONE SPINNER, the app's ring (ui/Spinner.tsx) at its small size,
   drawn in the button's own ink: a faint full ring and one bright arc. It
   exists only while a request is out. */
.wl-spin {
  width: 14px; height: 14px; flex: none;
  border: 2px solid color-mix(in srgb, var(--dd-on-accent) 28%, transparent);
  border-top-color: var(--dd-on-accent); border-radius: 50%;
}
.wl-go > .wl-face[data-on="true"] .wl-spin { animation: wl-spin 700ms linear infinite; }
@keyframes wl-spin { to { transform: rotate(360deg); } }
.wl-done { align-self: center; justify-self: center; text-align: center; }
/* The confirmation's mark is the product's checked box in ink, as a disc. */
.wl-tick { width: 22px; height: 22px; margin: 0 auto 10px; border-radius: 50%; }
.wl-tick::after { -webkit-mask-size: 13px 13px; mask-size: 13px 13px; }
.wl-done-head { margin: 0; font-size: var(--dd-fs-md); font-weight: var(--dd-w-bold); color: var(--dd-ink); }
.wl-done-line { margin: 4px 0 0; font-size: var(--dd-fs-sm-); color: var(--dd-ink-quiet); }
.wl-alt { margin: 16px 0 0; text-align: center; font-size: var(--dd-fs-sm-); color: var(--dd-ink-quiet); }
.wl-signin { color: var(--dd-ink); font-weight: var(--dd-w-bold); text-decoration: none; }
@media (hover: hover) { .wl-signin:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--dd-gray-300); } }

/* ================================================= THE GLOW AT THE FOOT
   Tab's two layers (shared/auth.css --dd-glow and --dd-dome, tab.bot's own
   values) on the ground's last screen, behind the close and the footer.
   .home-glow is one layer pinned to the page's foot, the height of a
   viewport (at least 720), and it clips ITSELF: the page's sides and foot
   are its only edges, as the viewport's are on tab.bot, so no section can
   cut the arc and nothing in it ever widens the page.

   THE WASH is --dd-glow on the layer, the periwinkle rising from under the
   fold (a circle centred 15 percent below the foot, gone by 43 percent of
   its reach, so it fades out well inside the layer and has no top edge).

   THE DOME is centred near the page's foot, as Tab's is on the viewport's
   (Tab places it bottom: -58% of a 900 viewport, which puts the centre of
   a 1600 by 1067 dome within a few pixels of the bottom edge). So only its
   upper half shows, a white heart at the foot and the periwinkle rim
   (61 to 78 percent of its radius) arching up behind the close's card.
   --dome-drop sinks it a little further on a desktop, so the rim's crest
   crosses the card's LOWER half (its doors), where Tab's crosses its
   waitlist card. Its width is Tab's min(1600px, 180vw) on a desktop; on a
   phone 180vw would put the rim a hand's width above the foot, under the
   footer, so there it is 260vw, undropped, and the arc again crosses the
   card's lower half. A
   softer blur than Tab's 5px (14px) melts the 8-bit steps of its long, low
   gradients, which otherwise show as bands on a large display. */
.home-glow {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 0;
  height: max(100vh, 720px);
  overflow: hidden; pointer-events: none;
  background: var(--dd-glow);
}
.home-glow > .home-dome {
  --dome-w: min(1600px, 180vw);
  /* 110px under the page's foot when the card stood about 140px over it;
     the card now stands two section pads (less 18) and the footer over it,
     so the dome rises by what that added, and the rim still crests across
     the card's lower half at every width. */
  --dome-drop: calc(191px - 2 * var(--home-sec-pad));
  left: 50%; bottom: calc(var(--dome-w) / -3 - var(--dome-drop));
  width: var(--dome-w);
  transform: translateX(-50%);
  filter: blur(14px);
}
@media (max-width: 719.98px) {
  .home-glow > .home-dome { --dome-w: 260vw; --dome-drop: 0px; }
}

/* THE FOOTER, tab.bot's foot: one quiet row at the very bottom, inside the
   glow. The logo small at the left, a few small grey links beside it, the
   company line at the right; Tab's grey (#858a93) at round one's 13px.
   On a phone the row wraps, the company line under the links. */
.home-foot {
  width: min(calc(var(--shelf) + 2 * var(--dd-pad-x)), 100%); margin: 0 auto;
  padding: 18px var(--dd-pad-x) 26px;
  display: flex; align-items: center; gap: 8px 22px; flex-wrap: wrap;
  font-size: var(--dd-fs-sm-); color: #858a93;
}
.home-foot .auth-mark { display: flex; align-items: center; color: var(--dd-ink); padding: 12px 0; margin: -12px 0; }
.home-foot .auth-mark .brand-logo { height: 16px; filter: none; }
.home-foot-links { display: flex; align-items: center; gap: 2px 18px; flex-wrap: wrap; }
.home-foot-links a {
  display: inline-flex; align-items: center; min-height: 32px;
  color: #858a93; text-decoration: none;
  transition: color var(--dd-dur) var(--dd-ease);
}
@media (hover: hover) { .home-foot-links a:hover { color: var(--dd-ink); } }
.home-foot-note { margin: 0 0 0 auto; }

/* ---------------------------------------------------------- responsive */
@media (max-width: 999.98px) {
  /* One column, each card its own flow: the shared subgrid only matters
     while cards stand side by side. */
  .fg, .eg { grid-template-columns: minmax(0, 1fr); row-gap: 16px; }
  .fg { max-width: 560px; margin-left: auto; margin-right: auto; }
  .fc { grid-row: auto; display: flex; flex-direction: column; margin-bottom: 0; }
  .fc-face { min-height: 0; }
  .fc-l { display: inline; }
}
@media (max-width: 899.98px) {
  /* Rail plus ONE pane, which is what the product shows a narrow window. */
  .vx-panes { grid-template-columns: 1fr 0px 0fr; }
  .vx-guest { display: none; }
  .vx-rail { width: calc(168 * var(--u)); }
}
@media (max-width: 719.98px) {
  /* A phone keeps the band running off both of its ends, inside the
     gutter like everything else: three rows, smaller marks in narrower
     cells, the fade a little deeper so no mark is ever cut by the band's
     end while it can still be read. The chips wrap,
     centred: the two short ones share the first line and the import,
     the long one, takes the line under them (order only moves it on
     screen; it is still second to a screen reader). */
  .tl-band { --tl-m: 26px; --tl-cell: 66px; --tl-fade: 26%; row-gap: 22px; }
  .tl-row:nth-child(n + 4) { display: none; }
  .tl-ways { gap: 8px; }
  .tl-way { min-height: 38px; padding: 8px 14px 8px 12px; font-size: var(--dd-fs-sm-); }
  .tl-way:nth-child(2) { order: 1; }
}
@media (max-width: 639.98px) {
  .t-row { gap: 9px; padding: 7px 8px; }
}
/* (A phone's nav and buttons, which stepped down here under 480, 390 and
   340, are the native pass's since 2026-09-25: THE NATIVE PASS, at the
   foot of this sheet. The bar has room for the whole logo at 320 now that
   Pricing and Sign in live in its menu.) */

/* A finger on a wider screen (a phone held sideways, a tablet): the small
   links take a 44px target from room given back as margin (or, inline,
   from padding, which a line box ignores), so every row lays out exactly
   as it draws. */
@media (pointer: coarse) and (min-width: 720px) {
  .home-foot-links a { min-height: 44px; padding: 0 2px; margin: -6px -2px; }
  .wl-signin { display: inline-block; padding: 14px 4px; margin: -14px -4px; line-height: 16px; }
  .pl-note-go { padding: 14px 0; }
  .pr-trust-go { padding: 14px 0; margin: -14px 0; }
}

/* ============================================================ ON A PHONE
   Round 4 (David: "optimize the website for mobile as well ... Just
   optimize for native mobile experience as well"). Under 720px every
   section this sheet owns outside the hero (which has THE PHONE) is laid
   out for a phone, and nothing here reaches 720 and up.
     - THE NAV is compact (64px), clear of a notch or a rounded corner
       (the safe area, the page asks for viewport-fit=cover); since the
       native pass it stays on screen and holds a menu (THE NATIVE PASS).
     - THE BUSYWORK cards (a row that swipes since the native pass) take
       the card's padding in, so each picture gets the room; the pictures
       are composed for a phone's width rather than cut from the
       desktop's: the replies wrap instead of being cut short, the meeting
       keeps its sender's head and draws its afternoon taller with larger
       hours and labels, the to-do rows are a thumb's size (and the sort
       plays in their pitch).
     - THE CLOSE's card takes the column with even margins, and the "Sign
       in" under it is a 44px target.
     - THE FOOTER stacks, centred, one thing a line: the logo, the links
       (each 44px tall), the company line, clear of the home indicator.
   Everything touchable is 44px, and a tap never leaves a hover behind
   (the hover rules above ask for a pointer that hovers). */
.home-body :is(a, button) { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
@media (max-width: 719.98px) {
  .home-body { --nav-h: 64px; }
  /* a phone's fade, shorter, in proportion (THE WHITE) */
  .home-hero { --hero-fade: clamp(300px, 42svh, 400px); }
  .home-nav {
    height: calc(var(--nav-h) + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
    padding-left: max(var(--dd-pad-x), env(safe-area-inset-left));
    padding-right: max(var(--dd-pad-x), env(safe-area-inset-right));
  }
  .home-nav .auth-mark .brand-logo { height: 20px; }
  .home-hero { padding-left: max(var(--dd-pad-x), env(safe-area-inset-left)); padding-right: max(var(--dd-pad-x), env(safe-area-inset-right)); }

  #work .fc { --fc-text: 20px; padding-top: 20px; }
  .sr-msg, .sc-msg { font-size: var(--dd-fs-sm); }
  .sr-opt { white-space: normal; text-overflow: clip; font-size: var(--dd-fs-sm); line-height: 1.4; padding: 8px 11px; }
  .sc-mail .mb { display: flex; }
  .sc-msg { padding: 2px 14px 8px; }
  .sc-grid { min-height: 228px; }
  .sc-gutter i { font-size: 11px; }
  .sc-blk .tg-ev-title { font-size: 12.5px; }
  .sc-trav { font-size: 11px; }
  .st { --pitch: 40px; }
  .st .st-row { height: 36px; min-height: 36px; font-size: var(--dd-fs-sm); }

  .end-card { padding: 22px 20px 20px; }
  .wl-signin { display: inline-block; padding: 14px 4px; margin: -14px -4px; line-height: 16px; }

  .home-foot {
    /* 14px apart, so the logo's 44px target (its padding) ends where the
       links' begin: no two targets overlap. */
    flex-direction: column; justify-content: center; gap: 14px 0;
    padding: 18px max(var(--dd-pad-x), env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom)) max(var(--dd-pad-x), env(safe-area-inset-left));
    text-align: center;
  }
  .home-foot-links { justify-content: center; gap: 0 22px; }
  .home-foot-links a { min-height: 44px; }
  .home-foot .auth-mark { padding: 14px 0; margin: -14px 0; }
  .home-foot-note { margin: -6px 0 0; }
}

/* ================================================================ PRICING
   (2026-09-24, David: "for the landing page, I want it to also be a
   pricing page ... in the same style as how you design the landing page").
   /pricing only (components/pricing/PricingPage.tsx): the homepage had a
   band of three plans here for a day until David took it off ("Keep
   pricing only on pricing page"); the nav and the footer lead here. The
   prices are the serif, at the size of a card's title and up; everything
   else is Inter. Nothing here moves with the scroll or enters when seen.

   THE HIGHLIGHT IS QUIET. Pro is the one plan with the ink button, and its
   card is the one that stands forward: over the glow, where every card is
   the close's translucent white, it is opaque with an ink ring. No badge says so (David's calm rule: no
   label restating what the layout shows). */

.pl-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; margin: 0; }
.pl-num {
  font-family: var(--home-font-display); font-feature-settings: var(--home-feat-display), "lnum"; font-synthesis: none;
  font-weight: 400; letter-spacing: -.03em; line-height: 1; color: var(--dd-ink);
}
.pl-per { font-size: var(--dd-fs-sm); color: var(--dd-ink-quiet); white-space: nowrap; }
.pr-trust-go {
  color: var(--dd-ink); font-weight: var(--dd-w-semibold); text-decoration: none;
  text-underline-offset: 3px; text-decoration-color: var(--dd-gray-300);
}
@media (hover: hover) { .pr-trust-go:hover { text-decoration-line: underline; } }
.pr-trust-go { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.pr-trust-go::after {
  content: ""; width: 14px; height: 14px; flex: none; background: currentColor;
  -webkit-mask: var(--pr-chev) center / 14px 14px no-repeat; mask: var(--pr-chev) center / 14px 14px no-repeat;
}
.home-body {
  --pr-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E");
}

/* ------------------------------------------------ /pricing, the hero
   The homepage's hero without the window: the headline and one line, one
   gap above and below, then the four plans standing on Tab's glow (the
   hero's own dome, centred behind the row and let go under it). */
.pr-hero { overflow-x: clip; padding-bottom: clamp(8px, 1.5vw, 20px); }
.pr-copy { position: relative; z-index: 3; padding: clamp(48px, 8vh, 104px) 0 clamp(40px, 5.2vw, 72px); }
.pr-plans { position: relative; width: min(var(--shelf), 100%); margin: 0 auto; }
.pr-dome {
  left: 50%; top: 50%;
  width: min(1680px, calc(min(var(--shelf), 100vw) * 1.4));
  transform: translate(-50%, -46%);
  -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent 76%);
  mask-image: linear-gradient(to bottom, #000 40%, transparent 76%);
}

/* THE FOUR PLANS. Four across at the ceiling, each card taking six rows of
   the row's grid as a subgrid, so the names, the prices, the lines, the
   buttons and the feature lists each start on one line across the four,
   whatever wraps. Two across from 720 to 1080, one column on a phone with
   Pro first. Each card is the close's surface (white at 72 percent, Tab's
   9 percent edge, radius 24), so the glow shows through; Pro is opaque
   with an ink ring and the ink button. */
.pl-grid {
  position: relative; z-index: 1;
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: clamp(12px, 1.2vw, 16px); row-gap: 0;
  text-align: left;
}
.pl {
  grid-row: span 6; display: grid; grid-template-rows: subgrid; row-gap: 0; min-width: 0;
  padding: clamp(24px, 2.3vw, 32px) clamp(22px, 2.1vw, 30px) clamp(26px, 2.4vw, 32px);
  border: 1px solid var(--home-edge); border-radius: var(--dd-radius-xl);
  background: rgb(255 255 255 / .72);
  box-shadow: 0 18px 60px rgb(60 78 135 / .07);
}
.pl.is-featured { background: var(--dd-panel); border-color: var(--dd-ink); box-shadow: 0 24px 70px rgb(60 78 135 / .13); }
.pl-name { margin: 0; font-size: var(--dd-fs-md); font-weight: var(--dd-w-bold); letter-spacing: -.006em; line-height: 1.3; color: var(--dd-ink); }
.pl-price { margin-top: clamp(16px, 1.6vw, 22px); }
.pl-num { font-size: clamp(2.625rem, 3.4vw, 3.25rem); }
/* A word where the others have a number ("Custom") is set a step smaller,
   so it does not outshout the prices beside it. */
.pl-num.is-word { font-size: clamp(2.125rem, 2.6vw, 2.5rem); }
.pl-who { margin: 10px 0 0; font-size: var(--dd-fs-sm); line-height: var(--dd-lh-body); color: var(--dd-ink-quiet); text-wrap: pretty; }
.home-body .pl-go { align-self: end; width: 100%; margin-top: clamp(20px, 2vw, 26px); }
.pl-inherit {
  margin: clamp(22px, 2vw, 26px) 0 0; padding-top: clamp(20px, 1.9vw, 24px);
  border-top: 1px solid rgb(17 17 18 / .07);
  font-size: var(--dd-fs-sm-); font-weight: var(--dd-w-semibold); color: var(--dd-ink);
}
.pl-inherit:empty { padding-top: 0; }
.pl-feats {
  list-style: none; margin: 14px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 12px;
  font-size: var(--dd-fs-sm); line-height: 1.45; color: var(--dd-ink-light);
}
.pl-feats li { display: flex; gap: 10px; min-width: 0; }
.pl-feats li::before, .cmp-yes {
  content: ""; width: 14px; height: 14px; flex: none; margin-top: 2px; background: #6f86e0;
  -webkit-mask: var(--dd-tick) center / 14px 14px no-repeat; mask: var(--dd-tick) center / 14px 14px no-repeat;
}
.pl-body { display: flex; flex-direction: column; min-width: 0; }
/* The student price, at the foot of Pro's card: a quiet line under a
   hairline, and a waitlist door. */
.pl-note {
  margin: auto 0 0; padding-top: 22px;
  font-size: var(--dd-fs-sm-); line-height: 1.45; color: var(--dd-ink-quiet);
}
.pl-note-go { color: inherit; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--dd-gray-300); }
@media (hover: hover) { .pl-note-go:hover { color: var(--dd-ink); } }

/* ------------------------------------------------- the comparison
   (2026-09-26, David: "Not very intuitive and hard to compare right
   now"). One table on the white page, features by row and plans by
   column (components/pricing/PricingPage.tsx says how it reads).
     THE HEAD stays at the top of the screen while the rows scroll under
       it, on the page's own white so nothing shows through: each plan's
       name, its price in the serif, and from 1024 up its button. While
       rows pass under it (data-stuck, set by the page's script) a soft
       shade falls from its foot across the whole width, never a line.
     WHO IT'S FOR, each plan's one line, is the first row, so it scrolls
       away and the head stays short.
     PRO stands on a faint wash from its head to its foot, rounded at
       both ends, the table's one emphasis beside its ink button.
     A GROUP is a heading in ink with air above it. A ROW is 15px words
       on a generous height between faint hairlines, a tick, a quiet dash
       or a short value in ink, the plain line under a term in grey, and
       the row under a pointer on a faint wash, the fill inside the
       table's own padding.
   The phone's two columns and their picker are below, under 720. */
.cmp-wrap {
  --cmp-top: 0px;
  --cmp-wash: rgb(17 17 18 / .03);
  --cmp-hover: rgb(17 17 18 / .025);
  --cmp-px: clamp(12px, 1.4vw, 20px);
  margin-top: var(--home-head-gap);
}
.cmp-pick { display: none; }
.cmp {
  width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed;
  font-size: var(--dd-fs-sm); line-height: 1.4; text-align: left; color: var(--dd-ink-light);
}
.cmp-cap { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.cmp-heads > :first-child { width: 28%; }

.cmp thead { position: sticky; top: var(--cmp-top); z-index: 2; }
.cmp thead :is(th, td) { background: var(--dd-canvas); font-weight: 400; text-align: center; vertical-align: top; }
.cmp-heads > * { padding: 24px var(--cmp-px) 0; }
.cmp-acts > * { padding: 12px var(--cmp-px) 20px; }
/* The shade: a soft fall under every cell of the head's last row, one
   band across the table with no seams between the cells. */
.cmp thead tr > * { position: relative; }
.cmp-wrap[data-stuck] .cmp-acts > *::after {
  content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 14px; pointer-events: none;
  background: linear-gradient(rgb(45 55 90 / .07), rgb(45 55 90 / .025) 40%, transparent);
}
.cmp-plan { display: block; font-size: var(--dd-fs-md); font-weight: var(--dd-w-bold); letter-spacing: -.006em; line-height: 1.3; color: var(--dd-ink); }
.cmp-price { display: block; margin-top: 8px; }
.cmp-num {
  display: block;
  font-family: var(--home-font-display); font-feature-settings: var(--home-feat-display), "lnum"; font-synthesis: none;
  font-size: 1.875rem; font-weight: 400; letter-spacing: -.03em; line-height: 1; color: var(--dd-ink);
}
/* "Custom" a step smaller, as on its card. */
.cmp-num.is-word { font-size: 1.5rem; line-height: 1.25; }
.cmp-per { display: block; min-height: 1.4em; margin-top: 6px; font-size: var(--dd-fs-sm-); color: var(--dd-ink-quiet); text-wrap: balance; }
.home-body .cmp-go { width: 100%; height: 40px; padding: 0 12px; }
.cmp-who { display: block; margin: 0 auto; max-width: 24ch; font-size: var(--dd-fs-sm-); line-height: 1.45; color: var(--dd-ink-quiet); text-wrap: balance; }
.cmp-intro .cmp-row > * { padding-top: 20px; padding-bottom: 8px; border-top: 0; vertical-align: top; }

.cmp tbody :is(th, td) { padding: 15px var(--cmp-px); vertical-align: middle; }
.cmp-row > * { border-top: 1px solid var(--mk-line); }
.cmp-row > td { text-align: center; }
.cmp tbody th { font-weight: 400; }
.cmp-name { display: block; color: var(--dd-ink); }
.cmp-note { display: block; margin-top: 2px; font-size: var(--dd-fs-sm-); line-height: 1.4; color: var(--dd-ink-quiet); text-wrap: pretty; }
.cmp .cmp-group > * { padding-top: 44px; padding-bottom: 12px; }
.cmp .cmp-intro + tbody .cmp-group > * { padding-top: 32px; }
.cmp .cmp-group th { font-size: var(--dd-fs-md); font-weight: var(--dd-w-bold); letter-spacing: -.006em; color: var(--dd-ink); }
.cmp tbody:last-of-type tr:last-child > * { padding-bottom: 18px; }
@media (hover: hover) {
  .cmp-row:hover > * { background-image: linear-gradient(var(--cmp-hover), var(--cmp-hover)); }
}
.cmp-yes { display: inline-block; margin: 0; vertical-align: middle; background: var(--dd-ink); }
.cmp-no { display: inline-block; width: 10px; height: 1.5px; border-radius: 1px; vertical-align: middle; background: var(--dd-gray-300); }
.cmp-val { color: var(--dd-ink); font-weight: var(--dd-w-medium); }

/* Pro's wash, head to foot, over the page's white in the head so the rows
   still pass under it. */
@media (min-width: 720px) {
  .cmp [data-plan="pro"] { background-color: var(--cmp-wash); }
  .cmp thead [data-plan="pro"] { background: linear-gradient(var(--cmp-wash), var(--cmp-wash)), var(--dd-canvas); }
  .cmp-heads [data-plan="pro"] { border-radius: var(--mk-rl) var(--mk-rl) 0 0; }
  .cmp tbody:last-of-type tr:last-child [data-plan="pro"] { border-radius: 0 0 var(--mk-rl) var(--mk-rl); }
}
/* Stuck, the head is square, so no row shows through a rounded corner. */
.home-body .cmp-wrap[data-stuck] .cmp .cmp-heads > [data-plan] { border-radius: 0; }
/* Under 1024 a column is too narrow for a button's words: the head keeps
   the name and the price, and the plans' own buttons are just above. */
@media (max-width: 1023.98px) {
  .cmp-acts { display: none; }
  .cmp-heads > * { padding-bottom: 18px; }
  .cmp-wrap[data-stuck] .cmp-heads > *::after {
    content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 14px; pointer-events: none;
    background: linear-gradient(rgb(45 55 90 / .07), rgb(45 55 90 / .025) 40%, transparent);
  }
  .cmp-heads > :first-child { width: 26%; }
}

/* The privacy line, the homepage's reassurance in one row on the ground
   grey, and the way to the whole section on the homepage. */
.pr-trust {
  display: flex; align-items: center; gap: 14px;
  margin-top: clamp(32px, 3.4vw, 48px); padding: 18px clamp(18px, 2vw, 26px);
  border-radius: var(--mk-rl); background: var(--mk-ground);
  text-align: left;
}
.pr-trust-mark { width: 22px; height: 22px; flex: none; color: #6f86e0; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.pr-trust p { flex: 1 1 auto; margin: 0; font-size: var(--dd-fs-sm); line-height: 1.5; color: var(--dd-ink-quiet); }
.pr-trust b { font-weight: var(--dd-w-semibold); color: var(--dd-ink); }

/* ------------------------------------------ narrower and on a phone */
@media (max-width: 1079.98px) {
  .pl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 760px; margin: 0 auto; }
  .pl { margin-bottom: clamp(12px, 1.2vw, 16px); }
}
@media (max-width: 719.98px) {
  /* /pricing: the plans stack, Pro first, each card one flow. */
  .pr-copy { padding: 40px 0 32px; }
  /* The glow frames the headline and the first plan, as the homepage's
     phone hero does, rather than cresting halfway down the column. */
  .pr-dome { top: 0; width: 240vw; transform: translate(-50%, -18%); }
  .pl-grid { grid-template-columns: minmax(0, 1fr); max-width: 520px; }
  .pl { grid-row: auto; display: flex; flex-direction: column; margin-bottom: 16px; padding: 24px 22px 26px; }
  .pl.is-featured { order: -1; }
  .pl-go { margin-top: 20px; }
  .pl-note { padding-top: 18px; }
  .pl-note-go { display: inline-block; padding: 12px 0; margin: -12px 0; }

  /* The comparison: two plans side by side, picked above the table (the
     phone's pass, THE COMPARE PICKER, below). */

  .pr-trust { flex-wrap: wrap; align-items: flex-start; padding: 18px 18px 16px; }
  .pr-trust p { flex-basis: calc(100% - 36px); }
  .pr-trust-go { margin-left: 36px; padding: 12px 0; margin-top: -8px; margin-bottom: -10px; }
}

/* ======================================================== THE NATIVE PASS
   (2026-09-25, David: "for the landing page. please make it more mobile
   native".) On a phone the page is laid out the way an iOS app or Apple's
   own mobile pages are, not as a desktop page taken in. Every rule in the
   blocks below is inside the page's phone band (under 720), so from 720 up
   the page is exactly what it was, to the pixel. Both pages wear it
   (/pricing shares the nav, the sheet, the close and the footer). Motion
   here is transform and opacity only, in CSS at the display's own rate,
   and under reduced motion every slide becomes a fade. In three blocks:
     THE HEADER AND ITS SHEET  the bar stays at the top of the screen; its
                               menu rises as a sheet
     SWIPE, DON'T STACK        the card sections are rows that swipe
     TYPE AND TARGETS          iOS sizes, 44px targets, a real press, and
                               the privacy list as a grouped list
   The phone's hero (no phone drawn inside the phone) is THE PHONE, above. */
.home-menu-btn, .home-dots, .home-ground > .home-sheet { display: none; }
@media (max-width: 719.98px) {
  .home-body {
    /* The gutters, clear of a rounded corner or a notch held sideways. */
    --home-gl: max(var(--dd-pad-x), env(safe-area-inset-left));
    --home-gr: max(var(--dd-pad-x), env(safe-area-inset-right));
  }
}

/* -------------------------------------------- THE HEADER AND ITS SHEET
   THE HEADER STAYS. A bar at the top of the screen, clear of the notch, on
   a translucent white that blurs what passes under it, with a hairline
   that fades in only once the page has scrolled under it (a fade, never a
   line and a band; Nav.tsx flips data-under). It holds the logo, a
   compact "Join" pill and a menu button, each a 44px target; Pricing and
   Sign in move into the menu.
   THE SHEET (components/Sheet.tsx says how it behaves) rises from the
   foot of the screen over a dimmed scrim on an iOS sheet's curve, quick
   off the mark and long and soft into place, and goes back down the same
   way: a white card inset from the screen's edges and clear of the home
   indicator, a grabber, 52px rows and the one primary at the full width,
   every corner in it concentric with the card's. */
@media (max-width: 719.98px) {
  :root { --home-sheet-ease: cubic-bezier(.32, .72, 0, 1); }
  /* An anchor lands clear of the header. */
  html { scroll-padding-top: calc(76px + env(safe-area-inset-top)); }
  /* The sheet holds the page still while it is up (behaviours/menu.ts). */
  html.home-locked { overflow: hidden; }

  .home-nav { position: sticky; top: 0; z-index: 20; gap: 12px; }
  /* The translucent ground, on its own layer under the bar's contents, so
     the header itself keeps no fill and no filter (and is no containing
     block for anything fixed). */
  .home-nav::before {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background: rgb(253 253 252 / .8);
    -webkit-backdrop-filter: saturate(1.6) blur(18px);
    backdrop-filter: saturate(1.6) blur(18px);
  }
  .home-nav::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; pointer-events: none;
    background: rgb(17 17 18 / .08);
    opacity: 0; transition: opacity 240ms var(--dd-ease);
  }
  .home-nav[data-under]::after { opacity: 1; }
  /* ON THE SKY (the dusk hero). While the header stands on the hero's sky
     it has no ground of its own and draws in light (THE NAV ON THE SKY);
     once the page under it is the white one (Nav.tsx marks it data-lit as
     the horizon passes under it) it takes back its translucent white, its
     hairline and its ink. Only where a script runs (hw-on or hw-calm),
     since only a script can tell; with none the header is the ink one. */
  .home-dusk .home-nav {
    --nav-ink: var(--dd-ink);
    --nav-quiet: var(--dd-ink-light);
    --nav-fill: var(--dd-accent);
    --nav-fill-hover: color-mix(in srgb, var(--dd-accent) 88%, var(--dd-panel));
    --nav-on-fill: var(--dd-on-accent);
    --nav-ring: var(--dd-canvas);
  }
  html:is(.hw-on, .hw-calm) .home-dusk .home-nav:not([data-lit]) {
    --nav-ink: #fff;
    --nav-quiet: rgb(255 255 255 / .74);
    --nav-fill: #fff;
    --nav-fill-hover: rgb(255 255 255 / .86);
    --nav-on-fill: #0c1636;
    --nav-ring: #0c1636;
  }
  .home-dusk .home-nav::before { transition: opacity 240ms var(--dd-ease); }
  html:is(.hw-on, .hw-calm) .home-dusk .home-nav:not([data-lit])::before,
  html:is(.hw-on, .hw-calm) .home-dusk .home-nav:not([data-lit])::after { opacity: 0; }
  .home-dusk .home-menu-btn { color: var(--nav-ink); transition: color 240ms var(--dd-ease), background 100ms var(--dd-ease), transform 100ms var(--dd-ease); }
  /* Under reduced motion the header changes its colours at once. */
  @media (prefers-reduced-motion: reduce) {
    .home-dusk .home-nav :is(.auth-mark, .btn, .home-menu-btn),
    .home-dusk .home-nav::before, .home-dusk .home-nav::after { transition: none; }
  }
  .home-nav-actions { gap: 6px; margin-right: -10px; }
  .home-nav :is(.home-nav-site, .home-nav-link) { display: none; }
  /* The compact Join, a pill: 36px drawn, its target taken out to 44 by a
     layer the size of the target. Its last words are for the ear only. */
  .home-body .home-nav .btn-primary { position: relative; height: 36px; padding: 0 16px; border-radius: 18px; font-size: .9375rem; }
  .home-nav .btn-primary::after { content: ""; position: absolute; inset: -4px -3px; }
  .home-nav-more { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .home-menu-btn {
    display: grid; place-items: center; width: 44px; height: 44px; border-radius: var(--home-radius-ctl);
    color: var(--dd-ink); -webkit-tap-highlight-color: transparent;
    transition: background 100ms var(--dd-ease), transform 100ms var(--dd-ease);
  }
  .home-menu-btn svg { width: 22px; height: 22px; stroke-width: 1.9; stroke-linecap: round; }
  .home-menu-btn:active { background: rgb(17 17 18 / .06); transform: scale(.94); }

  .home-ground > .home-sheet {
    position: fixed; inset: 0; z-index: 40; display: block;
    visibility: hidden; pointer-events: none;
    transition: visibility 0s linear 320ms;
  }
  .home-ground > .home-sheet[data-open] { visibility: visible; pointer-events: auto; transition-delay: 0s; }
  .home-sheet-scrim {
    position: absolute; inset: 0; touch-action: none;
    background: rgb(17 17 18 / .3);
    opacity: 0; transition: opacity 320ms var(--home-sheet-ease);
  }
  .home-sheet-card {
    position: absolute;
    left: max(8px, env(safe-area-inset-left)); right: max(8px, env(safe-area-inset-right)); bottom: max(8px, env(safe-area-inset-bottom));
    padding: 24px 8px 8px; border-radius: var(--dd-radius-xl); touch-action: none; outline: none;
    background: var(--dd-panel);
    box-shadow: 0 0 0 1px rgb(17 17 18 / .04), 0 1px 3px rgb(40 45 70 / .06), 0 24px 64px -16px rgb(40 45 70 / .32);
    transform: translate3d(0, calc(100% + 24px), 0);
    transition: transform 320ms var(--home-sheet-ease);
  }
  /* The card takes the focus when it opens, and wears no ring for it. */
  .home-body .home-sheet-card:focus-visible { box-shadow: 0 0 0 1px rgb(17 17 18 / .04), 0 1px 3px rgb(40 45 70 / .06), 0 24px 64px -16px rgb(40 45 70 / .32); }
  .home-sheet[data-open] .home-sheet-scrim { opacity: 1; transition-duration: 460ms; }
  .home-sheet[data-open] .home-sheet-card { transform: none; transition-duration: 460ms; }
  .home-sheet-grab { position: absolute; top: 8px; left: 50%; width: 36px; height: 5px; margin-left: -18px; border-radius: 3px; background: rgb(17 17 18 / .14); }
  .home-sheet-rows { list-style: none; margin: 0; padding: 0; }
  .home-sheet-rows > li { position: relative; }
  .home-sheet-rows > li + li::before { content: ""; position: absolute; top: 0; left: 16px; right: 16px; height: 1px; background: var(--mk-line); }
  .home-sheet-row {
    display: flex; align-items: center; min-height: 52px; padding: 0 16px; border-radius: 16px;
    font-size: 1.0625rem; font-weight: var(--dd-w-medium); letter-spacing: -.01em; color: var(--dd-ink); text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: background 100ms var(--dd-ease);
  }
  .home-sheet-row::after {
    content: ""; width: 16px; height: 16px; margin-left: auto; flex: none; background: var(--dd-ink-quiet); opacity: .6;
    -webkit-mask: var(--pr-chev) center / 16px 16px no-repeat; mask: var(--pr-chev) center / 16px 16px no-repeat;
  }
  .home-sheet-row[aria-current="page"] { font-weight: var(--dd-w-bold); }
  .home-sheet-row:active { background: var(--mk-fill-2); }
  /* 8px inside the card's 24px corner, so its corner is the concentric 16,
     like the rows'. */
  .home-body .home-sheet-go { width: 100%; height: 50px; margin-top: 8px; border-radius: 16px; }
  /* THE ACCOUNT'S DOORS, apart from the site's pages above them
     (2026-09-28): a clear gap, then "Sign in" as the quiet door (the
     button's shape with no fill, a hairline round it) over the primary. */
  .home-sheet-doors { margin-top: 16px; }
  .home-body .home-sheet-in {
    display: flex; align-items: center; justify-content: center; width: 100%; height: 50px; border-radius: 16px;
    font-family: var(--home-font-text); font-size: 1.0625rem; font-weight: var(--home-btn-w); letter-spacing: var(--home-btn-ls);
    color: var(--dd-ink); text-decoration: none;
    box-shadow: inset 0 0 0 1px var(--mk-line);
    -webkit-tap-highlight-color: transparent;
    transition: background 100ms var(--dd-ease);
  }
  .home-body .home-sheet-in:active { background: var(--mk-fill-2); }

  /* UNDER REDUCED MOTION the sheet fades in place instead of sliding, and
     the header's hairline simply stands or goes. The shared sheet stops
     every transition there (auth.css, with !important), so the fade, and
     the sheet's hiding after it, are restated the same way. */
  @media (prefers-reduced-motion: reduce) {
    .home-sheet-card { transform: none; opacity: 0; }
    .home-sheet[data-open] .home-sheet-card { opacity: 1; }
    .home-ground > .home-sheet { transition: visibility 0s linear 200ms !important; }
    .home-ground > .home-sheet[data-open] { transition: visibility 0s !important; }
    .home-sheet :is(.home-sheet-scrim, .home-sheet-card) { transition: opacity 200ms var(--dd-ease) !important; }
    .home-nav::after { transition: none; }
  }
  /* With no script the menu button is a link to the sheet, which opens as
     the page's target. */
  @media (scripting: none) {
    .home-ground > .home-sheet:target { visibility: visible; pointer-events: auto; transition-delay: 0s; }
    .home-sheet:target .home-sheet-scrim { opacity: 1; }
    .home-sheet:target .home-sheet-card { transform: none; opacity: 1; }
  }
}

/* -------------------------------------------------- SWIPE, DON'T STACK
   The busywork's three cards and the team's four are one row each that
   the thumb swipes through, a card at a time: each card 86 percent of the
   column with the next one peeking, snapping to the gutter, momentum
   scrolling with no scrollbar, and a sideways swipe never moves the page.
   The page dots under a row say which card is in front (Dots.tsx). A row's
   cards share one height and the pictures stretch to it. Where a card is
   stretched, its picture reads from the top and the room it gains stays
   at its foot, so the story is on screen before the air is: the client's
   answer follows its sources rather than sinking to the pane's foot, and
   the time card's day keeps its rows while its agent takes the room, and
   where the time card is cropped it is the day, with its booked hour,
   that stands in view.
   Each picture still plays its job once, when it is swiped into view
   (usePlayOnce.ts watches it through the row's clip).

   A ROW FITS ON ONE SCREEN, the card and its dots together, so a card is
   always seen whole. A row is as tall as its tallest card and never
   taller than --row-cap: the small viewport, less the sticky header and
   the air under it, the dots, and the gap to the home indicator. It crops the
   PICTURE, never the words: the title and the sentence always stand in
   full, and the picture takes what is left and is cut with a soft fade at
   its foot, the way the App Store's Today cards crop (Dots.tsx marks a
   card data-crop when its picture is taller than its room; a picture
   that fits keeps its app panel filling the card, with no fade). The cap
   never goes under 400px, so on a screen shorter than a 568 one a card is
   still its words and a real piece of its picture, and there its dots
   may stand under the screen's foot. */
@media (max-width: 719.98px) {
  .fg, .eg {
    display: flex; gap: 12px;
    max-width: none; margin: 0 calc(-1 * var(--home-gr)) 0 calc(-1 * var(--home-gl));
    padding: 0 var(--home-gr) 0 var(--home-gl);
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory; scroll-padding-inline: var(--home-gl) var(--home-gr);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .fg::-webkit-scrollbar, .eg::-webkit-scrollbar { display: none; }
  .home-body {
    --row-cap: max(400px, calc(100svh - var(--nav-h) - env(safe-area-inset-top) - 12px - 50px - max(12px, env(safe-area-inset-bottom))));
  }
  .fg > .fc, .eg > .fc, .eg > .fc:not(:last-child) { flex: 0 0 86%; min-width: 0; max-height: var(--row-cap); margin: 0; scroll-snap-align: start; scroll-snap-stop: always; }
  .fc > .fc-face { flex: 1 1 auto; min-height: 0; }
  /* The crop's fade. The face reaches out over the card's bezel (and gives
     it back as padding, so its width, which the pictures' container
     queries read, is unchanged), so the fade takes the pane's soft shadow
     with it rather than cutting it at the sides. */
  .fc[data-crop] > .fc-face {
    margin-left: calc(-1 * var(--fc-bezel)); margin-right: calc(-1 * var(--fc-bezel));
    padding: 0 var(--fc-bezel);
    overflow: clip;
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 56px), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 56px), transparent);
  }
  /* The agent never shrinks under its content: a capped card crops it from
     the foot, under the day, rather than squeezing its thread. */
  .tt { grid-template-rows: max-content minmax(max-content, 1fr); }
  .cx-chat { justify-content: flex-start; }
  /* A card's sentences wrap in its narrower column rather than end in an
     ellipsis (the agent's finding, its booking, the next step it offers). */
  .tt-say > .tt-found, .tt-bookline, .cx-nextline { white-space: normal; }

  .home-dots { display: flex; justify-content: center; margin: 6px 0 -12px; }
  .home-dot {
    display: grid; place-items: center; width: 44px; height: 44px; padding: 0;
    border: 0; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  .home-dot::before {
    content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--dd-ink);
    opacity: .16; transition: opacity 200ms var(--dd-ease), transform 100ms var(--dd-ease);
  }
  .home-dot[aria-current="true"]::before { opacity: .8; }
  .home-dot:active::before { transform: scale(.8); }
  /* The focus ring rings the dot, not its 44px target. */
  .home-body .home-dot:focus-visible { box-shadow: none; }
  .home-body .home-dot:focus-visible::before { box-shadow: 0 0 0 2px var(--dd-canvas), 0 0 0 4px var(--dd-ink); }
  @media (prefers-reduced-motion: reduce) { .home-dot::before { transition: none; } }
  /* With no script the dots could not move, so they are not drawn. */
  @media (scripting: none) { .home-dots { display: none; } }
}

/* ------------------------------------------- THE PICTURES ON A PHONE
   (Round three, David: "improve all the animations and ui illustrations
   to fit better and be more native ... where the section is a time
   everyone's free. the agent chat is cut out so animation doesn't make as
   much sense".) Each card's picture is recomposed for a phone rather than
   cropped: the same markup, laid out as a phone app would lay it out,
   small enough that the whole of its one play stands inside the card at
   390 by 844, 375 by 667 and 430 by 932, so the row's fade crop is only
   a last resort (a 320 by 568 screen).
     - A TIME EVERYONE'S FREE is one conversation on one white pane: the
       ask at the top, the agent's line under it (reading five calendars,
       then the finding), the team's day as a compact calendar where the
       scan runs down, the three hours light and the one that works is
       booked, the booking line, and the composer where the ask is typed,
       at the foot as in any chat. The two pane heads and the ranked list
       step aside; the day's lit hours carry the ranking.
     - MANAGE PROJECTS TOGETHER keeps its head, its progress and the tasks
       the play moves (the Apple Pay task that takes the PR, and the
       ticked one that folds into Completed), with the mail and the tools
       it files as two small tiles side by side, each one row tall, so the
       newest lands on top and the one before slides out at its foot.
     - The others take small trims: a shorter afternoon for the meeting,
       closer rows for the client's sources, and the pricing call's pane
       head steps aside for its question. */
@media (max-width: 719.98px) {
  /* a. the time. */
  .home-ground .tt {
    display: flex; flex-direction: column; gap: 8px;
    padding: 10px 10px 8px;
    border-radius: var(--mk-rl); background: var(--dd-panel); box-shadow: var(--mk-shadow);
    overflow: hidden;
  }
  .tt :is(.tt-cal, .tt-chat, .tt-thread, .tt-answer) { display: contents; }
  .tt :is(.tt-cal, .tt-chat) > .mb, .tt .tt-opts { display: none; }
  .tt .tt-merow { order: 1; padding: 0 2px; }
  .tt .tt-reply { order: 2; padding: 0 2px; }
  .tt .tg { order: 3; --top: 24px; --rh: 16px; padding: 0 4px 0 0; }
  .tt .tt-booked { order: 4; }
  .tt .tt-comp { order: 5; margin: 0; }
  .tt .tg-hrow > span { margin-top: -5px; font-size: 9.5px; }
  .tt .tg-who { padding-top: 0; }
  .tt .tg-book { gap: 6px; }
  .tt .tg-book-tick { width: 12px; height: 12px; }
  .tt .tg-book-tick::after { -webkit-mask-size: 8px 8px; mask-size: 8px 8px; }
  .tt .tg-book-name { font-size: 10.5px; line-height: 1; }
  .tt .tg-opt > b { width: 13px; height: 13px; margin-top: -6.5px; font-size: 8px; }
  .tt .tg-b { top: calc(var(--t) * 100% / var(--span) + 1.5px); height: calc(var(--h) * 100% / var(--span) - 3px); border-radius: 4px; }

  /* b. the meeting: a shorter afternoon. */
  .sc-grid { min-height: 180px; }

  /* c. the client: its sources closer together. */
  .cx-in { gap: 10px; }
  .cx-src { gap: 3px; }
  .cx-tile { min-height: 32px; padding-top: 3px; padding-bottom: 3px; }

  /* d. the pricing call: the question stands for the pane's head. */
  .pr > .mb { display: none; }
  .pr-in { padding-top: 10px; gap: 6px; }
  .pr-tier { padding: 6px 8px 6px; gap: 2px; }
  .pr-head { padding: 4px 8px 3px; }

  /* e. the project. */
  .pj-bar { height: 44px; }
  .pj-page { padding-top: 2px; }
  .pj-activity { display: none; }
  .pj-progress { margin-top: 12px; }
  .pj-side {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
    margin: 14px 0 0; padding: 0;
  }
  .pj-side > .pj-sec { min-width: 0; padding: 8px 6px 6px; border-radius: var(--mk-rm); background: var(--mk-faint); box-shadow: inset 0 0 0 1px var(--mk-line); }
  .pj-sec > .pj-sechead { margin: 0 6px 4px; font-size: 11px; font-weight: var(--dd-w-medium); color: var(--dd-ink-quiet); line-height: 14px; }
  .pj-mails { height: calc(var(--pj-mp) - 4px); }
  .pj-conns { height: calc(var(--pj-cp) - 4px); }
  .pj-mail, .pj-conn { padding: 0 4px; }
  .pj-conn { gap: 6px; }
  .pj-conn .pj-logo { width: 14px; height: 14px; margin: 0; }
  .pj-tasks { margin-top: 14px; }
  .pj-tasks > .pj-sechead { margin: 0 8px 4px; }
  /* The one open task the play moves, and the ticked one over Completed's
     slot (a pitch under it). */
  .pj-tlist > .pj-task:not(.pj-moved):not(:first-child) { display: none; }
  .pj-moved { top: var(--pj-p); }
}

/* ---------------------------------------------------- TYPE AND TARGETS
   iOS SIZES. The body and every section's lead at 17px on a 1.45 leading,
   section titles in the serif at about 31px, the hero's at 44px (smaller
   only where 44 cannot hold "that" on a 320 screen), lists at 15px, and no
   small print under 13px. The product pictures keep the app's own sizes;
   they are pictures of it.
   TARGETS. Every control at least 44px; the fields 50px tall with 17px
   words (under 16px iOS zooms the page on focus), and every full-width
   primary 50px. A press answers at once, in 100ms, with a slight scale
   and a deeper fill, and nothing depends on hover.
   THE PRIVACY LIST is an iOS grouped list: one inset rounded group, rows
   of at least 52px, hairlines inset past the icon. */
@media (max-width: 719.98px) {
  :root {
    --home-h1-size: clamp(2.25rem, 11.3vw, 2.75rem);
    --home-h2-size: clamp(1.75rem, 8vw, 1.9375rem);
    --home-lede-size: 1.0625rem;
    --home-lede-lh: 1.45;
    --home-line-size: 1.0625rem;
    --home-btn-size: 1.0625rem;
  }
  .home-hero, .home-sec { padding-left: var(--home-gl); padding-right: var(--home-gr); }
  .home-line { line-height: 1.45; }
  .fc-say { font-size: 1.0625rem; line-height: 1.45; }

  .home-body .btn { padding: 0 20px; font-size: var(--home-btn-size); }
  .home-body :is(.wl-go, .sec-talk, .pl-go) { width: 100%; height: 50px; }
  /* The press: at once, a slight scale and a deeper fill. */
  .home-body .btn { transition: background 100ms var(--dd-ease), border-color 100ms var(--dd-ease), transform 100ms var(--dd-ease); }
  .home-body .btn:not(:disabled):active { transform: scale(.97); background: var(--dd-gray-100); }
  .home-body .btn-primary:not(:disabled):active { background: color-mix(in srgb, var(--dd-accent) 84%, var(--dd-panel)); }
  .home-foot-links a:active, .wl-signin:active, .pl-note-go:active, .pr-trust-go:active { opacity: .55; }
  .home-foot-links a { min-width: 44px; justify-content: center; }
  .pl-note-go { padding: 13px 0; margin: -13px 0; }
  .pr-trust-go { padding: 14px 0; margin-top: -10px; margin-bottom: -12px; }

  /* The form: 50px fields with 17px words, labels a size up, the one note
     at the small print's floor. */
  .wl-label { font-size: .9375rem; }
  .wl-label-2 { margin-top: 16px; }
  .wl-input { height: 50px; padding: 0 16px; font-size: 1.0625rem; }
  .wl-note { font-size: .8125rem; }
  .wl-alt { font-size: .9375rem; }

  .sec-grid { border-radius: 20px; }
  .sec-item { position: relative; min-height: 52px; padding: 13px 16px 14px; column-gap: 14px; box-shadow: none; }
  .sec-item + .sec-item::before { content: ""; position: absolute; top: 0; right: 0; left: 60px; height: 1px; background: var(--mk-line); }
  .sec-ico { width: 30px; height: 30px; border-radius: 8px; }
  .sec-ico svg { width: 17px; height: 17px; }
  .sec-name { font-size: 1.0625rem; line-height: 1.3; }
  .sec-say { font-size: .9375rem; line-height: 1.4; }
  .sec-teams-line { font-size: 1.0625rem; line-height: 1.45; }
  .sec-ent { font-size: .9375rem; }

  /* /pricing. */
  .pl-name { font-size: 1.0625rem; }
  .pl-who { font-size: 1.0625rem; line-height: 1.45; }
  .pl-per, .pl-feats, .pr-trust p { font-size: .9375rem; }
}

/* ---------------------------------------------------- THE COMPARE PICKER
   /pricing's table on a phone. Four columns do not fit a thumb's width
   and a table that scrolls sideways hides the plan you came to see, so
   the table shows two: an iOS segmented control over it picks a plan, and
   the plan stands beside its neighbour (Free or Pro, the two of them; Teams
   beside Pro; Enterprise beside Teams), on the wash that marks Pro on a
   desktop. The control is four native radio buttons (arrow keys, and no
   script needed): the page reads which is checked with :has(). The thumb
   slides to it on the sheet's curve, and under reduced motion it is
   simply there.
   Both stay under the site's header, the control first and the plans'
   names and prices under it, on the page's white; the header's height is
   the page's own (--nav-h and the notch), read here, never set. Rows are
   17px, the plain lines 15px, every target at least 44px. */
@media (max-width: 719.98px) {
  .cmp-wrap {
    --cmp-top: calc(var(--nav-h) + env(safe-area-inset-top));
    --cmp-pick-h: 60px;
    margin-top: 28px;
  }
  .cmp-pick {
    position: sticky; top: var(--cmp-top); z-index: 3;
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    height: var(--cmp-pick-h); box-sizing: border-box; padding: 8px 0;
    background: var(--dd-canvas);
  }
  /* The track, and the thumb on it. */
  .cmp-pick::before { content: ""; position: absolute; inset: 8px 0; border-radius: var(--home-radius-ctl); background: rgb(17 17 18 / .055); }
  .cmp-thumb {
    position: absolute; top: 11px; left: 3px; width: calc((100% - 6px) / 4); height: calc(var(--cmp-pick-h) - 22px);
    border-radius: 9px; background: var(--dd-panel);
    box-shadow: 0 0 0 .5px rgb(17 17 18 / .04), 0 1px 2px rgb(40 45 70 / .08), 0 3px 8px rgb(40 45 70 / .08);
    transition: transform 320ms var(--home-sheet-ease);
  }
  .cmp-pick:has([value="pro"]:checked) .cmp-thumb { transform: translateX(100%); }
  .cmp-pick:has([value="teams"]:checked) .cmp-thumb { transform: translateX(200%); }
  .cmp-pick:has([value="enterprise"]:checked) .cmp-thumb { transform: translateX(300%); }
  .cmp-seg {
    position: relative; z-index: 1; display: grid; place-items: center; min-width: 0; min-height: 44px;
    font-size: .9375rem; font-weight: var(--dd-w-medium); color: var(--dd-ink-light);
    cursor: pointer; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none;
  }
  .cmp-seg input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
  .cmp-seg span { pointer-events: none; }
  .cmp-seg:has(:checked) { color: var(--dd-ink); font-weight: var(--dd-w-semibold); }
  .cmp-seg:active span { opacity: .55; }
  .cmp-seg:has(:focus-visible)::after {
    content: ""; position: absolute; inset: 3px; border-radius: 9px; pointer-events: none;
    box-shadow: 0 0 0 2px var(--dd-canvas), 0 0 0 4px var(--dd-ink);
  }

  .cmp { font-size: 1.0625rem; line-height: 1.35; }
  .cmp thead { top: calc(var(--cmp-top) + var(--cmp-pick-h)); }
  /* The head is two short lines a plan, the name and what it costs, so
     the control, the head and the site's header together keep most of
     the screen for the rows. */
  .cmp-heads > :first-child { width: 52%; }
  .cmp-heads > * { padding: 10px 6px 12px; }
  .cmp-plan { font-size: 1.0625rem; font-weight: var(--dd-w-semibold); }
  .cmp-price { margin-top: 2px; font-size: .8125rem; line-height: 1.3; color: var(--dd-ink-quiet); }
  .cmp-num, .cmp-num.is-word {
    display: block; font-family: inherit; font-feature-settings: inherit;
    font-size: inherit; letter-spacing: 0; line-height: inherit; color: var(--dd-ink-light);
  }
  .cmp-per { min-height: 0; margin: 0; font-size: inherit; text-wrap: balance; }
  .cmp-intro { display: none; }
  .cmp tbody :is(th, td) { padding: 13px 6px; }
  .cmp tbody th { padding-left: 0; padding-right: 12px; }
  .cmp-row > td { font-size: .9375rem; }
  .cmp-note { font-size: .9375rem; }
  .cmp .cmp-group > * { padding-top: 36px; padding-bottom: 10px; }
  .cmp .cmp-intro + tbody .cmp-group > * { padding-top: 16px; }
  .cmp .cmp-group th { font-size: 1.0625rem; white-space: nowrap; }
  .cmp-val { text-wrap: balance; }

  /* Two columns: the picked plan and its neighbour. */
  .cmp [data-plan] { display: none; }
  .cmp-wrap:has([value="free"]:checked) .cmp :is([data-plan="free"], [data-plan="pro"]),
  .cmp-wrap:has([value="pro"]:checked) .cmp :is([data-plan="free"], [data-plan="pro"]),
  .cmp-wrap:has([value="teams"]:checked) .cmp :is([data-plan="pro"], [data-plan="teams"]),
  .cmp-wrap:has([value="enterprise"]:checked) .cmp :is([data-plan="teams"], [data-plan="enterprise"]) { display: table-cell; }
  /* The picked one on the wash, rounded at its head and its foot. */
  .cmp-wrap:has([value="free"]:checked) .cmp [data-plan="free"],
  .cmp-wrap:has([value="pro"]:checked) .cmp [data-plan="pro"],
  .cmp-wrap:has([value="teams"]:checked) .cmp [data-plan="teams"],
  .cmp-wrap:has([value="enterprise"]:checked) .cmp [data-plan="enterprise"] { background-color: var(--cmp-wash); }
  .cmp-heads > [data-plan] { background: var(--dd-canvas); }
  .cmp-wrap:has([value="free"]:checked) .cmp-heads > [data-plan="free"],
  .cmp-wrap:has([value="pro"]:checked) .cmp-heads > [data-plan="pro"],
  .cmp-wrap:has([value="teams"]:checked) .cmp-heads > [data-plan="teams"],
  .cmp-wrap:has([value="enterprise"]:checked) .cmp-heads > [data-plan="enterprise"] {
    background: linear-gradient(var(--cmp-wash), var(--cmp-wash)), var(--dd-canvas);
    border-radius: var(--mk-rl) var(--mk-rl) 0 0;
  }
  .cmp tbody:last-of-type tr:last-child > [data-plan] { border-radius: 0 0 var(--mk-rl) var(--mk-rl); }
  /* A browser without :has() shows Free and Pro, the picker's default. */
  @supports not selector(:has(a)) {
    .cmp-pick { display: none; }
    .cmp :is([data-plan="free"], [data-plan="pro"]) { display: table-cell; }
    .cmp thead { top: var(--cmp-top); }
  }
}
@media (max-width: 719.98px) and (prefers-reduced-motion: reduce) {
  .cmp-thumb { transition: none; }
}
