/* Signed-out landing page. */
.hire-button {
  background: var(--accent);
  color: var(--bg);
  border: none;
  padding: 0.625rem 1.5rem;
  border-radius: var(--radius-sm);
  font-size: 0.9375rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease;
  white-space: nowrap;

  &:hover {
    background: var(--accent-hover);
  }
}

/* Capabilities: term over description, two columns. A dl rather than a ul —
   these are definitions, and six bold-then-muted bullet lines read as a wall.
   Wide column gap and a narrow measure per cell so each pair reads as one
   block; the descriptions carry the smaller step so the terms scan first.
   Second user since 2026-09-15: every section of /security, which was thirty
   identical bullets at a 109-character measure. */

.capability-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-8) var(--space-16);
  max-width: 58rem;
  margin-top: var(--space-12);
}

.capability-grid dt {
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  margin-bottom: var(--space-1);
}

.capability-grid dd {
  margin: 0;
  font-size: 0.9375rem;
  --lh: 1.65;
  color: var(--text-muted);
  text-wrap: pretty;
}

@media (max-width: 48rem) {
  .capability-grid {
    grid-template-columns: 1fr;
    gap: var(--space-6);
    margin-top: var(--space-8);
    /* One column at tablet width would otherwise run the full 45rem: the cap
       keeps the description near 70 characters. Below ~34rem it does nothing,
       so the phone is unaffected. */
    max-width: 34rem;
  }
}

/* The landing's own cut of the grid: one line per capability, two columns,
   ruled like a ledger. Six cards of bold-then-muted prose took four hundred
   pixels to say what six lines say — and the page already argues its case in
   the floors below, so this only has to be scannable. This modifier is the
   landing's. After the base media
   query, so its one-column rule doesn't win the cascade over the two below. */

/* One grid for the whole list — picture, name, clause — and every job a row
   of it (subgrid), so the name column is exactly as wide as the longest name
   and the clauses start one step after it. A fixed column for the names left
   a hole between a short name and its clause, wide enough that the clauses
   read as a second, unnamed column. The list fills its column, so its
   hairlines end on the wrap's right edge; stacked, the demo's cap is its cap
   too, or they would run on into air. */
.capability-grid--marks {
  grid-template-columns: 2.5rem max-content minmax(0, 1fr);
  gap: 0 var(--space-4);
  margin-top: 0;
  max-width: 44rem;
}

/* Rows are parted by a hairline over each, except the first, which has
   nothing above it to part from and stands on the claim's first line. Name
   and clause share a baseline: they are two sizes, and centred on their
   boxes they sat a pixel apart. */
.capability-grid--marks > div {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: baseline;
  padding: var(--space-3) 0;
  border-top: 1px solid var(--hairline);
}

.capability-grid--marks > div:first-child { padding-top: 0; border-top: 0; }

/* The picture and the name are one cell's children in the markup; laid out
   as the row's own, so the name starts on one vertical for all six. */
/* Both lines of text take the picture's own height, so the words stand on
   the picture's middle: at their natural leading they hung from the top of
   the row and the picture sat a few pixels under them. */
.capability-grid--marks dt {
  display: contents;
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 2rem;
  white-space: nowrap;
}

.capability-grid--marks dd {
  padding-left: var(--space-4);
  font-size: 0.9375rem;
  line-height: 2rem;
  color: var(--text-muted);
  white-space: nowrap;
}

/* A clay picture per job in one box for all six, wider than tall: fitted to
   a square, the round and the upright ones filled it and the wide ones — the
   card, the megaphone — came out a third smaller. Centred on the line, not
   on its baseline. --fit is the mark's own correction on top of the box (set
   beside each picture in the view): it evens out how much clay each one
   shows. It sizes the box to an even whole pixel and margins give the
   difference back, so no row moves for it and the picture stays centred on a
   whole pixel; a scale() transform left it on fractions (41.6px tall at 1.3,
   2026-10-14). On the name's own 32px line, not on the row: name and clause
   on one baseline make the row 33px, and centred on that the picture stood on
   a half pixel. */
.capability-grid__mark {
  --w: round(2.5rem * var(--fit, 1), 2px);
  --h: round(2rem * var(--fit, 1), 2px);
  align-self: start;
  width: var(--w);
  height: var(--h);
  margin: calc((2rem - var(--h)) / 2) calc((2.5rem - var(--w)) / 2);
  object-fit: contain;
}


/* ===== Vision =====
   One statement in the middle of the page, at the size of the cover's own
   headline and with twice a floor's air round it: the only floor that is
   nothing but a sentence, so it is set as one. No rule over it or under it —
   a line either side would file it between its neighbours. */
.marketing-section.vision {
  padding: calc(2 * var(--floor-pad)) 0;
  text-align: center;
}

