/* Conjurate public pages (landing, legal, and the Jinja auth templates), Cool plum
   (Chris, 2026-10-09; docs/design-system.md): a lavender-white ground, plum-black ink, one violet-plum accent, Newsreader
   for titles and Hanken Grotesk for text. The tokens match the console's tokens.css, so the
   site and the app read as one system. Self-contained: public templates link this file, not
   console.css. */
:root {
  --ground: #FBF8FC; --panel: #F2EEF7; --tile: #ECE9F7; --surface: #FFFFFF;
  --ink: #1C1533; --muted: #625B74; --faint: #9F99B3; --line: #E7E1EF;
  --accent: #5F52A8; --accent-ink: #4B4090; --accent-soft: #ECE9F7; --on-accent: #FFFFFF;
  --ok: #2A6E4C; --bad: #9C3A4A; --warn-soft: #F6EBDA;
  --focus-ring: var(--accent);
  --display: "Newsreader", "Iowan Old Style", Georgia, serif;
  --body: "Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground: #13111E; --panel: #1C1A2B; --tile: #252238; --surface: #1C1A2B;
    --ink: #ECE9F7; --muted: #A8A2C0; --faint: #6B6790; --line: #302C45;
    --accent: #ADA6EC; --accent-ink: #CDC8F5; --accent-soft: #29264A; --on-accent: #13111E;
    --ok: #7CCBA2; --bad: #F09AA8; --warn-soft: #2E271F;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #13111E; --panel: #1C1A2B; --tile: #252238; --surface: #1C1A2B;
  --ink: #ECE9F7; --muted: #A8A2C0; --faint: #6B6790; --line: #302C45;
  --accent: #ADA6EC; --accent-ink: #CDC8F5; --accent-soft: #29264A; --on-accent: #13111E;
  --ok: #7CCBA2; --bad: #F09AA8; --warn-soft: #2E271F;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* In-page links land exactly under the sticky bar, so no strip of the section above shows
   (the bands reach the section's edge, so a gap showed the previous band). landing.js sets
   --nav-h to the bar's measured height (67px, 69px on phones); 67px holds before it runs. */
html { scroll-padding-top: var(--nav-h, 67px); }
body { background: var(--ground); color: var(--ink); font: 17px/1.6 var(--body); }
a { color: inherit; }
/* An author `display` rule beats the user agent's `[hidden]`; the demo panels and the
   typing dots both have one, so `hidden` must win here (console.css does the same). */
[hidden] { display: none !important; }
h1, h2, h3 { margin: 0; text-wrap: balance; }
h1, h2 { font-family: var(--display); font-weight: 400; letter-spacing: -0.02em; }
h3 { font-family: var(--body); font-weight: 600; letter-spacing: -0.005em; }
p { margin: 0; }
.wrap { max-width: 1200px; margin: 0 auto; padding-inline: 32px; }
.muted { color: var(--muted); }
.eyebrow { font: 500 13px/1 var(--body); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; border-radius: 6px; }

/* ---- Brand: the plum mark in light, the white mark in dark ---- */
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.brand img.mark { height: 28px; width: auto; display: block; }
.brand img.word { height: 16px; width: auto; display: block; }
.brand-name { font: 600 18px var(--body); letter-spacing: .01em; }
.brand img.logo-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand img.logo-light { display: none; }
  :root:not([data-theme="light"]) .brand img.logo-dark { display: block; }
}
:root[data-theme="dark"] .brand img.logo-light { display: none; }
:root[data-theme="dark"] .brand img.logo-dark { display: block; }

/* ---- Buttons: the accent fills the primary; ghost is a hairline; quiet is text ---- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 12px 22px;
  border: 1px solid var(--accent); border-radius: 10px; background: var(--accent); color: var(--on-accent);
  font: 500 15px var(--body); text-decoration: none; cursor: pointer; transition: background .2s, color .2s, border-color .2s; }
.btn:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn.ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn.ghost:hover { background: var(--ink); color: var(--ground); }
.btn.quiet { background: transparent; border-color: transparent; color: var(--muted); }
.btn.quiet:hover { color: var(--ink); }
.btn.block { width: 100%; }

/* ---- Landing: top bar ---- */
.site-nav { position: sticky; top: 0; z-index: 10; background: color-mix(in srgb, var(--ground) 92%, transparent);
  backdrop-filter: saturate(1.2) blur(8px); -webkit-backdrop-filter: saturate(1.2) blur(8px); border-bottom: 1px solid var(--line); }
.nav-row { display: flex; align-items: center; gap: 28px; padding-block: 14px; }
.page-links { display: flex; gap: 24px; margin-left: auto; font-size: 15px; }
.page-links a { text-decoration: none; color: var(--muted); }
.page-links a:hover { color: var(--ink); }
.account { display: flex; gap: 6px; align-items: center; }
.account .btn { padding: 9px 16px; font-size: 14px; }

/* ---- Hero: the headline is the page; it rises in once, from a visible state ---- */
.hero { padding-block: 96px 72px; display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 24px 64px; align-items: end; }
.hero .eyebrow { grid-column: 1 / -1; }
.hero h1 { font-size: clamp(44px, 7.2vw, 100px); line-height: .98; letter-spacing: -0.035em; animation: rise .9s cubic-bezier(.16, 1, .3, 1) both; }
.hero h1 .soft { color: var(--muted); }
/* Three key phrases (the hero, "Live in a week." and the closing line) carry a felt-marker
   stroke in the plum accent: a heavier start, streaky ink and a fade where the pen lifts. Few
   marks so each one counts, on the first and last things a visitor reads. A hand-drawn stroke
   never reads as a link the way a straight coloured underline does. The stroke is one SVG
   stretched to the phrase; each wrapped line gets its own copy. Its colour follows the theme
   through --marker, kept out of the token blocks above. In the headline the phrase also
   returns to full ink, so the payoff reads first. */
:root { --marker: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 20' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='%235F52A8' stop-opacity='.95'/%3E%3Cstop offset='.12' stop-color='%235F52A8' stop-opacity='.82'/%3E%3Cstop offset='.7' stop-color='%235F52A8' stop-opacity='.72'/%3E%3Cstop offset='1' stop-color='%235F52A8' stop-opacity='.25'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-5%25' y='-40%25' width='110%25' height='180%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.32' numOctaves='2' seed='3' result='n'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='n' scale='1.4' result='d0'/%3E%3CfeGaussianBlur in='d0' stdDeviation='.28' result='d'/%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.015 0.55' numOctaves='2' seed='7' result='s'/%3E%3CfeColorMatrix in='s' type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 -1.1 1.35' result='sa'/%3E%3CfeComposite in='d' in2='sa' operator='in'/%3E%3C/filter%3E%3C/defs%3E%3Cpath d='M3.89 14.37 L7.03 15.15 L10.19 15.92 L13.37 16.27 L16.55 16.37 L19.74 16.44 L22.93 16.50 L26.13 16.54 L29.32 16.56 L32.52 16.56 L35.71 16.53 L38.91 16.49 L42.10 16.42 L45.30 16.34 L48.49 16.23 L51.68 16.10 L54.87 15.96 L58.06 15.80 L61.25 15.62 L64.43 15.44 L67.61 15.24 L70.79 15.03 L73.96 14.81 L77.13 14.59 L80.30 14.37 L83.46 14.15 L86.62 13.94 L89.78 13.72 L92.94 13.52 L96.09 13.33 L99.24 13.15 L102.38 12.98 L105.53 12.83 L108.67 12.69 L111.81 12.57 L114.95 12.48 L118.09 12.40 L121.23 12.34 L124.37 12.31 L127.51 12.30 L130.64 12.30 L133.78 12.33 L136.92 12.38 L140.07 12.44 L143.21 12.52 L146.36 12.62 L149.51 12.73 L152.66 12.85 L155.82 12.93 L158.98 12.99 L162.15 13.02 L165.32 13.03 L168.49 13.03 L171.67 13.00 L174.85 12.95 L178.04 12.88 L181.22 12.78 L184.41 12.65 L187.59 12.50 L190.78 12.32 L193.96 12.10 L194.04 8.24 L190.89 7.89 L187.74 7.54 L184.59 7.19 L181.44 6.84 L178.30 6.49 L175.15 6.15 L172.00 5.82 L168.84 5.50 L165.68 5.20 L162.52 4.92 L159.35 4.66 L156.18 4.44 L153.01 4.26 L149.83 4.13 L146.64 4.02 L143.45 3.92 L140.27 3.84 L137.08 3.78 L133.88 3.73 L130.69 3.70 L127.49 3.70 L124.30 3.71 L121.10 3.75 L117.91 3.80 L114.71 3.88 L111.52 3.98 L108.33 4.10 L105.14 4.23 L101.95 4.39 L98.76 4.56 L95.58 4.74 L92.40 4.94 L89.22 5.14 L86.04 5.36 L82.87 5.57 L79.70 5.79 L76.54 6.01 L73.37 6.23 L70.21 6.45 L67.06 6.65 L63.90 6.85 L60.75 7.04 L57.61 7.21 L54.46 7.37 L51.32 7.51 L48.18 7.64 L45.04 7.74 L41.90 7.83 L38.76 7.89 L35.62 7.93 L32.48 7.96 L29.35 7.96 L26.21 7.94 L23.07 7.90 L19.92 7.84 L16.78 7.77 L13.63 7.68 L10.48 7.82 L7.30 8.35 L4.11 8.88Z' fill='url(%23g)' filter='url(%23f)'/%3E%3C/svg%3E"); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --marker: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 20' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='%23ADA6EC' stop-opacity='.95'/%3E%3Cstop offset='.12' stop-color='%23ADA6EC' stop-opacity='.82'/%3E%3Cstop offset='.7' stop-color='%23ADA6EC' stop-opacity='.72'/%3E%3Cstop offset='1' stop-color='%23ADA6EC' stop-opacity='.25'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-5%25' y='-40%25' width='110%25' height='180%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.32' numOctaves='2' seed='3' result='n'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='n' scale='1.4' result='d0'/%3E%3CfeGaussianBlur in='d0' stdDeviation='.28' result='d'/%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.015 0.55' numOctaves='2' seed='7' result='s'/%3E%3CfeColorMatrix in='s' type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 -1.1 1.35' result='sa'/%3E%3CfeComposite in='d' in2='sa' operator='in'/%3E%3C/filter%3E%3C/defs%3E%3Cpath d='M3.89 14.37 L7.03 15.15 L10.19 15.92 L13.37 16.27 L16.55 16.37 L19.74 16.44 L22.93 16.50 L26.13 16.54 L29.32 16.56 L32.52 16.56 L35.71 16.53 L38.91 16.49 L42.10 16.42 L45.30 16.34 L48.49 16.23 L51.68 16.10 L54.87 15.96 L58.06 15.80 L61.25 15.62 L64.43 15.44 L67.61 15.24 L70.79 15.03 L73.96 14.81 L77.13 14.59 L80.30 14.37 L83.46 14.15 L86.62 13.94 L89.78 13.72 L92.94 13.52 L96.09 13.33 L99.24 13.15 L102.38 12.98 L105.53 12.83 L108.67 12.69 L111.81 12.57 L114.95 12.48 L118.09 12.40 L121.23 12.34 L124.37 12.31 L127.51 12.30 L130.64 12.30 L133.78 12.33 L136.92 12.38 L140.07 12.44 L143.21 12.52 L146.36 12.62 L149.51 12.73 L152.66 12.85 L155.82 12.93 L158.98 12.99 L162.15 13.02 L165.32 13.03 L168.49 13.03 L171.67 13.00 L174.85 12.95 L178.04 12.88 L181.22 12.78 L184.41 12.65 L187.59 12.50 L190.78 12.32 L193.96 12.10 L194.04 8.24 L190.89 7.89 L187.74 7.54 L184.59 7.19 L181.44 6.84 L178.30 6.49 L175.15 6.15 L172.00 5.82 L168.84 5.50 L165.68 5.20 L162.52 4.92 L159.35 4.66 L156.18 4.44 L153.01 4.26 L149.83 4.13 L146.64 4.02 L143.45 3.92 L140.27 3.84 L137.08 3.78 L133.88 3.73 L130.69 3.70 L127.49 3.70 L124.30 3.71 L121.10 3.75 L117.91 3.80 L114.71 3.88 L111.52 3.98 L108.33 4.10 L105.14 4.23 L101.95 4.39 L98.76 4.56 L95.58 4.74 L92.40 4.94 L89.22 5.14 L86.04 5.36 L82.87 5.57 L79.70 5.79 L76.54 6.01 L73.37 6.23 L70.21 6.45 L67.06 6.65 L63.90 6.85 L60.75 7.04 L57.61 7.21 L54.46 7.37 L51.32 7.51 L48.18 7.64 L45.04 7.74 L41.90 7.83 L38.76 7.89 L35.62 7.93 L32.48 7.96 L29.35 7.96 L26.21 7.94 L23.07 7.90 L19.92 7.84 L16.78 7.77 L13.63 7.68 L10.48 7.82 L7.30 8.35 L4.11 8.88Z' fill='url(%23g)' filter='url(%23f)'/%3E%3C/svg%3E"); } }
:root[data-theme="dark"] { --marker: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 20' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='%23ADA6EC' stop-opacity='.95'/%3E%3Cstop offset='.12' stop-color='%23ADA6EC' stop-opacity='.82'/%3E%3Cstop offset='.7' stop-color='%23ADA6EC' stop-opacity='.72'/%3E%3Cstop offset='1' stop-color='%23ADA6EC' stop-opacity='.25'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-5%25' y='-40%25' width='110%25' height='180%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.32' numOctaves='2' seed='3' result='n'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='n' scale='1.4' result='d0'/%3E%3CfeGaussianBlur in='d0' stdDeviation='.28' result='d'/%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.015 0.55' numOctaves='2' seed='7' result='s'/%3E%3CfeColorMatrix in='s' type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 -1.1 1.35' result='sa'/%3E%3CfeComposite in='d' in2='sa' operator='in'/%3E%3C/filter%3E%3C/defs%3E%3Cpath d='M3.89 14.37 L7.03 15.15 L10.19 15.92 L13.37 16.27 L16.55 16.37 L19.74 16.44 L22.93 16.50 L26.13 16.54 L29.32 16.56 L32.52 16.56 L35.71 16.53 L38.91 16.49 L42.10 16.42 L45.30 16.34 L48.49 16.23 L51.68 16.10 L54.87 15.96 L58.06 15.80 L61.25 15.62 L64.43 15.44 L67.61 15.24 L70.79 15.03 L73.96 14.81 L77.13 14.59 L80.30 14.37 L83.46 14.15 L86.62 13.94 L89.78 13.72 L92.94 13.52 L96.09 13.33 L99.24 13.15 L102.38 12.98 L105.53 12.83 L108.67 12.69 L111.81 12.57 L114.95 12.48 L118.09 12.40 L121.23 12.34 L124.37 12.31 L127.51 12.30 L130.64 12.30 L133.78 12.33 L136.92 12.38 L140.07 12.44 L143.21 12.52 L146.36 12.62 L149.51 12.73 L152.66 12.85 L155.82 12.93 L158.98 12.99 L162.15 13.02 L165.32 13.03 L168.49 13.03 L171.67 13.00 L174.85 12.95 L178.04 12.88 L181.22 12.78 L184.41 12.65 L187.59 12.50 L190.78 12.32 L193.96 12.10 L194.04 8.24 L190.89 7.89 L187.74 7.54 L184.59 7.19 L181.44 6.84 L178.30 6.49 L175.15 6.15 L172.00 5.82 L168.84 5.50 L165.68 5.20 L162.52 4.92 L159.35 4.66 L156.18 4.44 L153.01 4.26 L149.83 4.13 L146.64 4.02 L143.45 3.92 L140.27 3.84 L137.08 3.78 L133.88 3.73 L130.69 3.70 L127.49 3.70 L124.30 3.71 L121.10 3.75 L117.91 3.80 L114.71 3.88 L111.52 3.98 L108.33 4.10 L105.14 4.23 L101.95 4.39 L98.76 4.56 L95.58 4.74 L92.40 4.94 L89.22 5.14 L86.04 5.36 L82.87 5.57 L79.70 5.79 L76.54 6.01 L73.37 6.23 L70.21 6.45 L67.06 6.65 L63.90 6.85 L60.75 7.04 L57.61 7.21 L54.46 7.37 L51.32 7.51 L48.18 7.64 L45.04 7.74 L41.90 7.83 L38.76 7.89 L35.62 7.93 L32.48 7.96 L29.35 7.96 L26.21 7.94 L23.07 7.90 L19.92 7.84 L16.78 7.77 L13.63 7.68 L10.48 7.82 L7.30 8.35 L4.11 8.88Z' fill='url(%23g)' filter='url(%23f)'/%3E%3C/svg%3E"); }
.ul { background: var(--marker) 0 100% / 100% .48em no-repeat; padding-bottom: .1em;
  -webkit-box-decoration-break: clone; box-decoration-break: clone; }
/* The hero's stroke draws itself once on load: "already", then "booked the call.". The stroke
   sits in its final shape from the first frame; a page-coloured cover with a soft leading edge
   slides off it left to right, so the ink is uncovered in place like a pen tip, never stretched.
   The cover is --ground, so this only works on the plain hero background. */
.ul-draw { background: none; padding-bottom: 0; }
.ul-draw > span { background: linear-gradient(90deg, transparent, var(--ground) .7em) 100% 0 / 0% 100% no-repeat,
  var(--marker) 0 100% / 100% .48em no-repeat; padding-bottom: .1em;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
  animation: ink .5s cubic-bezier(.45, .05, .4, 1) .8s both; }
.ul-draw > span + span { animation-duration: .78s; animation-delay: 1.35s; }
@keyframes ink { from { background-size: calc(100% + .7em) 100%, 100% .48em; } to { background-size: 0% 100%, 100% .48em; } }
.hero h1 .soft .ul { color: var(--ink); }
@keyframes rise { from { opacity: .2; transform: translateY(.12em); } to { opacity: 1; transform: none; } }
.hero-aside { display: grid; gap: 22px; padding-bottom: 10px; }
.hero .lede { font-size: 18px; color: var(--muted); }
.cta { display: flex; gap: 10px; flex-wrap: wrap; }
.audience { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0; }
.access { font: 13px/1.5 var(--mono); color: var(--muted); }

/* ---- Demo: one wide panel, tabs on the left, the conversation and the hand-off ---- */
.demo-panel { background: var(--panel); border-radius: 24px; padding: 40px; display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 48px; }
.demo-intro { display: grid; gap: 16px; align-content: start; }
.demo-intro h2 { font-size: 34px; line-height: 1.08; }
.sub { color: var(--muted); }
.demo-intro .sub { font-size: 16px; }
.tabs { display: grid; gap: 2px; margin-top: 8px; }
.tabs [role=tab] { text-align: left; background: none; border: 0; border-radius: 8px; padding: 10px 12px; font: 500 15px var(--body); color: var(--muted); cursor: pointer; }
.tabs [role=tab]:hover { color: var(--ink); }
.tabs [role=tab][aria-selected=true] { background: var(--ground); color: var(--ink); }
.demo-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; font: 12px var(--mono); color: var(--muted); }
.replay { background: none; border: 1px solid var(--line); border-radius: 8px; padding: 5px 10px; font: 500 13px var(--body); color: var(--muted); cursor: pointer; }
/* 44px at every width and pointer (L9): a width rule, so emulation and tests see it too. */
.tabs [role=tab], .replay { min-height: 44px; }
.replay:hover { color: var(--ink); border-color: var(--faint); }
.demo-stage { min-width: 0; }
.phone { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.convo, .handoff { background: var(--surface); border-radius: 16px; padding: 24px; display: grid; gap: 12px; align-content: start; min-width: 0; }
.convo .bar { display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap; font-size: 14px; }
.convo .bar b { font-weight: 600; }
.convo .bar span { font: 12px/1.6 var(--mono); color: var(--muted); }
.thread { position: relative; display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
/* Read aloud, never seen: "Assistant:" / "Lead:" before each message (N-L3). */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.msg { max-width: 88%; padding: 10px 14px; border-radius: 14px; font-size: 15px; line-height: 1.5; transition: opacity .3s, transform .3s; }
.msg.ai { background: var(--panel); border-bottom-left-radius: 4px; }
.msg.lead { justify-self: end; background: var(--accent); color: var(--on-accent); border-bottom-right-radius: 4px; }
.msg .t { display: block; font: 11px var(--mono); opacity: .85; margin-top: 4px; text-wrap: balance; }
.msg.pending { opacity: 0; transform: translateY(6px); }
/* The hand-off card keeps its place while the thread plays: its content waits (still in the
   accessibility tree) and three soft bars stand in, so the card is never a blank panel. */
.handoff { position: relative; }
.handoff.pending > * { opacity: 0; }
.handoff.pending::after { content: ""; position: absolute; inset: 20px 20px auto 20px; height: 68px; border-radius: 6px;
  background: linear-gradient(color-mix(in srgb, var(--muted) 24%, transparent), color-mix(in srgb, var(--muted) 24%, transparent)) 0 0 / 55% 14px no-repeat,
    linear-gradient(color-mix(in srgb, var(--muted) 24%, transparent), color-mix(in srgb, var(--muted) 24%, transparent)) 0 27px / 100% 10px no-repeat,
    linear-gradient(color-mix(in srgb, var(--muted) 24%, transparent), color-mix(in srgb, var(--muted) 24%, transparent)) 0 49px / 80% 10px no-repeat;
  animation: skel 1.6s ease-in-out infinite; }
@keyframes skel { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
.msg.typing { position: absolute; left: 0; display: inline-flex; gap: 4px; padding: 14px; }
.msg.typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: dot 1s infinite; }
.msg.typing span:nth-child(2) { animation-delay: .15s; } .msg.typing span:nth-child(3) { animation-delay: .3s; }
@keyframes dot { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }
.handoff h3 { font: 400 26px/1.1 var(--display); letter-spacing: -0.01em; }
.facts { margin: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 18px; font-size: 14px; }
.facts dt, .facts dd { margin: 0; padding-block: 9px; border-top: 1px solid var(--line); }
.facts dt { color: var(--muted); }
.who { font: 12px/1.5 var(--mono); color: var(--muted); padding-top: 4px; }

/* ---- Bands (Chris, 2026-10-02): each rounded block opens into a full-width band as it
   scrolls up into view, growing like a picture rather than reflowing: landing.js sets --p
   (0..1) and --s, the scale that takes the block to the full width at --p = 1. Text, art and
   gaps all scale together, so no line ever re-wraps. The block grows from its top edge and
   reserves its fully grown height below it from the start (--reserve, set by the script), so the page never changes height while you scroll and an in-page jump lands where it aimed. The corners square
   off as --p reaches 1 (divided by --s so they shrink on screen at the same rate). Without
   the script (or with reduced motion) the blocks keep their rounded look. ---- */
body.landing { overflow-x: clip; overflow-anchor: none; }
.morph { --p: 0; --s: 1;
  transform: scale(var(--s)); transform-origin: 50% 0;
  margin-bottom: var(--reserve, 0px);
  border-radius: calc((1 - var(--p)) * var(--r) / var(--s)); }
.demo-panel.morph { --r: 24px; }
/* Desktop tiles: the cards merge into one band; their own fills fade into the band's and
   their corners square off. */
.tiles.morph { --r: 20px;
  background: color-mix(in srgb, var(--panel) calc(var(--p) * 100%), transparent); }
.tiles.morph .tile { border-radius: calc((1 - var(--p)) * 20px / var(--s));
  background: color-mix(in srgb, var(--panel) calc((1 - var(--p)) * 100%), transparent); }
.tiles.morph .tile:hover { transform: none; }
/* Wider screens: the block only grows halfway into the margins, so it stays a rounded panel
   (its corners hold their on-screen size) rather than squaring off into a band. */
@media (min-width: 681px) { .morph { border-radius: calc(var(--r) / var(--s)); } }

/* ---- Sections ---- */
.section { padding-block: 120px 0; display: grid; gap: 44px; }
.section-head { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: end; }
.section-head h2 { font-size: clamp(34px, 4.6vw, 56px); line-height: 1.03; }
.section-head .sub { font-size: 18px; max-width: 32em; }
.when { font: 12px/1.4 var(--mono); color: var(--muted); letter-spacing: .02em; }
.timeline, .numbered { list-style: none; margin: 0; padding: 0; display: grid; }
.timeline li { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 24px; padding-block: 24px; border-top: 1px solid var(--line); }
.timeline li:last-child { border-bottom: 1px solid var(--line); }
.timeline .when { padding-top: 4px; }
.timeline h3, .numbered h3 { font-size: 18px; margin-bottom: 6px; }
.timeline p, .numbered p, .tile p { color: var(--muted); font-size: 16px; }
.turn { font: 400 26px/1.35 var(--display); letter-spacing: -0.01em; max-width: 30em; }
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.tile { display: grid; grid-template-rows: auto 1fr; border-radius: 20px; overflow: hidden; background: var(--panel); transition: transform .25s cubic-bezier(.16, 1, .3, 1); }
.tile:hover { transform: translateY(-3px); }
/* Desktop art is a wide strip (L10), not a 16:9 slab: the Guardrails heading and its three
   claims share the first screen. Each strip is a small real artifact built from the demo's
   own strings (.art); the glyph svg is the phone thumbnail. */
.tile figure { margin: 0; background: var(--tile); aspect-ratio: 3 / 1; display: grid; place-items: center; }
.tile .art { display: none; }
@media (min-width: 681px) {
  .tile figure.has-art svg { display: none; }
  .tile .art { display: grid; gap: 6px; justify-items: center; align-content: center; padding: 10px; max-width: 100%; }
  .tile .art .chip { font: 12px/1 var(--mono); padding: 7px 11px; border-radius: 999px; background: var(--surface);
    border: 1px solid var(--line); color: var(--ink); white-space: nowrap; }
  .tile .art .chip.hot { background: var(--accent-soft); color: var(--accent-ink); border-color: transparent; }
  .tile .art .art-arrow { font: 12px/1 var(--mono); color: var(--muted); }
  .tile .art:has(.chip + .chip + .chip) { grid-auto-flow: column; }
  .tile .art .mini { display: grid; gap: 3px; background: var(--surface); border: 1px solid var(--line);
    border-radius: 10px; padding: 10px 16px; }
  .tile .art .mini b { font: 400 18px/1.1 var(--display); letter-spacing: -0.01em; }
  .tile .art .mini span { font: 11px/1.3 var(--mono); color: var(--muted); }
  .tile .art .ledger { display: grid; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; }
  .tile .art .ledger span { display: flex; justify-content: space-between; gap: 24px; padding: 5px 12px;
    font: 11px/1.3 var(--mono); color: var(--ink); }
  .tile .art .ledger span + span { border-top: 1px solid var(--line); }
  .tile .art .ledger i { font-style: normal; color: var(--muted); }
}
.tile svg { width: 42%; height: auto; max-width: 100%; }
.tile svg * { fill: none; stroke: var(--ink); stroke-width: 2; }
.tile svg .f { fill: var(--ink); stroke: none; }
.tile svg .a { fill: var(--accent); stroke: none; }
.tile svg .d { stroke: var(--faint); stroke-dasharray: 3 5; }
.tile .copy { padding: 24px 26px 28px; display: grid; gap: 8px; align-content: start; }
.tile h3 { font: 400 26px/1.12 var(--display); letter-spacing: -0.015em; }
.numbered li { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 20px; padding-block: 26px; border-top: 1px solid var(--line); }
.numbered .n { font: 400 34px/1 var(--display); color: var(--muted); }
.numbered .when { display: block; margin-bottom: 6px; }

.close { padding-block: 140px 120px; display: grid; gap: 36px; justify-items: start; }
.close h2 { font-size: clamp(40px, 6vw, 84px); line-height: 1; letter-spacing: -0.03em; }

.foot { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 32px; padding-block: 48px 56px; border-top: 1px solid var(--line); font-size: 14px; }
.foot-brand, .foot-col { display: grid; gap: 10px; align-content: start; }
.foot-brand > span { font: 12px var(--mono); color: var(--muted); }
.foot-col a { text-decoration: none; color: var(--muted); padding-block: 4px; } .foot-col a:hover { color: var(--ink); }
.foot-contact { color: var(--ink); text-underline-offset: 3px; text-decoration-color: var(--accent); width: fit-content; }
/* The close's second action is a quiet link, so Book stays the one filled button (L11). */
.close .btn.watch-again { color: var(--ink); text-decoration: underline; text-decoration-color: var(--accent);
  text-underline-offset: 4px; padding-inline: 6px; margin-inline-start: -6px; min-height: 44px; }

/* Short button labels for phones: one of the two spans shows, so only it is read aloud.
   Only the hero's Watch button uses them; booking buttons say one label at every width (U6). */
.btn .short { display: none; }
.btn { white-space: nowrap; }

@media (max-width: 980px) {
  .page-links { display: none; }
  .account { margin-left: auto; }
  .hero { grid-template-columns: 1fr; padding-block: 56px 48px; }
  .demo-panel { grid-template-columns: 1fr; padding: 24px; gap: 24px; }
  .tabs { display: flex; flex-wrap: wrap; }
  .section { padding-top: 88px; }
  .section-head { grid-template-columns: 1fr; gap: 16px; }
  .tiles { grid-template-columns: 1fr 1fr; }
}
/* Phones only: the leading pills that close each middle section (shown in the block below). */
.carry-row { display: none; }
@media (max-width: 680px) {
  .wrap { padding-inline: 16px; }
  .phone, .tiles { grid-template-columns: 1fr; }
  .btn .long { display: none; }
  .btn .short { display: inline; }
  /* Top bar: the mark and Log in (or Open console when signed in). The booking button joins
     them, compact, once the hero's Book has scrolled away and no other Book is on screen
     (landing.js sets .past-hero; R13, Chris 2026-10-02), so one Book shows at a time. Both
     bar buttons keep a 44px tap height, so the bar never changes height when Book arrives. */
  .account .btn.book { display: none; }
  .account .btn { min-height: 44px; }
  .site-nav.past-hero .account .btn.book { display: inline-flex; padding: 8px 14px; }
  /* The hero's Book is behind the bar by then; an opaque bar keeps it from ghosting through. */
  .site-nav.past-hero { background: var(--ground); }
  .account .btn.quiet { color: var(--ink); padding-inline: 4px; }
  .nav-row { padding-block: 12px; }
  /* Phone rhythm (Chris, 2026-10-02: "too cramped"): room between the headline, the lede, the
     buttons and the note, and more air above each section. */
  .hero { padding-block: 48px 56px; gap: 24px; }
  .hero h1 { font-size: 44px; line-height: 1.04; }
  .hero-aside { gap: 28px; padding-bottom: 0; }
  .hero .lede { font-size: 16px; line-height: 1.6; }
  .access { font-size: 12px; line-height: 1.7; }
  .demo-panel { padding: 18px; gap: 22px; border-radius: 18px; }
  /* The "Illustrative example" label stays on phones (L4): the reply-time stamp inside the
     example is only honest while the page says it is made up. Replay keeps its 44px hit area. */
  .demo-intro .sub { display: none; }
  .demo-foot { margin-top: -6px; }
  .demo-intro h2 { font-size: 26px; }
  /* Three equal cells that wrap their label (U9): "Home services" never clips and nothing
     scrolls sideways behind a hidden scrollbar. */
  .tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; overflow: visible; }
  .tabs [role=tab] { white-space: normal; text-align: center; line-height: 1.2; padding: 8px; font-size: 14px;
    border-radius: 14px; }
  .convo, .handoff { padding: 16px; }
  /* One card: the hand-off sits directly under the last message. */
  .phone { gap: 0; }
  .convo { border-radius: 16px 16px 0 0; }
  .handoff { border-radius: 0 0 16px 16px; border-top: 1px solid var(--line); }
  .facts { gap: 0 14px; }
  .facts dt, .facts dd { padding-block: 6px; }
  .section { padding-top: 88px; gap: 28px; }
  .section-head h2 { font-size: 32px; }
  .section-head .sub { font-size: 15px; }
  .timeline li { grid-template-columns: 1fr; gap: 8px; padding-block: 20px; }
  .numbered li { grid-template-columns: 40px minmax(0, 1fr); gap: 12px; padding-block: 20px; }
  /* Tiles become compact rows: a small drawing beside the copy. */
  .tiles { gap: 0; background: var(--panel); border-radius: 18px; padding: 4px 14px; }
  .tile { grid-template-columns: 56px minmax(0, 1fr); grid-template-rows: none; gap: 14px; align-items: start; background: none;
    border-radius: 0; padding-block: 18px; border-top: 1px solid var(--line); overflow: visible; }
  .tile:first-child { border-top: 0; }
  .tile:hover { transform: none; }
  .tile figure { aspect-ratio: 1; border-radius: 12px; }
  .tile svg { width: 80%; }
  .tile .copy { padding: 0; gap: 4px; }
  .tile h3 { font-size: 20px; }
  .tile p { font-size: 14px; }
  .tile .when { display: none; }
  .close { padding-block: 96px 112px; }
  .close h2 { font-size: 34px; }
  .foot { grid-template-columns: 1fr 1fr; }
  .foot-brand { grid-column: 1 / -1; }
  /* Leading pills: one closes each middle section; the floating pill (landing.js) copies the
     last one scrolled past and steps aside while an inline pill crosses its spot. It carries
     section pills only: booking lives in the top bar (R13). */
  .carry-row { display: flex; justify-content: flex-end; padding-top: 4px; }
  .demo > .carry-row { padding: 16px 16px 0; }
  .lead-pill, .float-pill { display: inline-flex; align-items: center; gap: 8px; border-radius: 999px;
    font: 500 15px var(--body); text-decoration: none; white-space: nowrap;
    background: var(--accent-soft); color: var(--accent-ink); }
  .lead-pill, .float-pill { min-height: 44px; }
  .lead-pill { padding: 11px 16px; }
  .lead-pill svg, .float-pill svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round; }
  .float-pill { position: fixed; right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 30;
    padding: 13px 18px; box-shadow: 0 8px 24px rgba(28, 21, 51, .18), 0 1px 2px rgba(28, 21, 51, .1);
    transition: opacity .2s ease, transform .2s ease, background .2s ease, color .2s ease; }
  .float-pill.away { opacity: 0; transform: translateY(12px); pointer-events: none; }
}
@media (min-width: 681px) { .float-pill { display: none; } }
@media (max-width: 680px) {
  .demo-panel.morph { --r: 18px; }
  .demo-panel.morph, .tiles.morph { border-radius: calc((1 - var(--p)) * var(--r) / var(--s)); }
  .tiles.morph { --r: 18px; background: var(--panel); padding: 4px 14px; gap: 0; }
  .tiles.morph .tile { border-radius: 0; background: none; }
}
@media (max-width: 340px) { .brand-name { display: none; } }
/* Narrowest phones: while the bar carries Book, the mark stands in for the name, so mark, Log
   in and Book fit on one line. Mark, name, Log in and either booking label measure as fitting
   at 360px and up, so common phones (375, 390) keep the name. */
