html{scroll-padding-top:72px}
/* Polyphonic — v3 landing. Tokens, type and state rules; the page's structure is inline-styled in
   index.html, exactly as the prototype specifies it (see README.md, "v3"). */

/* ---- fonts ---- local only; no Google Fonts, no third-party request anywhere on this page. */
@font-face{font-family:'Instrument Sans';src:url(fonts/instrument-sans.woff2) format('woff2');font-style:normal;font-weight:400 700;font-display:swap}
@font-face{font-family:'Fragment Mono';src:url(fonts/fragment-mono.woff2) format('woff2');font-style:normal;font-weight:400;font-display:swap}
/* Metric-matched fallbacks: a local face scaled with its line metrics overridden, so text set in the
   fallback fills the webfont's box and the swap moves nothing (measured in Chromium, WP-13). */
@font-face{font-family:'Instrument Sans Fallback';src:local('Arial'),local('ArialMT');font-style:normal;font-weight:400 500;size-adjust:104%;ascent-override:93.3%;descent-override:24%;line-gap-override:0%}
@font-face{font-family:'Instrument Sans Fallback';src:local('Arial Bold'),local('Arial-BoldMT');font-style:normal;font-weight:600 700;size-adjust:98.2%;ascent-override:98.8%;descent-override:25.5%;line-gap-override:0%}
@font-face{font-family:'Fragment Mono Fallback';src:local('Menlo'),local('Menlo-Regular');font-style:normal;font-weight:400;size-adjust:102.65%;ascent-override:92.55%;descent-override:24.35%;line-gap-override:0%}

*{box-sizing:border-box}
:root{
  --bg:#000000;--s1:#0E0E0E;--s2:#161616;--s3:#1E1E1E;--line:#232323;--line2:#2E2E2E;
  /* t2/t3 are the prototype's #565656 raised for legibility (WP-18 decision 2). They carry the
     commons eyebrow and numbers, the room topics and composers, the feed rows and the footer's
     legal line. #7E7E7E clears 4.5:1 on #000 and #0E0E0E but measures 4.46 on the #161616 card
     ground these rows actually sit on, so the token is #848484: measured 5.62 on #000,
     5.16 on #0E0E0E, 4.84 on #161616. */
  --t0:#E4E4E0;--t1:#B4B4B4;--t2:#848484;--t3:#848484;
  --glass:#0A0B0A;
  --sans:'Instrument Sans','Instrument Sans Fallback',system-ui,sans-serif;
  --mono:'Fragment Mono','Fragment Mono Fallback',ui-monospace,monospace;
  --pad:clamp(20px,5vw,80px);
  --ease-ctl:cubic-bezier(.2,0,0,1);--ease-page:cubic-bezier(.16,1,.3,1);
  --app-ink:#c7c6be;--app-surface:#101010;
  color-scheme:dark;
}
html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--t1);font-family:var(--sans);font-size:17px;line-height:1.62;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
#pp-root{position:relative;z-index:0;min-height:100vh;background:var(--bg);overflow-x:clip}
::selection{background:var(--t0);color:var(--bg)}
a{color:var(--t0);text-decoration:none}
button,input{font-family:inherit}
[hidden]{display:none!important}

/* Keyboard focus only. The prototype's red ring fired on mouse clicks too (WP-18 decision 2). */
:focus{outline:none}
:focus-visible{outline:2px solid var(--t0);outline-offset:3px}

.pp-sr{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}
.pp-hp{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}
.pp-skip{position:absolute;left:-9999px;top:0;z-index:60;padding:10px 16px;background:var(--t0);color:var(--bg);border-radius:0 0 8px 0;font-size:14px}
.pp-skip:focus-visible{left:0}