/* The disclaimer's label, in the muted ink: this one names, that one warns. */
.marketing-section .vision__label {
  /* The section's paragraphs are capped and so sit at the left of a wide
     floor; this one takes the floor's width and centres with the rest. */
  max-width: none;
  margin: 0 0 var(--space-6);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Three lines at every width, broken at the sense: the stance on a line of
   its own, then the claim in two ("an agent can run / a whole company"), so
   no line ends on an article. The page's largest type, so its tightest:
   leading at the size itself and the tracking a step closer than the floors'
   headings. */
.marketing-section h2.vision__claim {
  /* Even, so centred on an even floor it starts on a whole pixel (2026-10-14). */
  max-width: round(down, 18ch, 2px);
  margin: 0 auto var(--space-8);
  font-size: round(clamp(2.25rem, 6vw, 4.5rem), 1px);
  font-weight: 800;
  letter-spacing: -0.04em;
  --lh: 1;
  text-wrap: balance;
}

.vision__stance { display: block; }

/* The line the floor is for, so it is set to be read and not as a caption:
   a third of the claim's size, where a fifth left it as small print under a
   poster. One ink and one weight for all of it: the turn is carried by the
   words and by standing on a line of its own. */
.marketing-section .vision__why {
  max-width: none;
  margin: 0 auto;
  font-size: round(clamp(1.25rem, 2.2vw, 1.75rem), 1px);
  letter-spacing: -0.015em;
  /* Two sentences, each its own line: at a paragraph's leading they read as
     one wrapped sentence, so they stand a little further apart. */
  --lh: 1.6;
  color: var(--text-muted);
}



/* A phone wraps each sentence: they keep a paragraph's leading inside and a
   step of air between, or four even lines read as one sentence; and each
   wraps in two even lines instead of leaving two words alone. */
@media (max-width: 40rem) {
  .marketing-section .vision__why { --lh: 1.35; }
  .vision__why > span { display: block; text-wrap: balance; }
  .vision__why > span:last-child { margin-top: var(--space-3); }
  .vision__why > br { display: none; }
}

/* Narrow: the clause drops under its name, beside the picture, and the list
   takes the column. */
@media (max-width: 48rem) {
  .capability-grid--marks { grid-template-columns: 2.5rem minmax(0, 1fr); }

  .capability-grid--marks > div { align-items: center; }

  .capability-grid__mark { grid-row: 1 / span 2; align-self: center; }

  .capability-grid--marks dt { --lh: 1.35; }

  .capability-grid--marks dd { grid-column: 2; padding-left: 0; --lh: 1.5; white-space: normal; }
}


/* ===== Work loop =====
   One task running, on a loop, in the two panes the real company has: the
   shell the agent types in and the browser it drives. Both run off one step
   number (workloop_controller) — the `[computer] click` line and the cursor
   landing on the button are the same beat, and a click that happened in only
   one pane would be the whole point missed.

   Screen surfaces, so the darks are literal and not themed: the shell is the
   terminal's own #0d1117, the window chrome its #161b22, and the page inside
   the browser stays a light page because that is what a page is. Nothing here
   changes layout as it plays — every line holds its row from the first frame. */

.worklog {
  /* The section's own width, like every other block on the page: a panel that
     stops 11rem short of the right edge reads as a column that missed. */
  margin: 0;
  /* Narrow enough that the app inside fills its window: wider than this and the
     page keeps a hand's width of empty white down its right side. */
  max-width: 44rem;
  /* Local to this panel, like the simulator's: a pointer is not part of the
     interface mark set. Drawn twice in the one file — a white stroke under a
     dark fill — because a single-colour arrow disappears into a dark row or a
     coloured button the moment it lands on one. */
  --worklog-cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 3v16.2l4.1-3.8 2.5 5.6 2.8-1.3-2.5-5.4 5.5-.4z' fill='%230f172a' stroke='%23ffffff' stroke-width='2.4' stroke-linejoin='round'/%3E%3Cpath d='M6 3v16.2l4.1-3.8 2.5 5.6 2.8-1.3-2.5-5.4 5.5-.4z' fill='%230f172a'/%3E%3C/svg%3E");
}

/* No shell of its own: the panel IS the window, with the log and the subtitles
   living inside it. */
.worklog__panes {
  position: relative;
  display: block;
}

.worklog__screen {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 0.5rem 1.75rem rgba(15, 23, 42, 0.14), 0 0 0 1px rgba(15, 23, 42, 0.06);
}

/* A laptop's screen, chrome included: one window, with the log and the
   subtitles living inside it rather than competing for the eye beside it. */
.worklog__screen {
  position: relative;
  background: #ffffff;
  /* 16:10, a laptop's own ratio. The extra height over 16:9 is not empty: it is
     the strip the log and the subtitles sit in, which is how they stay off the
     rows — a name hidden under the log is the context of the screen gone. */
  aspect-ratio: 16 / 10;
}

/* ===== The subtitles =====
   The one line that says what is happening, in the words someone would use to
   say it, sitting where a film puts them: over the picture, near its foot. The
   log beside it is the machine's account of the same beat, so reading that is
   optional. Beats are long enough to read this one — see workloop_controller. */

.worklog__now {
  position: absolute;
  left: var(--space-3);
  bottom: var(--space-3);
  z-index: 2;
  max-width: calc(100% - 1.5rem);
  display: flex;
  align-items: center;
  gap: 0.4375rem;
  padding: 0.3125rem 0.6875rem;
  border-radius: var(--radius-pill);
  background: rgba(15, 23, 42, 0.88);
  transition: background var(--dur) ease;
  overflow: hidden;
  box-shadow: 0 0.5rem 1.5rem rgba(15, 23, 42, 0.22);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Every line in one cell, so the bar can't change width mid-sentence — which
   also means the pill is as wide as the longest of the eight. Centred, each
   shorter line sat at its own x and the mark jumped left and right on every
   beat; flush left, the mark and the first letter hold one vertical for the
   whole run and only the tail moves. It is also where the fill starts. */
.worklog__acts {
  position: relative;
  display: grid;
  min-width: 0;
}

.worklog__act {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  gap: round(0.5em, 1px);
  min-width: 0;
  /* The panel's reading size, the letter's own: four sizes in the whole mock
     — 0.625 for what is glanced at (tabs, times, pills, counts), 0.6875 for
     what is scanned (rows, the sidebar, the address), 0.75 for what is read
     (the letter, this line), 0.875 for a page's title. Six sizes within three
     pixels of each other read as none. */
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  /* Literal light ink: this rides on a dark bar over the page, not on chrome. */
  color: #f1f5f9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transform: translateY(0.1875rem);
  /* The line that is leaving goes first and quickly; the one arriving waits for
     it, then eases in over twice as long. Cross-faded at the same instant, the
     two sat on top of each other and the swap read as a flicker. */
  transition: opacity 160ms ease-in, transform 160ms ease-in;
}

.worklog__act.is-on {
  opacity: 1;
  transform: none;
  transition: opacity 320ms cubic-bezier(0.22, 0.61, 0.36, 1) 120ms,
              transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1) 120ms;
}

/* Only the ending keeps a glyph. Through the run the words already say what is
   happening in fewer characters than the icon takes to read, and seven glyphs
   swapping in ten seconds is one more moving thing beside a page where the real
   movement — the pointer, the click, the row — is the point. The check is the
   exception: it marks a state, not an action. */
.worklog__act .mark { display: none; }

.worklog__act--done .mark {
  display: inline-block;
  width: round(1.05em, 1px);
  height: round(1.05em, 1px);
  margin-right: 0;
  color: #4ade80;
}

/* The one beat where the screen has nothing to show: a still panel reads as a
   stall, so the clock breathes through it. */
.worklog[data-step="7"] .worklog__act.is-on .mark {
  animation: worklog-waiting 1.4s ease-in-out infinite;
}

@keyframes worklog-waiting {
  50% { opacity: 0.35; }
}

/* The bubble IS the bar: the whole pill fills, which is what makes it read as
   one modern object rather than as a caption with a rail bolted under it. */
.worklog__progress {
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.worklog__progress-fill {
  display: block;
  height: 100%;
  width: var(--progress, 0%);
  /* The leading edge fades out over its last 1.25rem instead of cutting the
     sentence with a vertical line — that hard edge was the only thing wrong
     with filling the pill. */
  background: linear-gradient(90deg,
    rgba(125, 211, 252, 0.17) 0,
    rgba(125, 211, 252, 0.17) calc(100% - 1.25rem),
    rgba(125, 211, 252, 0) 100%);
  /* Linear and exactly as long as the beat it crosses: the controller hands it
     both the target and the time it has to get there, so the line crawls like a
     player's scrubber instead of dashing and waiting. */
  transition: width var(--progress-dur, 420ms) linear, background var(--dur) ease;
}

/* Full and paid: the bubble goes deep green, and the fill drops its fading
   tail — at 100% that fade left the last 1.25rem of the pill looking unfilled,
   so the bar seemed to stop just short of the end. */
.worklog:is([data-step="8"], [data-step="9"]) .worklog__now {
  background: rgba(6, 78, 59, 0.94);
}

/* The loop's restart is a cut, not a rewind: the bubble would otherwise fade
   green to navy in front of the visitor. The bar's own rewind is cut in the
   controller, which has to restore its transition immediately afterwards. */
.worklog[data-step="0"] .worklog__now {
  transition: none;
}

.worklog:is([data-step="8"], [data-step="9"]) .worklog__progress-fill {
  background: rgba(134, 239, 172, 0.16);
}

/* ===== The window chrome =====
   A tab strip over an address bar, because the agent changing app is the
   middle of the story and a 10px hostname does not tell it.

   Light, like the browser on most desks and like the pages it shows: the dark
   chrome it replaced put a slab of night on top of two white apps and made the
   panel read as a terminal with a page in it. */

.worklog__chrome {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  background: #dee1e6;
}

.worklog__tabs {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.4375rem 0.625rem 0;
}

/* 8px, an even dot centred on the tabs' even line: at 7 it stood on a half
   pixel (2026-10-14). */
.worklog__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-pill);
  background: #c3c7ce;
  flex: 0 0 auto;
}

.worklog__dot:nth-of-type(3) { margin-right: 0.375rem; }

.worklog__tab {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  max-width: 11rem;
  padding: 0.375rem 0.625rem;
  border-radius: 0.5rem 0.5rem 0 0;
  font-size: 0.6875rem;
  font-weight: 600;
  color: #5f6368;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background var(--dur) ease, color var(--dur) ease;
}

.worklog__tab.is-on {
  background: #ffffff;
  color: #202124;
}

/* The favicon is the fastest signal in a tab strip, so each app keeps its
   own — drawn, not borrowed: a coloured square is not a logo. */
.worklog__favicon {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 0.125rem;
  flex: 0 0 auto;
}