@media (max-width: 359px) { .site-nav.past-hero .brand-name { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .hero h1, .msg.typing span, .ul-draw > span, .handoff.pending::after { animation: none; }
  .btn, .tile, .msg, .float-pill { transition: none; }
}

/* ---- Auth (the Jinja templates; the Next auth pages carry the same look) ---- */
.auth { min-height: 100vh; display: grid; grid-template-columns: minmax(0, 1fr); place-items: center; padding: 24px; }
.auth-card { width: 400px; max-width: 100%; background: var(--surface); border: 1px solid var(--line); border-radius: 18px;
  padding: 28px 28px 24px; box-shadow: 0 1px 2px rgba(28, 21, 51, .04); }
.auth-card .brand { margin-bottom: 18px; }
.auth-card .brand img.mark { height: 30px; }
.auth-card .brand img.word { height: 14px; }
.auth-card h1 { font-size: 30px; font-weight: 500; letter-spacing: -0.015em; margin: 0 0 4px; }
.auth-card .lede { color: var(--muted); font-size: 14.5px; margin: 0 0 18px; }
.auth-card .foot-links { color: var(--muted); font-size: 13px; margin: 16px 0 0; }
.auth-card .legal { color: var(--muted); font-size: 12px; margin: 18px 0 0; text-align: center; background: none; border: 0; padding: 0; }
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 5px; }
.field .hint { font-size: 12.5px; color: var(--muted); margin-top: 4px; }
input[type=text], input[type=email], input[type=password], input[type=tel] { width: 100%; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface); font: 15px var(--body); color: var(--ink); }
input:focus { border-color: var(--accent); }
.callout { border-left: 3px solid var(--accent); background: var(--panel); border-radius: 0 10px 10px 0;
  padding: 10px 14px; font-size: 13.5px; margin-bottom: 14px; }
