:root{color-scheme:light}
*{box-sizing:border-box;margin:0}
body{font-family:'Instrument Sans',Helvetica,Arial,sans-serif;background:#fafbfc;color:#191d23;line-height:1.6;font-size:20px;-webkit-font-smoothing:antialiased}
a{color:oklch(0.42 0.09 255);text-decoration:none}
a:hover{color:oklch(0.32 0.09 255);text-decoration:underline}
.wrap{max-width:1120px;margin:0 auto;padding:0 24px}
header{border-bottom:1px solid #e6e9ee;background:#fafbfc}
.nav{display:flex;align-items:center;justify-content:space-between;height:68px}
.brand{font-weight:700;font-size:21px;letter-spacing:-0.02em;color:#191d23}
.brand:hover{text-decoration:none;color:#191d23}
.brand span{color:oklch(0.42 0.09 255)}
.nav ul{display:flex;gap:28px;list-style:none;padding:0}
.nav ul a{color:#454c57;font-size:15px;font-weight:500}
.nav ul a:hover{color:#191d23;text-decoration:none}
.nav ul a.on{color:oklch(0.42 0.09 255)}
main{padding:64px 0 88px}
h1{font-size:46px;letter-spacing:-0.02em;line-height:1.15;margin-bottom:20px;font-weight:700}
.prose{max-width:none}
.prose p{margin-bottom:16px;color:#333a44}
.prose h2{font-size:25px;margin:36px 0 12px;letter-spacing:-0.01em}
.prose ul{margin:0 0 16px;padding-left:22px;color:#333a44}
.prose li{margin-bottom:6px}
.muted{color:#6a7280;font-size:18px}
.btn{display:inline-block;background:oklch(0.42 0.09 255);color:#fff;padding:12px 26px;border-radius:6px;font-weight:600;font-size:18.5px}
.btn:hover{background:oklch(0.36 0.09 255);color:#fff;text-decoration:none}
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:16px;margin:28px 0}
.card{border:1px solid #e6e9ee;background:#fff;border-radius:8px;padding:20px 22px}
.card h3{font-size:20px;margin-bottom:6px;font-weight:600}
.card p{font-size:17px;color:#6a7280}
.kv{border:1px solid #e6e9ee;background:#fff;border-radius:8px;max-width:none;margin-top:28px}
.kv div{display:grid;grid-template-columns:300px 1fr;gap:16px;padding:14px 22px;border-top:1px solid #eef0f4;font-size:18.5px}
.kv div:first-child{border-top:0}
.kv dt{color:#6a7280;font-weight:500}
.kv dd{color:#191d23}
footer{border-top:1px solid #e6e9ee;background:#f3f5f8;padding:44px 0 36px;font-size:14.5px;color:#5c6470}
.fcols{display:flex;flex-wrap:wrap;gap:48px;justify-content:space-between}
.fbrand{font-weight:700;font-size:17px;color:#191d23;margin-bottom:8px}
.fcols ul{list-style:none;padding:0;display:grid;grid-template-columns:repeat(2,minmax(100px,auto));gap:6px 36px}
.fcols ul a{color:#5c6470}
.legalline{margin-top:32px;padding-top:20px;border-top:1px solid #e2e5ea;font-size:13.5px;color:#7a828e}
@media(max-width:640px){.nav ul{gap:16px}.nav ul a{font-size:13.5px}h1{font-size:36px}.kv div{grid-template-columns:1fr;gap:2px}}
.appheader{display:flex;align-items:center;gap:22px;margin-bottom:22px}
.appheader h1{margin-bottom:2px}
.appicon{width:84px;height:84px;border-radius:19px;flex:0 0 auto;box-shadow:0 2px 12px oklch(0.42 0.09 255 / 0.16)}
.subtitle{font-size:23px;font-weight:500;letter-spacing:-0.01em;color:#6a7280}
.faq h3{font-size:21px;margin:28px 0 10px;letter-spacing:-0.01em}
@media(max-width:640px){.appheader{gap:16px}.appicon{width:62px;height:62px;border-radius:14px}}
/* The screenshot strip on /apps/nowline/. It scrolls sideways rather than
   wrapping into the .cards grid: five phone frames laid out in a grid either
   shrink past the point where the screen inside them reads, or push the page's
   own prose below two screens of pictures. Three are visible at 960px, and the
   fourth peeking past the edge is the scroll affordance. No border -- these
   frames are near-black, and a light rule around one reads as a halo -- the
   .appicon shadow instead, so icon and screenshots sit on the page the same
   way. The background is the frames' own top colour (surfMid0), so the box does
   not flash white while the image loads.

   The scrollbar is hidden. It sat under the frames as a grey slab with nothing
   else on the page to justify it, and hiding it means the affordance has to come
   from somewhere else: the next frame is always cut by the right edge, and the
   two round buttons scroll by exactly one frame. Only the bar is gone -- wheel,
   trackpad, touch and arrow keys all still scroll the strip, and the buttons are
   an addition rather than the only way through. */
.shotstrip{position:relative;margin:32px 0}
.shots{display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x proximity;scroll-behavior:smooth;scrollbar-width:none}
.shots::-webkit-scrollbar{display:none}
.shot{flex:0 0 272px;padding:0;border:0;background:none;cursor:zoom-in;scroll-snap-align:start;border-radius:12px;line-height:0}
.shot img{width:272px;height:auto;display:block;border-radius:12px;background:#0c0e1b;box-shadow:0 2px 12px oklch(0.42 0.09 255 / 0.16)}
.shot:focus-visible{outline:3px solid oklch(0.42 0.09 255);outline-offset:3px}
/* The scroll buttons sit over the gutter between frames rather than over a
   frame, and disappear at the end they would do nothing at. */
.shotnav{position:absolute;top:50%;transform:translateY(-50%);width:44px;height:44px;border-radius:50%;border:1px solid #e6e9ee;background:#fff;color:#191d23;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px oklch(0.42 0.09 255 / 0.18);transition:opacity .15s}
.shotnav[hidden]{display:none}
.shotnav:hover{background:#f3f5f8}
.shotnav--prev{left:-14px}
.shotnav--next{right:-14px}
.shotnav svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
@media(max-width:640px){.shot{flex:0 0 228px}.shot img{width:228px}.shotnav{display:none}}

/* The lightbox. A native <dialog>, so Esc, the backdrop, modality and returning
   focus to the frame that opened it are the browser's job rather than ours --
   which is most of why this is sixty lines and not a dependency. */
/* Centred explicitly rather than left to the UA's margin:auto, which does not
   land it in the middle here. Filling the viewport also gives the backdrop
   click a target: anything outside the figure is the dialog itself. */
.lb{position:fixed;inset:0;width:100vw;height:100vh;max-width:100vw;max-height:100vh;margin:0;border:0;padding:0;background:none;overflow:hidden}
.lb[open]{display:grid;place-items:center}
.lb::backdrop{background:oklch(0.16 0.02 255 / 0.82)}
.lb-fig{display:flex;flex-direction:column;align-items:center;gap:14px;margin:0}
.lb-img{max-width:min(600px,86vw);max-height:82vh;width:auto;height:auto;border-radius:14px;background:#0c0e1b;display:block}
.lb-cap{color:#e7eaf0;font-size:16px;line-height:1.45;max-width:min(600px,86vw);text-align:center;margin:0}
.lb-btn{position:fixed;width:48px;height:48px;border-radius:50%;border:1px solid oklch(1 0 0 / 0.22);background:oklch(1 0 0 / 0.12);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;backdrop-filter:blur(6px)}
.lb-btn:hover{background:oklch(1 0 0 / 0.22)}
.lb-btn[hidden]{display:none}
.lb-btn svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.lb-prev{left:16px;top:50%;transform:translateY(-50%)}
.lb-next{right:16px;top:50%;transform:translateY(-50%)}
.lb-close{right:16px;top:16px}
body.lb-open{overflow:hidden}
@media(max-width:640px){.lb-prev{left:8px}.lb-next{right:8px}.lb-btn{width:42px;height:42px}}
/* The NowLine wordmark, set in Outfit at weight 450. This is the second
   and last family on the site, and it sets the mark and nothing else.
   outfit-450-nowline.ttf is the app's own assets/fonts/Outfit.ttf, instanced at
   450 and subset to the seven letters of the mark -- it will render nothing
   else. Same file as the app on purpose: the kerning below was solved against
   this build. SIL OFL, licence text in OFL-Outfit.txt beside it. */
@font-face{font-family:'Outfit';src:url('outfit-450-nowline.ttf') format('truetype');font-weight:400;font-style:normal;font-display:swap}
/* Optical kerning, in em, applied after each character. These are the
   generator's numbers (tool/gen/generate_brand_assets.py DRAW_SPACING), not the
   app's: Flutter applies Outfit's own kerning across span boundaries and a
   browser does not, so `ow` carries the full -0.0200 here where the app carries
   -0.0070. Both put the glyph in the same place. Global tracking of -0.020 is
   already folded into every value. */
.wordmark{font-family:'Outfit','Instrument Sans',Helvetica,Arial,sans-serif;font-weight:400;font-kerning:none;letter-spacing:0;white-space:nowrap}
.wordmark span:nth-child(1){letter-spacing:-0.0091em}
.wordmark span:nth-child(2){letter-spacing:-0.0200em}
.wordmark span:nth-child(3){letter-spacing:-0.0275em}
.wordmark span:nth-child(4){letter-spacing:-0.0100em}
.wordmark span:nth-child(5){letter-spacing:0.0247em}
.wordmark span:nth-child(6){letter-spacing:0.0125em}
/* The last letter carries 0 and inherits it: letter-spacing is added *after* a
   character, so a value there would hang empty space off the end of the mark. */