.worklog__favicon.is-mail { background: #ea4335; }
.worklog__favicon.is-stripe { background: #635bff; }

.worklog__address {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem var(--space-3) 0.5rem;
  background: #ffffff;
  /* The toolbar and the page are both white; without this line the chrome and
     the app it frames run into each other. */
  box-shadow: inset 0 -1px 0 rgba(15, 23, 42, 0.09);
}

.worklog__address .mark {
  width: 0.75rem;
  height: 0.75rem;
  margin-right: 0;
  color: #5f6368;
}

.worklog__url {
  flex: 1;
  padding: 0.1875rem 0.5rem;
  border-radius: var(--radius-pill);
  background: #f1f3f4;
  color: #202124;
  font-size: 0.75rem;
  --lh: 1.5;
}

/* Both addresses sit in the one pill; only the current one is laid out, so the
   bar can't grow or shrink when the agent navigates. */
.worklog__host { display: none; }
.worklog__host.is-on { display: inline; }

/* Before the controller has counted once there is no data-step on the panel,
   and nothing is `is-on`: the address pill had no line to hold, so the chrome
   grew a row on every reload, and the tab strip flashed from blank to lit. The
   first frame is drawn here instead — mail open, mail lit. */
.worklog:not([data-step]) .worklog__host[data-until] { display: inline; }

.worklog:not([data-step]) .worklog__tab[data-until] {
  background: #ffffff;
  color: #202124;
}

/* Only the opening line: every act carries a `data-until`, and lighting all
   of them printed the whole script on top of itself. */
.worklog:not([data-step]) .worklog__act:not([data-at]) { opacity: 1; transform: none; }

/* ===== The apps =====
   Everything below is someone ELSE's product seen through the browser — a mail
   client, a payments dashboard. They carry their own colours so they are
   recognised at a glance; those colours are literal and never become tokens. */

.worklog__page {
  position: relative;
  flex: 1;
  display: grid;
  min-height: 0;
}

/* Positioned, so each view paints as one unit: unpositioned boxes paint every
   background first and every line of text after, which let one page's rows read
   straight through the opaque page on top of them. */
.worklog__view {
  position: relative;
  grid-area: 1 / 1;
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3) 3.25rem;
  background: #ffffff;
  transition: opacity 260ms ease-in-out;
}

.worklog__view[data-at] { opacity: 0; }
.worklog__view[data-at].is-on { opacity: 1; }

.worklog__view--mail { --app-ink: #1a73e8; }
.worklog__view--pay  { --app-ink: #635bff; }

/* The furniture down the left of both apps: what makes a page read as an app
   rather than as a list on white. */
.worklog__nav {
  display: flex;
  flex-direction: column;
  gap: 0.1875rem;
  width: 6.5rem;
  flex: 0 0 auto;
  font-size: 0.75rem;
}

.worklog__compose {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  align-self: flex-start;
  margin-bottom: var(--space-2);
  padding: 0.375rem 0.625rem;
  border-radius: var(--radius-pill);
  background: #c2e7ff;
  color: #001d35;
  font-weight: 700;
}

/* 15px, odd like the button's 31px: at 14 it was centred on a half pixel
   (2026-10-14). */
.worklog__compose .mark {
  width: 0.9375rem;
  height: 0.9375rem;
  margin-right: 0;
}

/* Inset to the nav items' own padding, so the wordmark and the labels sit on
   one vertical and only the active pill hangs into the gutter — which is what a
   sidebar's pill is for. */
.worklog__brand {
  padding-inline: 0.625rem;
  margin-bottom: var(--space-3);
  color: #635bff;
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: -0.03em;
}

.worklog__nav-item {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.3125rem 0.625rem;
  border-radius: var(--radius-pill);
  color: #5f6368;
  font-weight: 500;
}

.worklog__nav-item.is-on {
  background: color-mix(in srgb, var(--app-ink) 12%, transparent);
  color: var(--app-ink);
  font-weight: 700;
}

/* The count's line as tall as the label's 19px, so the item does not centre
   it on a half pixel (2026-10-14). */
.worklog__nav-count {
  margin-left: auto;
  font-size: 0.6875rem;
  --lh: 1.7;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* The column's own rhythm is a step tighter than the page's: at 12 the head,
   the card, the table and the button did not fit above the subtitles, and the
   button ended up on the bubble's shoulder.

   The inset lives HERE, and the blocks that are meant to bleed (the rows, the
   search bar, the card, the action row) are pulled back out by the same step —
   so every line of text starts on one vertical and only tinted grounds run
   wider than it, which is what those grounds are for. */
.worklog__app {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-inline: var(--space-3);
  flex: 1;
  min-width: 0;
  max-width: 34rem;
}

/* The bar belongs to the window, not to the list or the letter under it, so it
   keeps a step more air than the column's own rhythm gives. */
.worklog__search {
  margin-block: 0 var(--space-2);
  margin-inline: calc(var(--space-3) * -1);
  padding: 0.375rem var(--space-3);
  border-radius: var(--radius-pill);
  background: #f1f3f4;
  color: #80868b;
  font-size: 0.75rem;
}

.worklog__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
}

.worklog__page-title {
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #0a2540;
}

.worklog__chip {
  padding: 0.0625rem 0.5rem;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--app-ink) 12%, transparent);
  color: var(--app-ink);
  font-size: 0.6875rem;
  font-weight: 600;
}

/* The rows follow the title and anything under them follows the rows:
   stretching the list opened a white hole in the middle of the page at every
   width where the box is tall. */
.worklog .worklog__list {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  list-style: none;
  /* Out by the column's own inset, so the tinted rows run the full width while
     their text keeps the one vertical. The shorthand has to come before the
     inline margin, or it resets it. */
  margin: 0 calc(var(--space-3) * -1);
  max-width: none;
  padding: 0;
  width: auto;
}

.worklog .worklog__mail,
.worklog .worklog__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0.3125rem var(--space-3);
  border-radius: 0.5rem;
  font-size: 0.75rem;
  --lh: 1.5;
}

/* A payments table is a table: hairlines, not cards, and nothing ruled off
   under the last row. */
.worklog .worklog__row {
  border-radius: 0;
  border-bottom: 1px solid #e6e9ef;
}

.worklog .worklog__row:last-child { border-bottom: none; }

/* The row the agent is working, tinted from the beat it is clicked, so the page
   agrees with the log about which one it is. */
/* Under the pointer, not before it: each target lights up 700ms into its beat,
   which is how long the cursor takes to cross to it. The delay rides on the
   hover rule itself, so the press that follows is still instant. */
.worklog:is([data-step="1"], [data-step="2"]) .worklog__mail.is-target {
  background: #e8f0fe;
  transition: background var(--dur) ease 700ms;
}

/* Held back until the pointer has actually crossed to it — the travel takes
   760ms — and lighter than the lit tab, because a hover is not a state. */
/* Pressed, for the beat of the click itself — the row and the button, not the
   tab: a browser tab doesn't depress, it just becomes the one in front. */
.worklog[data-step="2"] .worklog__mail.is-target {
  background: #d2e3fc;
  transition: background 90ms ease;
}


.worklog[data-step="6"] .worklog__button {
  transform: scale(0.96);
  background: #4f46e5;
  transition: transform 90ms ease, background 90ms ease;
}

.worklog[data-step="3"] .worklog__tab[data-at] {
  background: rgba(255, 255, 255, 0.55);
  /* The label carries most of the hover: between the strip and the white tab
     there is not enough room for a background to say it on its own. */
  color: #202124;
  transition: background var(--dur) ease 700ms, color var(--dur) ease 700ms;
}

.worklog[data-step="5"] .worklog__button {
  background: #4f46e5;
  transform: translateY(-1px);
  transition: background var(--dur) ease 700ms, transform var(--dur) var(--ease-out) 700ms;
}