/* ---- controls: five states, no colour outside the tokens ---- */
.pp-pill,.pp-pill-btn{transition:transform .12s var(--ease-ctl),background .12s var(--ease-ctl)}
.pp-pill:hover,.pp-pill-btn:hover{background:#D3D3CF;color:var(--bg)}
.pp-pill:active,.pp-pill-btn:active{transform:translateY(1px)}
.pp-lnk{transition:color .12s var(--ease-ctl)}
.pp-lnk:hover{color:var(--t0)}
.pp-lnk1{transition:color .12s var(--ease-ctl)}
.pp-lnk1:hover{color:var(--t0)}
.pp-hairbtn{transition:transform .12s var(--ease-ctl),border-color .12s var(--ease-ctl)}
.pp-hairbtn:hover{border-color:var(--t2)}
.pp-hairbtn:active{transform:translateY(1px)}
.pp-quietbtn{transition:color .12s var(--ease-ctl),border-color .12s var(--ease-ctl)}
.pp-quietbtn:hover{color:var(--t0)}
.pp-field{outline:none;transition:border-color .12s var(--ease-ctl)}
.pp-field:focus{border-color:var(--t2)}
.pp-field:focus-visible{border-color:var(--t2);outline:2px solid var(--t0);outline-offset:3px}
.pp-field[aria-invalid="true"]{border-color:#C94B40}
.pp-privacy{margin-left:10px;color:var(--t2);transition:color .12s var(--ease-ctl)}
.pp-privacy:hover{color:var(--t0)}

/* ---- phone nav (WP-18 decision 2) ---- the prototype pushes "Beta" and the pill off-screen
   below ~550px. Below 640px the three text links stand down; the pill, whose target is #beta,
   stays, so the beta section is still one tap away. */
@media (max-width:639px){.pp-navlinks{display:none!important}}

/* ---- page motion ---- */
@keyframes pp-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes pp-blink{0%,80%,100%{opacity:.25}40%{opacity:1}}
@keyframes pp-frame{from{opacity:0;transform:translateY(20px) scale(.986)}to{opacity:1;transform:none}}
@keyframes pp-fromleft{from{opacity:0;transform:translateX(-24px)}to{opacity:1;transform:none}}
@keyframes pp-rise{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
.pp-fade{animation:pp-in .36s var(--ease-page) both}
/* Reveals and Luca's replay arm themselves in CSS, so nothing flashes before the script runs and no
   inline script is needed. Under reduced motion neither block applies; without scripting the
   <noscript> block in index.html shows everything at once. */
@media (prefers-reduced-motion:no-preference){
  [data-rv]{opacity:0;transform:translateY(26px);transition:opacity .7s var(--ease-page),transform .7s var(--ease-page)}
  [data-rv="on"]{opacity:1;transform:none}
  [data-replay="armed"] .pp-ghost{visibility:hidden}
  [data-replay="armed"] .pp-type{display:block;position:absolute;inset:0}
  /* the dots overlay the paragraph's reserved box instead of taking a row of their own, so
     showing and hiding them cannot move anything below (WP-18: 0px shift, measured). */
  [data-replay="armed"] .pp-dots{display:inline-flex;gap:5px;align-items:center;position:absolute;left:2px;top:0;height:27px}
  [data-replay="armed"] [data-pp-cards] > *,[data-replay="armed"] [data-pp-receipt]{visibility:hidden}
  [data-replay="armed"] [data-pp-cards] > [data-on="1"],[data-replay="armed"] [data-pp-receipt][data-on="1"]{visibility:visible}
}

/* ---- the shell ---- tokens resolved from the app's source under vitesse-black; row states from
   its conversation-shell.css; online green is PresenceDot's bg-emerald-500. */
/* The shell's tokens come from the app's own source. ink-faint is the one exception: at the
   app's 50.6% it measures 4.43:1 on the selected chat row's #1f1e1e ground, so it is 54%
   (measured 4.86:1 there). Same legibility deviation as --t2/--t3 above. */
[data-pp-shell]{--mn-raised:0 0% 8.6%;--mn-border:60 2.22% 17.6%;--mn-ink:44 12% 75.5%;--mn-ink-muted:50 5.88% 60%;--mn-ink-faint:48 3.97% 54%;--mn-ink-ghost:42.9 3.74% 36.7%;--mn-online:oklch(69.6% .17 162.48)}
[data-pp-row]{display:flex;align-items:center;gap:10px;width:100%;min-height:30px;padding:0 8px;border:1px solid transparent;border-radius:8px;background:transparent;color:hsl(var(--mn-ink-muted));font:inherit;text-align:left;cursor:pointer}
[data-pp-row]:not([data-active="true"]):hover{background:hsl(var(--mn-ink) / .045);color:hsl(var(--mn-ink))}
[data-pp-row][data-open="true"]{background:hsl(var(--mn-ink) / .06);color:hsl(var(--mn-ink))}
[data-pp-row][data-open="true"]:hover{background:hsl(var(--mn-ink) / .075)}
[data-pp-row][data-active="true"]{background:hsl(var(--mn-ink) / .08);color:hsl(var(--mn-ink))}
[data-pp-row][data-active="true"] svg{color:hsl(var(--mn-ink) / .72)}
[data-pp-slot]{color:hsl(var(--mn-ink-muted))}
[data-open="true"] [data-pp-slot]{color:hsl(var(--mn-ink))}
[data-pp-control]{background:transparent;color:hsl(var(--mn-ink-faint))}
[data-pp-control]:hover{background:hsl(var(--mn-raised));color:hsl(var(--mn-ink))}
[data-pp-row]:focus-visible,[data-pp-control]:focus-visible{outline:1px solid hsl(var(--mn-ink) / .5);outline-offset:-1px}
[data-pp-row][data-active="true"]:focus-visible{background:hsl(var(--mn-ink) / .12);outline:none}
[data-rail]::-webkit-scrollbar{width:6px}
[data-rail]::-webkit-scrollbar-track{background:transparent}
[data-rail]::-webkit-scrollbar-thumb{background:#2a2a28;border-radius:3px}
[data-rail]{scrollbar-width:thin;scrollbar-color:#2a2a28 transparent}

/* The rail appears at 760px of page width and the chats column at 840px, as the prototype's
   state.w (the root element's width) switches them. */
[data-pp-shell]{grid-template-columns:minmax(0,1fr)}
[data-pp-rail-col]{display:none}
[data-pp-floor]{padding:5px}
[data-pp-inner]{grid-template-columns:minmax(0,1fr)}
[data-pp-chats]{display:none}
@media (min-width:760px){
  [data-pp-shell]{grid-template-columns:224px minmax(0,1fr)}
  [data-pp-rail-col]{display:flex}
  [data-pp-floor]{padding:5px 5px 5px 0}
}
@media (min-width:840px){
  [data-pp-inner]{grid-template-columns:194px minmax(0,1fr)}
  [data-pp-chats]{display:flex}
}
/* × collapses the column until the next rail pick. */
[data-pp-shell][data-list="closed"] [data-pp-inner]{grid-template-columns:minmax(0,1fr)}
[data-pp-shell][data-list="closed"] [data-pp-chats]{display:none}

/* ---- Luca's replay ---- the finished text is in the HTML, so the page reads without JS and under
   reduced motion. While the replay is armed the finished text is present but invisible, holding the
   paragraph's height, and the typed characters are laid over it: nothing in the frame moves. */
.pp-para{position:relative}
.pp-type,.pp-dots{display:none}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  [data-rv-ready] [data-rv]{opacity:1;transform:none}
}