.error-note { color: var(--bad); font-size: 13.5px; margin-bottom: 12px; }
.hp { position: absolute; left: -9999px; }

/* ---- Legal pages (privacy, terms) ---- */
.legal-nav { max-width: 720px; margin: 0 auto; padding: 22px 28px; display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.legal-nav-links { display: flex; gap: 8px; flex-wrap: wrap; }
.legal-nav .btn { padding: 9px 16px; font-size: 14px; }
.legal-nav .brand img.mark { height: 28px; }
.legal-nav .brand img.word { height: 14px; }
.legal-page { max-width: 720px; margin: 0 auto; padding: 24px 28px 48px; }
.legal-page h1 { font-size: clamp(34px, 5vw, 52px); line-height: 1.05; }
.legal-page .effective { font: 13px var(--mono); color: var(--muted); margin: 12px 0 28px; }
.legal { background: var(--panel); border-radius: 18px; padding: 32px 36px; }
.legal h2 { font: 600 17px var(--body); letter-spacing: 0; margin: 28px 0 8px; }
.legal h2:first-child { margin-top: 0; }
/* Prose measure (L12): 52ch, not the old ~100 characters a line. `ch` is the width of a
   zero, so the real line length is measured in a browser against the real font. */
.legal p, .legal li { color: var(--muted); font-size: 16px; line-height: 1.65; max-width: 52ch; }
.legal p { margin: 0 0 12px; }
.legal p:last-child { margin-bottom: 0; }
.legal b { color: var(--ink); }
.legal a { color: var(--ink); text-decoration-color: var(--accent); text-underline-offset: 2px; }
.legal .legal-todo { background: var(--warn-soft); color: var(--ink); border-radius: 4px; padding: 0 4px; }
.legal-foot { max-width: 720px; margin: 0 auto; padding: 0 28px 40px; display: flex; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; font: 12px var(--mono); color: var(--muted); }
.legal-foot a { color: inherit; }
@media (max-width: 560px) {
  .legal-nav, .legal-page, .legal-foot { padding-inline: 16px; }
  .legal { padding: 20px 18px; }
}

/* iOS Safari zooms the page when a field under 16px takes focus, and stays zoomed, so the
   layout looks cut off on the right (Chris, 2026-10-02, the Studio chat on a phone). Touch
   screens and phone widths get 16px in every text field; !important because the fields'
   own classes (e.g. .sc-composer-input at 14.5px) set a smaller size. */
@media (pointer: coarse), (max-width: 680px) {
  input:not([type=checkbox]):not([type=radio]):not([type=range]), textarea, select { font-size: 16px !important; }
}

/* Forgot password sits under the password field, where the failure happens (L7), and the
   sign-up link gets its own line below the button so the two opposite intents never touch. */
.auth-card .field-aux { display: flex; justify-content: flex-end; margin: -8px 0 6px; }
.auth-card .field-aux a { display: inline-flex; align-items: center; min-height: 44px; padding-inline: 4px;
  font-size: 14px; color: var(--muted); }

/* The signup confirmation's note and two exits (L8; the Jinja rollback of the Next page). */
.auth-card .auth-done-note { color: var(--ink); font-size: 14.5px; margin: 0 0 18px; }
.auth-card .auth-done-actions { display: grid; gap: 10px; margin-top: 4px; }
.auth-card .auth-done-actions .btn { min-height: 44px; }

/* Touch targets (L9): one query for every public page, the same one the 16px-field rule
   above uses. Links that stand alone in a footer or card get a 44px hit area; links inside
   a sentence of legal prose are exempt (WCAG's inline exception). */
@media (pointer: coarse), (max-width: 680px) {
  .brand { min-height: 44px; }
  .foot-col a { display: flex; align-items: center; min-height: 44px; padding-block: 0; }
  .foot-contact { display: inline-flex; align-items: center; min-height: 44px; }
  .legal-nav .btn { min-height: 44px; }
  .page-links a, .site-nav .btn { min-height: 44px; display: inline-flex; align-items: center; }
  .legal-foot a { display: inline-flex; align-items: center; min-height: 44px; }
  .legal-foot > span:last-child { display: inline-flex; align-items: center; gap: 8px; }
  .auth-card .foot-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0 6px; }
  .auth-card .foot-links a, .auth-card .legal a { display: inline-flex; align-items: center; min-height: 44px; }
  .auth-card .legal { display: flex; justify-content: center; align-items: center; gap: 8px; }
}