.worklog .worklog__mail.is-new { background: #f8fafd; }

.worklog__who {
  font-weight: 700;
  color: #202124;
  white-space: nowrap;
}

/* Read letters at the running weight, the new one bold with its subject in
   ink: the way a mail client says which row is news, and what leads the eye
   to Rosa before the pointer does. Every sender bold was a column of
   headings. */
.worklog__mail .worklog__who { font-weight: 500; }
.worklog__mail.is-new .worklog__who { font-weight: 700; }
.worklog__mail.is-new .worklog__subject { color: #202124; font-weight: 600; }
.worklog__mail.is-new .worklog__time { color: #202124; font-weight: 600; }

.worklog__subject {
  min-width: 0;
  color: #5f6368;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* An initial in a disc — what every mail client draws, and what makes a column
   of rows read as people. */
.worklog__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.375rem;
  height: 1.375rem;
  border-radius: var(--radius-pill);
  font-size: 0.6875rem;
  font-weight: 700;
  color: #ffffff;
  flex: 0 0 auto;
}

.worklog__avatar.is-teal   { background: #0f9d8f; }
.worklog__avatar.is-amber  { background: #e8890c; }
.worklog__avatar.is-violet { background: #7c4dff; }
.worklog__avatar.is-blue   { background: #1a73e8; }

/* An 18px line like the sender's and the subject's, so the row centres all
   three on one whole pixel (2026-10-14). */
.worklog__time {
  margin-left: auto;
  font-size: 0.6875rem;
  --lh: 1.65;
  color: #5f6368;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

.worklog__amount {
  margin-left: auto;
  min-width: 4rem;
  text-align: right;
  font-weight: 600;
  color: #0a2540;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

/* Stripe's own vocabulary of states: pastel fill, dark ink, and only the paid
   one is green. */
.worklog__state {
  display: grid;
  justify-items: end;
  min-width: 2.75rem;
  flex: 0 0 auto;
}

.worklog__state .worklog__pill { grid-area: 1 / 1; }

/* 16px line + 2px of padding = the rows' 18px text line: a 19px pill made
   every row centre its text on a half pixel (2026-10-14). */
.worklog__pill {
  --lh: 1.45;
  padding: 0.0625rem 0.5rem;
  border-radius: var(--radius-pill);
  background: #cbf4c9;
  color: #0e6245;
  font-size: 0.6875rem;
  font-weight: 600;
  flex: 0 0 auto;
}

.worklog__pill.worklog__pill--draft { background: #e3e8ee; color: #4f566b; }
.worklog__pill.worklog__pill--sent  { background: #d6ecff; color: #3d4eac; }

/* A 20px line beside the 22px avatar, an even difference: at 19 the name
   stood on a half pixel (2026-10-14). */
.worklog__from {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.75rem;
  --lh: 1.7;
}

/* The letter goes on past the line worth reading — as two grey bars, because
   the rest of a mock letter is not for reading. */
.worklog__bar {
  width: 100%;
  height: 0.5rem;
  border-radius: var(--radius-pill);
  background: #eef1f6;
}

.worklog__bar--short { width: 42%; }

/* Two ghost buttons under the letter, as a mail client draws them. */
.worklog__reply {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.worklog__reply span {
  padding: 0.25rem 0.75rem;
  border: 1px solid #dadce0;
  border-radius: var(--radius-pill);
  color: #5f6368;
  font-size: 0.75rem;
  font-weight: 500;
}

/* The one line of the letter worth reading: it is what makes the invoice that
   follows obviously the right invoice. */
.worklog__said {
  max-width: 28rem;
  font-size: 0.75rem;
  --lh: 1.7;
  color: #202124;
}

/* ===== The money =====
   A balance, the week behind it, and the moment it moves. */

.worklog__card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: auto;
  margin-inline: calc(var(--space-3) * -1);
  padding: var(--space-2) var(--space-3);
  border-radius: 0.75rem;
  background: linear-gradient(135deg, #f5f4ff 0%, #ffffff 55%, #f2fbf6 100%);
  box-shadow: inset 0 0 0 1px #e6e4ff;
  transition: box-shadow var(--dur-slow) var(--ease-out);
}


.worklog__balance {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}

/* A label in sentence case at the meta size: tracked capitals were the one
   shout on a quiet card, and the dashboard this imitates does not use them. */
.worklog__balance-label {
  font-size: 0.6875rem;
  font-weight: 600;
  color: #697386;
}

/* Both figures ride in one cell, so the balance changing can't move the chart
   under it, and the grid keeps them at the left. */
.worklog__money {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  align-items: baseline;
  gap: var(--space-2);
}

.worklog__figure {
  grid-area: 1 / 1;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #0a2540;
  font-variant-numeric: tabular-nums;
}

.worklog__figure.is-on { animation: worklog-pop 420ms cubic-bezier(0.34, 1.56, 0.64, 1); }

@keyframes worklog-pop {
  0% { transform: scale(0.94); }
  60% { transform: scale(1.03); }
  100% { transform: scale(1); }
}

.worklog__delta {
  grid-column: 2;
  padding: 0.0625rem 0.4375rem;
  border-radius: var(--radius-pill);
  background: #cbf4c9;
  color: #0e6245;
  font-size: 0.75rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* A week of takings beside the figure, filling the card's other half. The
   bars stand on the figure's own baseline: centred in the card they floated
   between the label and the number, belonging to neither. */
.worklog__chart {
  display: flex;
  align-items: flex-end;
  align-self: flex-end;
  gap: 0.4375rem;
  flex: 0 1 10.5rem;
  height: 1.75rem;
  margin-bottom: 0.3125rem;
}

/* Each bar's share of the 28px chart is rounded to a whole pixel, so its top
   lands on one (2026-10-14). */
.worklog__chart span {
  flex: 1;
  min-width: 0;
  height: round(var(--h, 40%), 1px);
  border-radius: 0.125rem;
  background: rgba(99, 91, 255, 0.28);
}

/* The day the money lands: the bar grows into it and turns green. */
.worklog__bar-live {
  height: round(20%, 1px);
  background: rgba(99, 91, 255, 0.5);
  transition: height var(--dur-slow) var(--ease-out), background var(--dur-slow) ease;
}

.worklog:is([data-step="8"], [data-step="9"]) .worklog__bar-live {
  height: 100%;
  background: #0e9f6e;
}

/* Confetti around the display, not inside the dashboard: two cannons at the
   foot of the window firing up and out past its edges, once, on the beat the
   money lands. It sits on the panel rather than in the page, because a
   celebration that stops at the frame is not one. */
.worklog__confetti {
  position: absolute;
  bottom: 8%;
  z-index: 3;
  pointer-events: none;
}

.worklog__confetti--left { left: 3%; }

/* The right cannon is the left one mirrored — same throws, opposite side. */
.worklog__confetti--right { right: 3%; transform: scaleX(-1); }

.worklog__confetti span {
  position: absolute;
  width: 0.4375rem;
  height: 0.625rem;
  border-radius: 0.0625rem;
  opacity: 0;
}

/* After the bar is full, not with it: the celebration was going off while the
   progress still had a step to run. */
.worklog__confetti.is-on span {
  animation: worklog-confetti 1600ms cubic-bezier(0.12, 0.75, 0.3, 1) forwards;
  animation-delay: calc(460ms + var(--d, 0ms));
}

@keyframes worklog-confetti {
  0% { opacity: 0; transform: translate(0, 0) rotate(0) scale(0.4); }
  10% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(var(--r)) scale(1); }
}

.worklog__confetti span:nth-child(1) { --dx: -3rem;  --dy: -9rem;  --r: -260deg; background: #7c4dff; --d: 0ms; }
.worklog__confetti span:nth-child(2) { --dx: 1rem;   --dy: -13rem; --r: 200deg;  background: #0e9f6e; --d: 60ms; }
.worklog__confetti span:nth-child(3) { --dx: 5rem;   --dy: -16rem; --r: -140deg; background: #e8890c; --d: 30ms; }
.worklog__confetti span:nth-child(4) { --dx: 10rem;  --dy: -14rem; --r: 300deg;  background: #1a73e8; --d: 110ms; }
.worklog__confetti span:nth-child(5) { --dx: 15rem;  --dy: -11rem; --r: -180deg; background: #7c4dff; --d: 45ms; }
.worklog__confetti span:nth-child(6) { --dx: 20rem;  --dy: -7rem;  --r: 240deg;  background: #0e9f6e; --d: 150ms; }
.worklog__confetti span:nth-child(7) { --dx: -6rem;  --dy: -5rem;  --r: -220deg; background: #e8890c; --d: 90ms; }
.worklog__confetti span:nth-child(8) { --dx: 25rem;  --dy: -3rem;  --r: 160deg;  background: #1a73e8; --d: 190ms; }

/* Right under the invoice it sends, not pinned to the floor: on a page with one
   row the button sat alone at the bottom of a white field. */
.worklog__actions {
  display: flex;
  justify-content: flex-end;
  margin: var(--space-3) calc(var(--space-3) * -1) 0;
}

.worklog__button {
  padding: 0.3125rem 0.75rem;
  border-radius: 0.375rem;
  background: #635bff;
  color: #ffffff;
  font-size: 0.75rem;
  font-weight: 700;
  box-shadow: 0 1px 2px rgba(10, 37, 64, 0.2);
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast) ease;
}

/* Everything the loop turns on and off shares one entrance: up a little, in. */
.worklog__pill,
.worklog__figure,
.worklog__delta,
.worklog__actions {
  opacity: 0;
  transform: translateY(0.3125rem);
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out);
}

.worklog__pill.is-on,
.worklog__figure.is-on,
.worklog__delta.is-on,
.worklog__actions.is-on {
  opacity: 1;
  transform: none;
}

/* A pill that is simply there, not one the loop turns on: only the timed ones
   carry a window. */
.worklog__pill:not([data-at]):not([data-until]) { opacity: 1; transform: none; }

/* The carrier is the page box, so its translate percentages ARE page
   percentages — the cursor rides at its origin and the box does the moving,
   which is what lets one transition ease a click across the page. */
.worklog__carrier {
  position: absolute;
  inset: 0;
  pointer-events: none;
  --cx: 74%;
  --cy: 86%;
  transform: translate(var(--cx), var(--cy));
  /* A hand's travel, not a cut: long and decelerating, so the click looks
     aimed. */
  transition: transform 760ms cubic-bezier(0.32, 0.72, 0.28, 1);
}

/* The tip lands on the row, then on the button's lower edge — never across the
   label it is about to press, which reads as a typo. */
/* On Rosa's row from the beat before the click, and on the button from the
   beat the invoice is written: the hand arrives, then presses. A pointer that
   lands at the same instant as the page it opened reads as the page opening
   itself. */
/* Measured against the real boxes, not guessed: a quarter into Rosa's row, on
   the Stripe tab (above the page, hence the negative y), and inside the Send
   button below its label. tmp/ops/worklog/aim.js reads all three back as
   percentages of the page, which is what the carrier translates by; run it
   again after anything that moves a row, the tab strip or the button. */
.worklog[data-step="1"] .worklog__carrier,
.worklog[data-step="2"] .worklog__carrier { --cx: 40.3%; --cy: 43.3%; }

.worklog[data-step="3"] .worklog__carrier,
.worklog[data-step="4"] .worklog__carrier { --cx: 28.4%; --cy: -15.7%; }

/* The hand stays where it clicked — it has nothing else to do — but relaxes a
   few points once the button is gone from under it. */
.worklog:is([data-step="5"], [data-step="6"]) .worklog__carrier { --cx: 93.7%; --cy: 78.9%; }

.worklog:is([data-step="7"], [data-step="8"], [data-step="9"]) .worklog__carrier { --cx: 90%; --cy: 85.2%; }

.worklog__cursor {
  position: absolute;
  width: 0.9375rem;
  height: 0.9375rem;
  background: var(--worklog-cursor) center / contain no-repeat;
  filter: drop-shadow(0 1px 1.5px rgba(15, 23, 42, 0.35));
}

.worklog__ping {
  position: absolute;
  width: 1.75rem;
  height: 1.75rem;
  margin: -0.625rem 0 0 -0.625rem;
  border: 1.5px solid var(--accent);
  border-radius: var(--radius-pill);
  opacity: 0;
}

.worklog__ping.is-on { animation: worklog-ping 600ms var(--ease-out); }

@keyframes worklog-ping {
  from { opacity: 0.9; transform: scale(0.25); }
  to { opacity: 0; transform: scale(1); }
}

@media (max-width: 48rem) {
  /* The browser goes 4:3: at 16:10 a tablet-width window is short enough to
     cut the page off after three rows. */
  .worklog__screen { aspect-ratio: 4 / 3; }

  /* The page is a different shape here, so the targets are in different places:
     measured again at this width, not scaled from the desktop's. */
  .worklog[data-step="1"] .worklog__carrier,
  .worklog[data-step="2"] .worklog__carrier { --cx: 37.5%; --cy: 29.3%; }

  .worklog[data-step="3"] .worklog__carrier,
  .worklog[data-step="4"] .worklog__carrier { --cx: 24.5%; --cy: -10.6%; }

  .worklog:is([data-step="5"], [data-step="6"]) .worklog__carrier { --cx: 91.8%; --cy: 53.3%; }

  .worklog:is([data-step="7"], [data-step="8"], [data-step="9"]) .worklog__carrier { --cx: 88.1%; --cy: 59.6%; }
}

/* Phone. The browser turns portrait, because 4:3 at 21rem wide is still not
   tall enough for a balance, three rows and the button under them; the log
   drops a step in size, since half its lines wrap at this width; and the strip
   keeps the words and loses the progress line, which is the one thing there
   that says nothing on its own. */
@media (max-width: 30rem) {
  /* Square, not portrait: at 3:4 the page filled its top half and the rest was
     a white field with the subtitles floating at the bottom of it. */
  .worklog__screen { aspect-ratio: 1 / 1; }
  /* Two lines of log on a phone: the page underneath is the thing being
     watched, and the tail is the receipt. */

  /* One invoice is the story; the two settled ones are context a phone has no
     room for, and with them the page ran past the foot of the window. */
  .worklog__row:not(.is-target) { display: none; }

  /* Four letters and no reply bar: a square window ends where the subtitle
     starts, and a fifth row or a pair of buttons would sit under it. */
  .worklog__mail:nth-child(n + 5),
  .worklog__reply { display: none; }

  /* The week draws narrower, so the amount that lands beside the balance
     has room and does not run under the bars. */
  /* 72px less six 5px gaps is seven 6px bars; at 4px gaps each bar was
     6.86px and the week stood on fractions (2026-10-14). */
  .worklog__chart { flex-basis: 4.5rem; gap: 0.3125rem; }

  .worklog[data-step="1"] .worklog__carrier,
  .worklog[data-step="2"] .worklog__carrier { --cx: 26.8%; --cy: 49.4%; }

  .worklog[data-step="3"] .worklog__carrier,
  .worklog[data-step="4"] .worklog__carrier { --cx: 50.5%; --cy: -17.9%; }

  .worklog:is([data-step="5"], [data-step="6"]) .worklog__carrier { --cx: 88.9%; --cy: 67%; }

  .worklog:is([data-step="7"], [data-step="8"], [data-step="9"]) .worklog__carrier { --cx: 85.2%; --cy: 73.3%; }

  /* No sidebar on a phone — which is also what these apps do at this width,
     and what keeps the rows from running off the right edge. */
  .worklog__nav { display: none; }

  .worklog__act {
    font-size: 0.8125rem;
    white-space: normal;
  }

  /* 15px, odd like the 21px line it is centred on: 1.05em came to 14 and
     stood on a half pixel (2026-10-14). */
  .worklog__act--done .mark { width: 0.9375rem; height: 0.9375rem; }

  .worklog__now { max-width: calc(100% - 1.5rem); }
  .worklog__progress { display: none; }
  .worklog__time { display: none; }
  .worklog__figure { font-size: 1.25rem; }
}

/* Reduced motion keeps the story and drops the travel: pieces still turn on,
   they just stop sliding and the cursor stops crossing the page. */
@media (prefers-reduced-motion: reduce) {
  .worklog__view,
  .worklog__pill,
  .worklog__figure,
  .worklog__delta,
  .worklog__actions,
  .worklog__carrier,
  .worklog__button {
    transition: none;
  }

  .worklog__pill,
  .worklog__figure,
  .worklog__delta,
  .worklog__actions {
    transform: none;
  }

  .worklog__ping.is-on,
  .worklog__confetti.is-on span,
  .worklog[data-step="7"] .worklog__act.is-on .mark { animation: none; }
}

/* The demo panel rides ON the cover, between the promise and the ask — the
   product is the fold's argument, so it must not wait for a scroll. Hero
   children inherit the cover's white text-shadow; the panel is a surface of
   its own and takes none of it. */
.demo-stage {
  width: 100%;
  max-width: 48rem;
  /* The cover is three groups — promise, demo, ask — and the air between two
     groups has to beat the air inside one, or six centred rows read as a list.
     The ask gets the most air on the cover: under the picker it has to read
     as its own group, not as a third row of the demo's controls. */
  margin: var(--space-4) 0 var(--space-12);
  text-shadow: none;
}

/* .site-footer left with the /companies empty-desk page (2026-08-25) — the
   marketing layout carries its own .marketing-footer. */


/* ===== Demo simulator =====
   The landing's one moving explanation, in the two things its reader already
   knows: a conversation on the left — you ask, the agent answers and works
   through its list — and on the right the page it builds, which ends with
   money arriving. No window bar, task rail or status strip: those are how
   software looks to people who run software. The timeline is a step number
   set by demo_controller; everything here only says what a piece looks like
   ON (.is-on) and OFF. Nothing changes layout as it plays: both columns hold
   their height from the start, so the panel never jumps mid-loop. */

.demo-sim {
  display: grid;
  /* Six to five, the conversation the wider: it is the half that is read,
     and at an even split the page — a picture in a card in a tinted field —
     outweighed it. At this width the page stands as a page does, a little
     taller than wide, its picture comes out at sixteen to ten instead of a
     strip, and the longest offer still holds one line (a column narrower
     and it wraps, taking a line off that scene's picture). The finished
     conversation fills its column top to bottom, so the two halves end on
     the same lines. */
  /* Six elevenths rounded down, so the page's half starts on a whole pixel
     (2026-10-14). */
  grid-template-columns: round(down, 100% * 6 / 11, 1px) minmax(0, 1fr);
  margin-inline: auto;
  /* The cover centres its copy; the panel is an interface, not a caption. */
  text-align: left;
  /* The one glyph only this mock needs, kept local rather than added to the
     shared mark set in 01_base.css. */
  --demo-mark-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' d='M5 12.5 10 17.5 19 7'/%3E%3C/svg%3E");
  max-width: 48rem;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--bg-card);
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.05),
    0 22px 44px -28px rgba(15, 23, 42, 0.45);
  overflow: hidden;
}

/* Chat side */

.demo-chat {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-6);
  /* The whole conversation fits, so nothing is ever taken back out of it: a
     bubble that vanished as the next one landed read as a glitch, because a
     panel that doesn't scroll gives the eye no reason for it. A height rather
     than a min-height, so a line that outgrows the frame gets cut instead of
     pushing the cover down. It is what the longest conversation takes: a
     two-line ask, the reply, the five tasks and a two-line result. */
  height: 24rem;
  overflow: hidden;
}

.demo-msg {
  /* The agent's lines may run to the card's edge; a cap just short of it left
     a ragged step between the two. */
  max-width: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: var(--fill-soft);
  color: var(--text);
  /* The panel's one reading size — bubbles, the list, the page's lines. At
     0.9 against 0.85 the ask read a touch larger than the work under it, a
     difference small enough to look like an accident. */
  font-size: 0.875rem;
  --lh: 1.45;
  display: none;
}

/* Hidden pieces COLLAPSE rather than hold their space: a chat with three empty
   slots under the last bubble reads as a broken panel, and the column's fixed
   height keeps anything outside the chat from moving as the loop plays. */
.demo-msg.is-on {
  display: block;
  animation: demo-in 260ms ease both;
}

.demo-msg--you {
  align-self: flex-end;
  max-width: 17rem;
  background: var(--tint-active);
}

/* The agent's side of the conversation: its face once, at the foot of what it
   has said so far, the way a messenger sets it. */
.demo-agent {
  display: none;
  grid-template-columns: 2rem minmax(0, 1fr);
  align-items: end;
  gap: var(--space-2);
}

.demo-agent.is-on { display: grid; }

.demo-agent__face {
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-pill);
  object-fit: cover;
}

.demo-agent__says {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

/* The wait before the reply, so the agent doesn't answer before it's asked. */
.demo-msg--dots.is-on {
  display: flex;
  gap: 0.3125rem;
  width: fit-content;
}

.demo-msg--dots span {
  width: 0.375rem;
  height: 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--text-muted);
  animation: demo-pulse 1.2s ease-in-out infinite;
}

.demo-msg--dots span:nth-child(2) { animation-delay: 0.15s; }
.demo-msg--dots span:nth-child(3) { animation-delay: 0.3s; }

/* The work, as a card in the conversation. Fixed gap, and the rows are all
   there from the moment it lands: a list that grew row by row would push the
   bubbles above it up five times over. It runs to the column's edge, where
   the visitor's own line ends, so the conversation has one right edge. */
.demo-card {
  display: none;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
  margin: 0;
  padding: var(--space-3);
  list-style: none;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--bg-card);
}

.demo-card.is-on {
  display: flex;
  animation: demo-in 260ms ease both;
}

.demo-task {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: 0.875rem;
  --lh: 1.4;
  color: var(--text);
  transition: color 260ms ease;
}

.demo-task:has(.demo-task__tick.is-on) { color: var(--text-muted); }

/* A round tick, the kind on a paper list — not a form's checkbox. */
.demo-task__tick {
  position: relative;
  flex: none;
  width: 1.0625rem;
  height: 1.0625rem;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-pill);
  transition: background 220ms ease, border-color 220ms ease;
}

.demo-task:not(.is-on) .demo-task__tick { border-color: var(--hairline); }

.demo-task__tick.is-on {
  background: var(--green);
  border-color: var(--green);
}

.demo-task__tick::after,
.demo-toast__check::after {
  content: "";
  position: absolute;
  inset: 0.1875rem;
  background: var(--bg-card);
  -webkit-mask: var(--demo-mark-check) center / contain no-repeat;
  mask: var(--demo-mark-check) center / contain no-repeat;
}

.demo-task__tick::after {
  opacity: 0;
  transform: scale(0.4);
  transition: opacity 220ms ease, transform 220ms ease;
}

.demo-task__tick.is-on::after {
  opacity: 1;
  transform: none;
}

/* Not reached yet: a blank bar the words' own width, so a list or a page
   reads as about to fill from the first frame, and each piece writes itself
   in where it will stand. */
.demo-task > span:last-child,
.demo-piece {
  border-radius: var(--radius-sm);
  transition: color 260ms ease, background 260ms ease;
}

.demo-task:not(.is-on) > span:last-child,
.demo-piece:not(.is-on) {
  color: transparent;
  background: var(--fill-soft);
}

/* Page side */

.demo-result {
  position: relative;
  display: flex;
  padding: var(--space-6);
  border-left: 1px solid var(--hairline);
  background: var(--bg-panel);
}

/* The thing they end up owning. A page, not a browser: no address bar, no
   window buttons — its name and whether it is up yet, a picture, what it
   sells and for how much. */
.demo-page {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--bg-card);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
  overflow: hidden;
}

.demo-page__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3);
  font-size: 0.875rem;
  --lh: 1.4;
}

.demo-page__where {
  font-weight: 600;
  color: var(--text);
}

/* Still being made: the name holds its place in neutral ink and the pill
   turns green when the thing is actually up. */
.demo-page__top:has(.demo-page__pill--pending.is-on) .demo-page__where { color: var(--text-muted); }

.demo-page__pill {
  display: none;
  padding: 0.125rem 0.5rem;
  border-radius: var(--radius-pill);
  background: rgba(34, 197, 94, 0.16);
  color: var(--green);
  font-size: 0.75rem;
  font-weight: 600;
}

.demo-page__pill.is-on { display: inline-block; }

.demo-page__pill--pending {
  background: var(--fill-soft);
  color: var(--text-muted);
}

/* The picture takes whatever height the words leave, so six pages with
   different words are still one size. Out of flow, or its own height would
   be asked first and the page would grow past its half. */
.demo-page__art {
  position: relative;
  flex: 1;
  min-height: 0;
  background: var(--fill-soft);
}

.demo-page__art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 400ms ease;
}

.demo-page__art img.is-on { opacity: 1; }

.demo-page__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  padding: var(--space-3);
}

.demo-page__name {
  font-size: 1rem;
  font-weight: 600;
  --lh: 1.3;
  color: var(--text);
}

.demo-page__offer {
  font-size: 0.875rem;
  --lh: 1.4;
  color: var(--text-muted);
}

.demo-page__buy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  margin-top: var(--space-2);
  font-size: 0.875rem;
}

.demo-page__price {
  font-weight: 600;
  color: var(--text);
}

/* The shop's own button, in ink: the accent stays with the one button on the
   cover that is the visitor's to press. */
/* An 18px line in 4px of padding, 26px: the price's 22px line centres on it
   by a whole pixel, where at 27 it stood on a half (2026-10-14). */
.demo-page__cta {
  --lh: 1.5;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--text);
  color: var(--bg-card);
  font-size: 0.75rem;
  font-weight: 600;
}

/* The money, the way a phone says it: over the picture, hanging off the
   page's corner. It lands with a small overshoot — the one bit of theatre on
   the cover. */
.demo-toast {
  position: absolute;
  top: 5rem;
  right: var(--space-4);
  display: none;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--bg-card);
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.08),
    0 12px 24px -10px rgba(15, 23, 42, 0.4);
  color: var(--green);
  font-size: 0.875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.demo-toast.is-on {
  display: flex;
  animation: demo-pop 420ms cubic-bezier(0.2, 1.4, 0.5, 1) both;
}

.demo-toast__check {
  position: relative;
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: var(--radius-pill);
  background: var(--green);
}

.demo-toast__check::after { inset: 0.25rem; }

/* Which business plays. Five of them at a quarter of a minute each is longer
   than anyone waits, and the one a visitor picks is the one that sells them —
   so the choice goes on the page, and taking it also stops the loop moving on.
   The row is deliberately below the panel: the panel is the argument, this is
   the remote control. */
/* One control, not five: a segmented row reads as the panel's foot, where five
   free-floating pills read as five buttons competing with it. */
.demo-picker {
  display: flex;
  width: fit-content;
  gap: 0;
  margin: var(--space-3) auto 0;
  /* One step all round, so the capsule's own frame is even — the segments
     carry the air, not the shell. */
  padding: var(--space-1);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-pill);
  background: var(--bg-card);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
}

/* One weight, one size: the selection is carried by fill and colour, so the
   row's letters never shift as it moves. */
.demo-pick {
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 500;
  --lh: 1;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color 120ms ease, background 120ms ease;
}

.demo-pick:hover {
  background: var(--fill-soft);
  color: var(--text);
}

/* Inside the capsule: an outline outside it would be clipped by the edge. */
.demo-pick:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.demo-pick[aria-pressed="true"]:hover { background: var(--tint-active); }

.demo-pick[aria-pressed="true"] {
  background: var(--tint-active);
  color: var(--text);
}

@keyframes demo-in {
  from { opacity: 0; transform: translateY(0.375rem); }
}

@keyframes demo-pop {
  from { transform: scale(0.4); opacity: 0; }
}

@keyframes demo-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* Two columns hold down to phone-adjacent widths; only the truly narrow case
   stacks, where side-by-side would squeeze both to nothing. In between the
   squares give way before the words do: less air, and the page yields width
   to the chat, whose longest task must stay on one line. */
@media (max-width: 45rem) {
  .demo-sim { grid-template-columns: minmax(0, 1fr) round(44%, 1px); }

  .demo-chat,
  .demo-result { padding: var(--space-4); }

  .demo-toast {
    top: var(--space-16);
    right: var(--space-2);
  }
}

/* Stacked on a phone, and compact: the panel shares the fold with the headline
   and the ask, so every row gives back what it can. The heights are the
   finished content's own — the panel still never grows as it plays. */
@media (max-width: 40rem) {
  /* The button is the page's one ask; the panel below it is the argument for
     it. On a phone they stack, so the gap has to say which is which — the
     panel keeps its distance instead of crowding the button. */
  .demo-stage { margin: var(--space-8) 0 var(--space-3); }

  .demo-sim { grid-template-columns: 1fr; }

  .demo-chat,
  .demo-result { padding: var(--space-3); }

  /* The closing reply says what the page under it already shows, and on a
     phone the fold can't afford both. */
  .demo-msg--result.is-on { display: none; }

  /* The ask, the reply and the list, and not a line more: every pixel here is
     one the fold hasn't got. */
  .demo-chat { height: 18.5rem; }

  .demo-msg,
  .demo-card { max-width: none; }

  .demo-msg--you { max-width: 88%; }

  .demo-result {
    border-left: none;
    border-top: 1px solid var(--hairline);
  }

  /* The page turns on its side: the picture as a square beside its words, so
     it costs the fold a few lines rather than a screen. */
  .demo-page {
    display: grid;
    grid-template-columns: 6.5rem minmax(0, 1fr);
    grid-template-areas: "art top" "art body";
    height: 6.5rem;
  }

  .demo-page__top { grid-area: top; }
  .demo-page__art { grid-area: art; }

  .demo-page__body {
    grid-area: body;
    padding-top: 0;
  }

  .demo-page__offer,
  .demo-page__cta { display: none; }

  .demo-page__buy { margin-top: 0; }

  /* Across the seam between the two halves, over the list's empty corner:
     anywhere on a page this small it would cover the page's own words. */
  .demo-toast {
    top: -1.375rem;
    right: var(--space-3);
  }

  /* Six labels do not fit a phone in one line, and two ragged rows of them
     read as a tag cloud. A row of dots instead, the way a phone already says
     "one of six": the business names itself on the page above, and the label
     stays in the button for a screen reader. Set as a phone sets them — a
     dot's width apart, clear of the panel — or they read as six stray marks.
     Every button is its dot plus the same air either side, so the gaps stay
     equal when the lit one stretches.
     corner-cut: the target is full height but only as wide as its dot and
     gap; wider and the row falls apart again. A tap that lands on the
     neighbour only shows the next business. */
  .demo-picker {
    margin-top: var(--space-2);
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
  }

  .demo-pick,
  .demo-pick:hover,
  .demo-pick[aria-pressed="true"],
  .demo-pick[aria-pressed="true"]:hover { background: none; }

  .demo-pick {
    display: grid;
    place-items: center;
    height: 2.75rem;
    padding: 0 var(--space-1);
    font-size: 0;
  }

  .demo-pick::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--text);
    opacity: 0.25;
    transition: width 220ms ease, opacity 220ms ease;
  }

  .demo-pick[aria-pressed="true"]::before {
    width: 1.25rem;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .demo-msg--dots span { animation: none; }

  .demo-msg.is-on,
  .demo-card.is-on,
  .demo-toast.is-on { animation: none; }

  .demo-task,
  .demo-task__tick,
  .demo-task__tick::after,
  .demo-piece,
  .demo-page__art img { transition: none; }
}

/* Disclaimer — a notice, not an error: the label in amber (read this before you
   pay) and nothing else coloured. Red under the CTA read as "something broke".
   A hairline card on the page's own ground, sized to its copy: the notice has
   to read as its own object, and both alternatives were worse — bare prose runs
   into the sections around it, a left rule alone reads as debris. It sits on
   the wrap's left edge like every section after it. Body copy runs in
   full-strength ink: a notice nobody reads is a notice that isn't there. Scoped
   under .marketing-section so the generic p rule (class+element) loses to it. */

.marketing-disclaimer__card {
  background: var(--bg-card);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  padding: var(--space-8);
  /* Prose width plus its padding, so the copy fills the card. Centred, unlike
     every other block here: signed, it is a sheet of paper, and it continues
     the cover's axis before the page settles onto its left edge below. */
  max-width: 44rem;
  margin-inline: auto;
  /* The props stand against it. */
  position: relative;
}

/* The bulb and the piggy bank stand at the sheet's lower corners, each
   tucked a little behind it, so the three read as one group: a sheet with
   two things set down beside it. Out past the wrap with a gap between, they
   were three separate objects in a row and the outer two fell off a laptop's
   screen. Where the window has no room beside the sheet the bank goes and
   the bulb stands small on its top right corner.
   --h is the object's height. The file is taller and wider than the object:
   its shadow is drawn into it, with 0.14 of the height under the object and
   a tenth either side (clay_marks.rake, PROP_ROOM), and those are taken back
   off here so it is the object, not the file's edge, that is placed. Every
   one of those lengths is rounded, and the width is worked from the rounded
   height by the file's own ratio (--ratio): 11rem x 1.14 was 200.64px tall
   and 4.5rem x 1.14 was 82.08 (2026-10-14). */
.marketing-disclaimer__prop {
  --tall: round(var(--h) * 1.14, 1px);
  --under: round(var(--h) * 0.14, 1px);
  --side: round(var(--h) * 0.1, 1px);
  position: absolute;
  bottom: calc(-1 * var(--under));
  width: round(var(--tall) * var(--ratio), 1px);
  height: var(--tall);
  object-fit: contain;
  pointer-events: none;
}

/* Behind the sheet, so its edge cuts across them. */
.marketing-disclaimer__prop { z-index: -1; }
.marketing-disclaimer__prop--idea { --h: 11rem; --ratio: calc(539 / 638); right: calc(100% - var(--space-8) - var(--side)); }
.marketing-disclaimer__prop--bank { --h: 11rem; --ratio: calc(664 / 638); left: calc(100% - var(--space-8) - var(--side)); }

@media (max-width: 64rem) {
  .marketing-disclaimer__prop--bank { display: none; }

  /* On the sheet's top edge it lies in front, whole. */
  .marketing-disclaimer__prop--idea {
    z-index: 0;
    --h: 4.5rem;
    right: calc(var(--space-6) - var(--side));
    bottom: calc(100% - 0.5rem - var(--under));
  }
}

/* The belief and its caveat are one pair: the sheet follows the vision at a
   floor's gap, not at the vision's own double one. */
.marketing-section.vision:has(+ .marketing-disclaimer) { padding-bottom: var(--floor-pad); }

/* A tracked micro-label, not a display heading: the block already shouts in
   colour, and a second 2rem headline under the h1 would fight it. Sans, because
   the display face has nothing to give at 12px. */

.marketing-section .marketing-disclaimer__label {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--amber);
  /* Tighter than the paragraph rhythm: the label belongs to the line under it,
     not to the stack. */
  margin-bottom: var(--space-3);
}

/* The floors' lede size, a step over the body: the card is a few short lines
   on a wide sheet, and at 1rem they read as small print. */
.marketing-section .marketing-disclaimer__card p {
  color: var(--text);
  max-width: 46rem;
  font-size: 1.0625rem;
  --lh: 1.65;
  margin-bottom: var(--space-4);
  text-wrap: pretty;
}

/* The opening line carries the whole notice, so it reads as the statement and
   the rest as its footnotes. */

/* A clear step over the lines under it, not a shade: at 1.25rem against
   1rem the statement and its footnotes read as one size, bolder and not. */
.marketing-section .marketing-disclaimer__card p:first-of-type {
  font-size: 1.5rem;
  font-weight: 700;
  --lh: 1.3;
  letter-spacing: -0.02em;
  margin-bottom: var(--space-6);
  /* On a phone its two sentences take a line each instead of breaking after
     "The". */
  text-wrap: balance;
}

/* The sign-off: body size, so it cannot be mistaken for a second heading under
   the 1.5rem statement, and the weight plus the air above are what mark it as
   the last word. */

.marketing-section .marketing-disclaimer__card .marketing-disclaimer__kicker {
  font-weight: 600;
  margin-top: var(--space-8);
  margin-bottom: 0;
}

/* The signature: a written hand, sized by its height like a real one and left
   where a signature goes. `multiply` drops the image's white ground onto the
   card's own white, so there is no plate around the ink and no cut-out halo. */

/* The width worked from the file's 900x322 and rounded down: auto made it
   145.33px and, set to the right, its left edge stood on a fraction
   (2026-10-14). */
.marketing-section .marketing-disclaimer__card .marketing-disclaimer__sign {
  display: block;
  width: round(down, 3.25rem * 900 / 322, 1px);
  height: 3.25rem;
  object-fit: contain;
  /* Right-hand corner, where a signature goes on anything anyone has ever
     signed — and it is the one thing that balances a card of left-set prose.
     Pulled up level with the sign-off: a hand signs beside the last line, not a
     paragraph's distance under it, and the card loses a hole at its foot. */
  margin: calc(var(--space-6) * -1) 0 0 auto;
  mix-blend-mode: multiply;
}

@media (max-width: 56.25em) {
  .marketing-disclaimer__card { padding: var(--space-6); }

  /* The sign-off wraps to two lines at this width, and the signature pulled up
     beside it landed on top of the words. */
  .marketing-section .marketing-disclaimer__card .marketing-disclaimer__sign {
    margin-top: var(--space-2);
  }
}


/* ===== Processes: the app's three columns as a mock =====
   The list of places, the chosen one's conversation, and what wakes it. A
   row of the list is a label for a hidden radio; the pane whose radio is
   checked is the one drawn, so pressing a process swaps the conversation and
   the rail with no script. Four processes, four rules each way: a pane and a
   row are matched to their radio by position. */

/* The step every heading over a panel takes, the table's and the reel's too. */
.marketing-section.processes h2 { margin-bottom: var(--space-12); }

.proc { display: flex; flex-direction: column; }

/* Out of sight, still in the tab order: the row it stands for takes the ring. */
.proc__pick { position: absolute; opacity: 0; pointer-events: none; }

.proc__window {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  background: var(--bg-card);
  border-radius: var(--radius);
  box-shadow: 0 1rem 2.5rem rgba(15, 23, 42, 0.16), 0 0 0 1px rgba(15, 23, 42, 0.06);
  overflow: hidden;
  font-size: 0.875rem;
  --lh: 1.45;
  color: var(--text);
}

.proc__places {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  /* The same air under the columns as over them: the window opens on its
     content a step down from its edge and ends a step under the last row.
     The three columns' first lines share one line across the window. */
  padding: var(--space-6) var(--space-3);
  border-right: 1px solid var(--hairline);
}

/* A row's height is set, not left to its text: the note's line is told where
   each row sits (--place, below), and a row a pixel taller would miss it. */
.proc__place {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 2.25rem;
  padding: 0 var(--space-3);
  border-radius: var(--radius-sm);
  white-space: nowrap;
  cursor: pointer;
  transition: background 120ms;
}

.proc__place--still { cursor: default; }
.proc__place--add { color: var(--text-muted); }
label.proc__place:hover { background: var(--fill-soft); }
.proc__lead { flex: none; width: 1rem; text-align: center; color: var(--text-muted); }
.proc__mark { margin-left: auto; width: 1.125rem; height: 1.125rem; object-fit: contain; }

/* Every pane holds the same cell, shown or not, so the window is as tall as
   the tallest of them and choosing another moves nothing. */
.proc__pane {
  grid-area: 1 / 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 17rem;
  visibility: hidden;
}

.proc__pick:nth-of-type(1):checked ~ .proc__window .proc__pane:nth-of-type(1),
.proc__pick:nth-of-type(2):checked ~ .proc__window .proc__pane:nth-of-type(2),
.proc__pick:nth-of-type(3):checked ~ .proc__window .proc__pane:nth-of-type(3),
.proc__pick:nth-of-type(4):checked ~ .proc__window .proc__pane:nth-of-type(4),
.proc__pick:nth-of-type(5):checked ~ .proc__window .proc__pane:nth-of-type(5) { visibility: visible; }

.proc__pick:nth-of-type(1):checked ~ .proc__window label.proc__place:nth-of-type(1),
.proc__pick:nth-of-type(2):checked ~ .proc__window label.proc__place:nth-of-type(2),
.proc__pick:nth-of-type(3):checked ~ .proc__window label.proc__place:nth-of-type(3),
.proc__pick:nth-of-type(4):checked ~ .proc__window label.proc__place:nth-of-type(4),
.proc__pick:nth-of-type(5):checked ~ .proc__window label.proc__place:nth-of-type(5) { background: var(--tint-active); }

.proc__pick:nth-of-type(1):focus-visible ~ .proc__window label.proc__place:nth-of-type(1),
.proc__pick:nth-of-type(2):focus-visible ~ .proc__window label.proc__place:nth-of-type(2),
.proc__pick:nth-of-type(3):focus-visible ~ .proc__window label.proc__place:nth-of-type(3),
.proc__pick:nth-of-type(4):focus-visible ~ .proc__window label.proc__place:nth-of-type(4),
.proc__pick:nth-of-type(5):focus-visible ~ .proc__window label.proc__place:nth-of-type(5) { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The conversation: the owner's words in a bubble at the right, the agent's
   plain at the left, and between them what a feed delivered or a round's card. */
.proc__chat {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-6);
}

.marketing-section .proc__chat p { margin: 0; max-width: 30rem; color: var(--text); }

.marketing-section .proc__chat .proc__you {
  align-self: flex-end;
  max-width: 24rem;
  padding: var(--space-2) var(--space-3);
  background: var(--tint-chip);
  border-radius: var(--radius);
}

.proc__card,
.proc__rail-row {
  display: grid;
  grid-template-columns: 1.25rem minmax(0, 1fr) auto;
  column-gap: var(--space-3);
  align-items: center;
}

.proc__card {
  align-self: flex-start;
  width: min(24rem, 100%);
  padding: var(--space-3);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-sm);
}

/* On the title's capitals, by ink (bin/shots --ink, 2026-10-14): the 2px it
   was dropped by stood it 2px under them. */
.proc__card-mark { grid-row: 1 / span 3; align-self: start; margin-top: 0; width: 1.25rem; height: 1.25rem; object-fit: contain; }
.proc__card-title, .proc__rail-name { grid-column: 2; font-weight: 600; }
.proc__card-line, .proc__rail-sub { grid-column: 2; color: var(--text-muted); }

/* The tick a finished round wears, and the one a place's menu puts by the
   feed pointed at it. */
/* At 17px the mark is 20px, an even height centred on the rows' 40px; at 18
   it was 21 and stood on a half pixel (2026-10-14). */
.proc__tick { grid-row: 1 / span 2; display: inline-flex; color: var(--green); font-size: 1.0625rem; }
.proc__rail-row > .proc__tick { grid-column: 3; }

/* The rail: what wakes the place. Heads and rows at set heights, for the
   same reason the list's rows are (--wake, below). A feed that is not
   pointed here stands back, so the ticked one is the row that reads. */
.proc__rail {
  padding: var(--space-8) var(--space-4);
  border-left: 1px solid var(--hairline);
}

.proc__rail-head {
  height: 1.25rem;
  margin-bottom: var(--space-2);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-muted);
}

.proc__rail-row { height: 3rem; align-content: center; }
.proc__rail-row--task { height: 4.25rem; }
.proc__rail-row.is-off { opacity: 0.5; }
/* The second line as tall as the name's, 20px: at 19 the pair was 39px and
   centring it in a whole-pixel row stood every row's text on a half pixel
   (2026-10-14). */
.proc__rail-sub { font-size: 0.8125rem; --lh: 1.55; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The notes. Narrow and by default: three plain captions under the window. */
.proc__notes {
  order: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-6);
  margin-top: var(--space-6);
}

/* Notes: the name in ink, the line under it muted, so the eye finds the
   three names first and the picture still leads. */
.marketing-section .proc__note h3 { margin-bottom: var(--space-1); font-size: 0.9375rem; font-weight: 600; color: var(--text); }
.marketing-section .proc__note p { margin: 0; font-size: 0.875rem; --lh: 1.5; color: var(--text-muted); }

/* Wide: the notes stand over the window, and each is tied to what it names
   by a line that runs down its own edge into the window and ends in a dot —
   on the chosen process's row, on the owner's message, beside the feed or
   the task that wakes the place. Each line comes down a channel nothing else
   stands in (right of the longest name, left of the tick), so it crosses no
   word on its way. --reach is how far into the window it goes: where a row
   sits is arithmetic on the set heights above, and the first and third
   follow the choice. */
@media (min-width: 66rem) {
  .proc__notes {
    order: 0;
    grid-template-columns: 15rem minmax(0, 1fr) 17rem;
    gap: 0;
    align-items: end;
    margin: 0 0 var(--space-6);
    --gap: var(--space-6);
    /* The first process's row: the list's padding, the room's row and its
       gap, half a row. Each further process is one row and one gap lower,
       and the room itself, the first row, one higher. */
    --place: 5.125rem;
    /* The first feed's row: the rail's padding, a head and its margin, half
       a row. Each further feed is a row lower; a scheduled task stands first
       in its rail and is taller, so its middle is a little lower than a
       feed's. */
    --wake: 5.25rem;
  }

  .proc__pick:nth-of-type(1):checked ~ .proc__notes { --place: 2.625rem; --wake: 11.25rem; }
  .proc__pick:nth-of-type(3):checked ~ .proc__notes { --place: 7.625rem; --wake: 8.25rem; }
  .proc__pick:nth-of-type(4):checked ~ .proc__notes { --place: 10.125rem; --wake: 5.875rem; }
  .proc__pick:nth-of-type(5):checked ~ .proc__notes { --place: 12.625rem; --wake: 5.875rem; }

  .proc__note { position: relative; grid-row: 1; z-index: 1; padding-left: var(--space-3); }

  .proc__note::before,
  .proc__note::after { content: ""; position: absolute; left: 0; pointer-events: none; }

  /* The line, down the note's edge and on into the window. */
  .proc__note::before {
    top: 0.25rem;
    width: 1px;
    height: calc(100% - 0.25rem + var(--gap) + var(--reach));
    background: var(--hairline-strong);
    transition: height 200ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  /* The dot it ends in. */
  .proc__note::after {
    top: calc(100% + var(--gap) + var(--reach));
    width: 0.4375rem;
    height: 0.4375rem;
    margin: -0.25rem 0 0 -0.1875rem;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--accent) 55%, var(--bg-card));
    transition: top 200ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  /* Down the list's free channel, between the longest name and the marks. */
  .proc__note--place { grid-column: 1 / 3; width: 15rem; margin-left: 11.5rem; --reach: var(--place); }

  /* Onto the owner's bubble, which hangs from the chat's right edge. */
  .proc__note--rule { grid-column: 2; justify-self: end; width: 16rem; margin-right: var(--space-6); --reach: var(--space-8); }

  /* Down the rail's free channel, left of the tick: this note hangs from its
     right edge, its words set to it. */
  .proc__note--wake { grid-column: 3; padding: 0 var(--space-3) 0 0; margin-right: 3.25rem; text-align: right; --reach: var(--wake); }
  .proc__note--wake::before { left: auto; right: 0; }
  .proc__note--wake::after { left: auto; right: 0; margin: -0.25rem -0.1875rem 0 0; }
}

/* Narrow: the places run across the top as a strip the finger swipes, the
   conversation under it, what wakes it under that. */
@media (max-width: 56.25em) {
  .proc__window { grid-template-columns: minmax(0, 1fr); }
  .proc__places {
    flex-direction: row;
    overflow-x: auto;
    scrollbar-width: none;
    border-right: 0;
    border-bottom: 1px solid var(--hairline);
  }
  .proc__place--still { display: none; }
  .proc__place { flex: none; }
  .proc__pane { grid-area: 2 / 1; grid-template-columns: minmax(0, 1fr); }
  .proc__chat { padding: var(--space-4); }
  .proc__rail { padding: var(--space-4); border-left: 0; border-top: 1px solid var(--hairline); }
  .proc__notes { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
}

/* ===== Price =====
   The FAQ's split: the offer and the button in the first third, the terms in
   the other two. The terms are the capability grid's term-over-clause, in the
   page's one tinted panel, the tint Brrr's column wears in the table above. */
.price .marketing-cta { margin-top: var(--space-6); }

.capability-grid.price__terms {
  grid-column: span 2;
  max-width: none;
  margin-top: 0;
  padding: var(--space-8);
  gap: var(--space-8) 2.5rem;
  border-radius: var(--radius);
  background: var(--tint-chip);
}

/* Its two columns on whole pixels, as the floor's thirds (2026-10-14). */
@media not (max-width: 48rem) {
  .capability-grid.price__terms { grid-template-columns: round(down, (100% - 2.5rem) / 2, 1px) minmax(0, 1fr); }
}

@media (max-width: 64rem) {
  .capability-grid.price__terms { grid-column: auto; padding: var(--space-6); }
}
