/* The home page. External so the Content-Security-Policy can forbid inline styles. */
@font-face { font-family: 'Bricolage Grotesque'; src: url(fonts/bricolage.woff2) format('woff2'); font-weight: 400 800; font-display: swap; }
@font-face { font-family: 'Bricolage Lite'; src: url(fonts/bricolage-lite.woff2) format('woff2'); font-weight: 400 800; font-display: swap; }
/* Numbers on the chart and the storm's pressure: a few glyphs, a kilobyte or two. */
@font-face { font-family: 'Chart Mono'; src: url(fonts/chart-mono-400.woff2) format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Chart Mono'; src: url(fonts/chart-mono-500.woff2) format('woff2'); font-weight: 500; font-display: swap; }
/* System fonts resized to Bricolage's measure, so nothing jumps when it arrives. */
@font-face { font-family: 'Challoop Fallback'; src: local('Roboto'), local('Arial'), local('Helvetica Neue'), local('Helvetica'); font-weight: 400 500; size-adjust: 103.5%; ascent-override: 89%; descent-override: 26%; line-gap-override: 0%; }
@font-face { font-family: 'Challoop Fallback'; src: local('Roboto Bold'), local('Arial Bold'), local('Helvetica Neue Bold'), local('Helvetica Bold'); font-weight: 600 800; size-adjust: 93%; ascent-override: 100%; descent-override: 29%; line-gap-override: 0%; }
:root {
  --ink: #1e1a3c;
  --muted: #5d597b;
  --sand: #fbf6ec;
  --sky: #bfe2ff;
  --sea: #1c8fb8;
  --butter: #ffe68e;
  --apricot: #ffbe8a;
  --rose: #ffb1cb;
  --sans: 'Bricolage Grotesque', 'Challoop Fallback', 'Avenir Next', 'Helvetica Neue', sans-serif;
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --hero-tail: min(24vh, 13.75rem);
  --run: 360;
  --tail: 45vh;
  --cloud: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 170' preserveAspectRatio='none'%3E%3Cfilter id='b' x='-5%25' y='-20%25' width='110%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='3.2'/%3E%3C/filter%3E%3Cg filter='url(%23b)'%3E%3Cpath fill='%23fff' d='M0 104C20 92 30 62 70 56 84 30 130 14 178 26 214 6 276 12 304 44 336 46 366 64 398 78 470 84 560 90 660 92 760 92 850 84 930 72 956 44 1000 26 1046 34 1080 8 1150 4 1196 28 1240 16 1310 26 1340 54 1382 58 1420 78 1440 92L1440 126C1330 142 1180 140 1050 128 900 118 760 112 640 112 500 112 380 130 250 138 150 142 60 134 0 122Z'/%3E%3Cpath fill='%23b9c9f7' fill-opacity='.7' d='M30 122C110 130 230 128 340 112 280 134 120 142 30 122ZM1020 118C1120 132 1290 130 1420 112 1340 140 1140 144 1020 118Z'/%3E%3C/g%3E%3C/svg%3E");
  --cloud-narrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 170' preserveAspectRatio='none'%3E%3Cfilter id='b' x='-5%25' y='-20%25' width='110%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='2.4'/%3E%3C/filter%3E%3Cg filter='url(%23b)'%3E%3Cpath fill='%23fff' d='M-10 96C8 76 20 48 58 42 74 18 118 6 158 16 190 0 250 2 276 26 316 22 360 38 372 66 396 72 410 92 410 108 400 134 330 146 240 146 160 152 70 146 14 130-6 122-14 108-10 96Z'/%3E%3Cpath fill='%23b9c9f7' fill-opacity='.7' d='M22 124C100 136 280 138 396 112 360 148 110 158 22 124Z'/%3E%3C/g%3E%3C/svg%3E");
  --stroke: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 24' preserveAspectRatio='none'%3E%3Cpath d='M2 15C50 7 96 19 148 12S240 6 276 9c8 1 9 4 3 5-40 1-80 4-129 6-50 2-102-4-146-1-4 0-5-3-2-4z'/%3E%3Ccircle cx='291' cy='6' r='3.2'/%3E%3Ccircle cx='297' cy='14' r='1.8'/%3E%3C/svg%3E");
  /* Static torn edges: the paper for first paint, for low tiers and without script. */
  --tear-hero: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cpath id='e' d='M0 51l16 1 15 1 16 3 16 2 15 1 16 0 15 1 16-3 16 0 15-1 16-4 16-2 15 0 16 2 15-1 16 6 16 2 15 1 16-4 16-1 15 5 16 3 15 2 16 4 16 2 15-4 16-1 16 1 15 3 16 2 15 2 16 0 16-1 15-2 16-1 16-6 15-4 16-2 15-3 16-2 16-5 15-5 16-3 16-3 15-1 16-1 15-2 16-7 16 0 15 1 16 4 16-1 15-1 16 0 15 0 16 2 16 2 15 2 16-1 16 1 15 1 16 2 15 1 16 1' vector-effect='non-scaling-stroke'/%3E%3C/defs%3E%3Cpath d='M0 51l16 1 15 1 16 3 16 2 15 1 16 0 15 1 16-3 16 0 15-1 16-4 16-2 15 0 16 2 15-1 16 6 16 2 15 1 16-4 16-1 15 5 16 3 15 2 16 4 16 2 15-4 16-1 16 1 15 3 16 2 15 2 16 0 16-1 15-2 16-1 16-6 15-4 16-2 15-3 16-2 16-5 15-5 16-3 16-3 15-1 16-1 15-2 16-7 16 0 15 1 16 4 16-1 15-1 16 0 15 0 16 2 16 2 15 2 16-1 16 1 15 1 16 2 15 1 16 1V100H0z' fill='%23fbf6ec'/%3E%3Cg fill='none' stroke='%231c8fb8' vector-effect='non-scaling-stroke'%3E%3Cuse href='%23e' y='-3' stroke-opacity='0.75'/%3E%3Cuse href='%23e' y='-8' stroke-opacity='0.54'/%3E%3Cuse href='%23e' y='-16' stroke-opacity='0.33'/%3E%3C/g%3E%3C/svg%3E");
  --tear-in: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x2='0' y2='1'%3E%3Cstop stop-color='%23fbf6ec'/%3E%3Cstop offset='.35' stop-color='%23dcdfe6'/%3E%3Cstop offset='.7' stop-color='%23a6aecb'/%3E%3Cstop offset='1' stop-color='%236d70a0'/%3E%3C/linearGradient%3E%3Cpath id='e' d='M0 70l16 4 15-1 16-5 16-6 15-6 16 0 15 2 16-1 16 0 15 2 16 0 16 3 15-2 16-4 15-6 16 0 16-5 15-2 16-5 16-2 15 0 16 0 15 5 16 5 16 1 15 1 16 2 16 2 15-2 16 6 15 4 16 1 16 1 15 1 16-5 16-6 15-4 16-5 15-2 16-1 16-2 15 1 16 0 16 0 15-2 16-1 15-1 16-1 16 0 15-1 16-3 16 0 15-4 16 1 15 5 16 9 16 4 15 6 16 4 16 5 15 4 16 4 15 2 16 2' vector-effect='non-scaling-stroke'/%3E%3C/defs%3E%3Cpath d='M0 70l16 4 15-1 16-5 16-6 15-6 16 0 15 2 16-1 16 0 15 2 16 0 16 3 15-2 16-4 15-6 16 0 16-5 15-2 16-5 16-2 15 0 16 0 15 5 16 5 16 1 15 1 16 2 16 2 15-2 16 6 15 4 16 1 16 1 15 1 16-5 16-6 15-4 16-5 15-2 16-1 16-2 15 1 16 0 16 0 15-2 16-1 15-1 16-1 16 0 15-1 16-3 16 0 15-4 16 1 15 5 16 9 16 4 15 6 16 4 16 5 15 4 16 4 15 2 16 2V0H0z' fill='url(%23g)'/%3E%3Cg fill='none' stroke='%231e1a3c' vector-effect='non-scaling-stroke'%3E%3Cuse href='%23e' y='3' stroke-opacity='0.55'/%3E%3Cuse href='%23e' y='8' stroke-opacity='0.40'/%3E%3Cuse href='%23e' y='16' stroke-opacity='0.24'/%3E%3C/g%3E%3C/svg%3E");
  --tear-out: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x2='0' y2='1'%3E%3Cstop stop-color='%23fba99c'/%3E%3Cstop offset='.4' stop-color='%23fbbb84'/%3E%3Cstop offset='.75' stop-color='%23fbe096'/%3E%3Cstop offset='1' stop-color='%23fbf6ec'/%3E%3C/linearGradient%3E%3Cpath id='e' d='M0 35l16 3 15 4 16 8 16 11 15 7 16 5 15 1 16-2 16-11 15-4 16-5 16-6 15 0 16 0 15 1 16 4 16 3 15-3 16 5 16 1 15-6 16-2 15-1 16 0 16 3 15 4 16 2 16-2 15 2 16-4 15 4 16-2 16-3 15-4 16-1 16-6 15-2 16 1 15 2 16-1 16 0 15 1 16-3 16-1 15-3 16-4 15-3 16-2 16 3 15-1 16-1 16-1 15 1 16 5 15 1 16-3 16 4 15-3 16-1 16-1 15-2 16 6 15 3 16 1' vector-effect='non-scaling-stroke'/%3E%3C/defs%3E%3Cpath d='M0 35l16 3 15 4 16 8 16 11 15 7 16 5 15 1 16-2 16-11 15-4 16-5 16-6 15 0 16 0 15 1 16 4 16 3 15-3 16 5 16 1 15-6 16-2 15-1 16 0 16 3 15 4 16 2 16-2 15 2 16-4 15 4 16-2 16-3 15-4 16-1 16-6 15-2 16 1 15 2 16-1 16 0 15 1 16-3 16-1 15-3 16-4 15-3 16-2 16 3 15-1 16-1 16-1 15 1 16 5 15 1 16-3 16 4 15-3 16-1 16-1 15-2 16 6 15 3 16 1V100H0z' fill='url(%23g)'/%3E%3Cg fill='none' stroke='%231e1a3c' vector-effect='non-scaling-stroke'%3E%3Cuse href='%23e' y='-3' stroke-opacity='0.40'/%3E%3Cuse href='%23e' y='-8' stroke-opacity='0.29'/%3E%3Cuse href='%23e' y='-16' stroke-opacity='0.18'/%3E%3C/g%3E%3C/svg%3E");
  --tear-front: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cpath id='e' d='M0 45l16 1 15 4 16 4 16 5 15 6 16-1 15-3 16 1 16-2 15 1 16-1 16 3 15 0 16-1 15 2 16 5 16 2 15 3 16-1 16-1 15-3 16-4 15-4 16-2 16-7 15-2 16-5 16-4 15-2 16-6 15-2 16-3 16 0 15 0 16-1 16-1 15 1 16 3 15 3 16 5 16 2 15 5 16 4 16 6 15-1 16 0 15 1 16 4 16 4 15-1 16 1 16-1 15 0 16 1 15 1 16 3 16-1 15-3 16-5 16-6 15-4 16-5 15-5 16-1' vector-effect='non-scaling-stroke'/%3E%3C/defs%3E%3Cpath d='M0 45l16 1 15 4 16 4 16 5 15 6 16-1 15-3 16 1 16-2 15 1 16-1 16 3 15 0 16-1 15 2 16 5 16 2 15 3 16-1 16-1 15-3 16-4 15-4 16-2 16-7 15-2 16-5 16-4 15-2 16-6 15-2 16-3 16 0 15 0 16-1 16-1 15 1 16 3 15 3 16 5 16 2 15 5 16 4 16 6 15-1 16 0 15 1 16 4 16 4 15-1 16 1 16-1 15 0 16 1 15 1 16 3 16-1 15-3 16-5 16-6 15-4 16-5 15-5 16-1V100H0z' fill='%23211c42'/%3E%3Cg fill='none' stroke='%23fbf6ec' vector-effect='non-scaling-stroke'%3E%3Cuse href='%23e' y='-3' stroke-opacity='0.40'/%3E%3Cuse href='%23e' y='-8' stroke-opacity='0.29'/%3E%3Cuse href='%23e' y='-16' stroke-opacity='0.18'/%3E%3C/g%3E%3C/svg%3E");
  --tear-side: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 1000' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cpath id='e' d='M65 0l-2 16 -4 15 3 16 5 16 3 15 -1 16 -1 15 0 16 1 16 -1 15 2 16 -2 16 -1 15 -1 16 -3 15 -1 16 -6 16 -1 15 -2 16 -2 16 0 15 0 16 -2 15 0 16 -1 16 -7 15 -4 16 1 16 0 15 -4 16 -4 15 -4 16 3 16 4 15 2 16 0 16 1 15 6 16 2 15 -1 16 0 16 0 15 1 16 0 16 7 15 4 16 1 15 -1 16 0 16 3 15 1 16 0 16 -3 15 -1 16 0 15 -2 16 1 16 -2 15 0 16 -2 16 3 15 8 16 9 15 4 16' vector-effect='non-scaling-stroke'/%3E%3C/defs%3E%3Cpath d='M65 0l-2 16 -4 15 3 16 5 16 3 15 -1 16 -1 15 0 16 1 16 -1 15 2 16 -2 16 -1 15 -1 16 -3 15 -1 16 -6 16 -1 15 -2 16 -2 16 0 15 0 16 -2 15 0 16 -1 16 -7 15 -4 16 1 16 0 15 -4 16 -4 15 -4 16 3 16 4 15 2 16 0 16 1 15 6 16 2 15 -1 16 0 16 0 15 1 16 0 16 7 15 4 16 1 15 -1 16 0 16 3 15 1 16 0 16 -3 15 -1 16 0 15 -2 16 1 16 -2 15 0 16 -2 16 3 15 8 16 9 15 4 16H0V0z' fill='%231e1a3c'/%3E%3Cg fill='none' stroke='%23fbf6ec'%3E%3Cuse href='%23e' x='3' stroke-opacity='0.40'/%3E%3Cuse href='%23e' x='8' stroke-opacity='0.29'/%3E%3Cuse href='%23e' x='16' stroke-opacity='0.18'/%3E%3C/g%3E%3C/svg%3E");
}
.low { --sans: 'Bricolage Lite', 'Challoop Fallback', 'Avenir Next', 'Helvetica Neue', sans-serif; scroll-behavior: auto; }
.save { --sans: 'Challoop Fallback', 'Avenir Next', 'Helvetica Neue', sans-serif; }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--sand);
  color: var(--ink);
  font: 400 1.125rem/1.55 var(--sans);
  font-optical-sizing: auto;
  overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
/* The splash: a hand-cut stroke with two droplets, echoing the logo's wake. */
.splash { position: relative; display: inline-block; white-space: nowrap; --splash: var(--sea); }
.splash::after {
  content: ""; position: absolute; left: -0.03em; right: -0.1em; bottom: -0.2em; height: 0.3em;
  background: var(--splash); pointer-events: none;
  -webkit-mask: var(--stroke) center / 100% 100% no-repeat;
  mask: var(--stroke) center / 100% 100% no-repeat;
}
.top nav a { position: relative; }
.top nav a::after {
  content: ""; position: absolute; left: 0; right: -0.1em; bottom: -0.05em; height: 0.34em;
  background: var(--sea); opacity: 0; transition: opacity 150ms; pointer-events: none;
  -webkit-mask: var(--stroke) center / 100% 100% no-repeat;
  mask: var(--stroke) center / 100% 100% no-repeat;
}
.top nav a:hover::after, .top nav a:focus-visible::after { opacity: 1; }
:focus-visible { outline: 3px solid currentColor; outline-offset: 3px; border-radius: 3px; }
h1, h2, h3 { margin: 0; font-weight: 700; line-height: 1.04; letter-spacing: -0.025em; text-wrap: balance; }
p { margin: 0; }
.wrap { width: min(100% - 2 * var(--gutter), 70rem); margin-inline: auto; }

/* Layers: the sea, the chart paper with windows torn in it, then the page. The
   still sky is always there, under the live one, and is all that low tiers get. */
#still, #still i, #sea, #front { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; height: 100lvh; display: block; }
#still, #sea, #front { z-index: 0; }
#still { background: radial-gradient(52vmax 22vmax at 72% 25%, rgb(255 248 214 / 0.75), rgb(255 248 214 / 0) 70%), linear-gradient(180deg, #0f7fe8 0%, #1e9cf2 14%, #6fdcf2 26%, #f8f1d2 29.6%, #79e0d3 30%, #16aebb 39%, #0b7dbb 58%, #0a4fa8 100%); }
#still-storm { opacity: 0; visibility: hidden; background: linear-gradient(180deg, #161335 0%, #2a2046 22%, #5e3350 28%, #d07a52 29.7%, #123a44 30.4%, #0d3a48 38%, #0a2238 60%, #050d24 100%); }
#still-warm { opacity: 0; visibility: hidden; background: linear-gradient(180deg, #6f9fe6 0%, #c4bedd 16%, #ffc083 29.6%, #6fcfc4 30%, #16a0b4 40%, #0b78b8 60%, #0a4fa8 100%); }
.still-img #still { background: url(img/still-calm-l.webp) 72% 30% / cover no-repeat, #0b7dbb; }
.still-img.storm-near #still-storm { background: url(img/still-storm-l.webp) 72% 30% / cover no-repeat, #0a2238; }
.still-img.storm-near #still-warm { background: url(img/still-clear-l.webp) 72% 30% / cover no-repeat, #0b78b8; }
@media (orientation: portrait) {
  .still-img #still { background-image: url(img/still-calm-p.webp); }
  .still-img.storm-near #still-storm { background-image: url(img/still-storm-p.webp); }
  .still-img.storm-near #still-warm { background-image: url(img/still-clear-p.webp); }
}
#sea { opacity: 0; transition: opacity 500ms; }
.sea-on #sea { opacity: 1; }
#front { height: 100vh; pointer-events: none; }
#chartwrap { position: absolute; top: 0; left: 0; z-index: 1; width: 100%; height: 0; pointer-events: none; }
.page { position: relative; z-index: 3; }
/* The static paper. Sand under every section, torn edges where the sea shows. */
#build { background: linear-gradient(var(--sand), var(--sand)) 0 var(--hero-tail) no-repeat; }
#oss { background: var(--sand); }
#build::before, .storm::before, .storm::after { content: ""; position: absolute; left: 0; right: 0; pointer-events: none; background: center / 100% 100% no-repeat; }
#build::before { top: 0; height: var(--hero-tail); background-image: var(--tear-hero); }
.storm::before { top: 0; height: var(--tail); background-image: var(--tear-in); }
.storm::after { bottom: 0; height: var(--tail); background-image: var(--tear-out); }
html:not(.js) .storm { background: linear-gradient(180deg, #171433, #0d2b3c 45%, #050d24); }
/* Once the chart has painted it replaces all of that, margins and all on wide
   screens. On narrow ones it only redraws the torn bands. */
.charted #build::before, .charted .storm::before, .charted .storm::after { display: none; }
@media (min-width: 52rem) { .charted #build, .charted #oss { background: none; } }

/* Header: at the top of the page only, ink on the summer sky. */
.top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 6;
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.25rem 1.5rem;
  padding: 1.25rem var(--gutter);
}
/* The white cloud behind the writing: part of the header, so it is in the same
   place at first paint on every tier and every load, and it grows with the header
   when the nav wraps. The sky behind it changes; this never moves. */
.sea-on .top::before { opacity: 0; }
.top::before { content: ""; position: absolute; z-index: -1; left: 0; right: 0; top: 0; bottom: -30%; background: var(--cloud) center / 100% 100% no-repeat; pointer-events: none;; transition: opacity 500ms; }
.wordmark { display: block; }
.wordmark img { display: block; width: clamp(10.5rem, 15vw, 13.5rem); height: auto; }
.top nav { display: flex; flex-wrap: wrap; gap: 0.25rem 1.75rem; }
.top nav a { text-decoration: none; font-weight: 600; font-size: 1.1875rem; padding: 0.25rem 0; }

/* Hero: the sea, white type bottom-left. */
.hero {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr); align-content: end;
  min-height: 100vh; min-height: 100svh;
  /* The headline rises no further than the horizon, clear of the header and clouds.
     Past that, a growing quote box makes the page longer instead. */
  padding: max(31vh, 9rem) var(--gutter) clamp(3.5rem, 10vh, 6rem);
  padding-top: max(31svh, 9rem);
  color: #fff;
}
.hero-text { position: relative; max-width: 84rem; }
.hero h1 { font-size: clamp(3.5rem, 9.4vw, 9rem); font-weight: 760; letter-spacing: -0.035em; line-height: 0.96; text-shadow: 0 2px 40px rgb(10 40 70 / 0.4); }
.hero .lede { text-wrap: balance; margin-top: 1.25rem; font-size: clamp(1.25rem, 1.9vw, 1.75rem); line-height: 1.4; font-weight: 500; text-shadow: 0 1px 18px rgb(10 40 70 / 0.6); }

/* The quote bar: looks like search, works as the main way to reach us. */
.sr, .hp { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.quote { position: relative; max-width: 48rem; margin-top: 2rem; color: var(--ink); }
.quote-row { display: flex; align-items: flex-end; gap: 0.5rem; padding: 0.5rem; background: #fff; border-radius: 1.25rem; box-shadow: 0 14px 40px rgb(8 30 70 / 0.35); }
.quote-row:focus-within { outline: 3px solid var(--butter); outline-offset: 2px; }
.quote textarea { flex: 1; min-width: 0; max-height: 33.33vh; max-height: 33.33svh; overflow: hidden; padding: 0.7rem 0.75rem; border: 0; outline: 0; resize: none; background: none; color: var(--ink); font: 500 clamp(1.0625rem, 1.5vw, 1.25rem)/1.35 var(--sans); }
.quote textarea::placeholder { color: var(--muted); opacity: 1; }
.quote button { flex: none; min-height: 3rem; padding: 0 1.25rem; border: 0; border-radius: 0.85rem; background: var(--butter); color: var(--ink); font: 700 clamp(1rem, 1.4vw, 1.1875rem)/1 var(--sans); cursor: pointer; white-space: nowrap; }
.quote button:hover { background: var(--apricot); }
.quote button[disabled] { opacity: 0.6; cursor: wait; }
.quote button:focus-visible { outline-color: var(--ink); }
.splash24 { position: absolute; z-index: 1; right: -0.4rem; top: -1.7em; color: var(--butter); font-size: clamp(1.125rem, 2vw, 1.625rem); font-weight: 800; letter-spacing: -0.015em; text-shadow: 2px 2px 0 var(--ink); transform: rotate(-5deg); white-space: nowrap; pointer-events: none; }
.quote-more { margin-top: 0.6rem; padding: 0.9rem 1rem; background: #fff; border-radius: 1.25rem; box-shadow: 0 14px 40px rgb(8 30 70 / 0.3); }
.js .quote:not(.open) .quote-more { display: none; }
.quote-more > label { display: block; font-size: 1rem; font-weight: 600; margin-bottom: 0.35rem; }
.quote-more input[type=email] { display: block; width: 100%; min-height: 3rem; padding: 0.6rem 0.75rem; border: 1.5px solid rgb(30 26 60 / 0.25); border-radius: 0.7rem; background: #fff; color: var(--ink); font: 500 1.0625rem var(--sans); }
.quote-more input[type=email]:focus { outline: 3px solid var(--butter); outline-offset: 1px; border-color: var(--ink); }
.quote-note { margin-top: 0.6rem; color: var(--muted); font-size: 0.9375rem; }
.quote-result { margin-top: 0.6rem; padding: 0.8rem 1rem; background: var(--ink); color: var(--sand); border-radius: 1rem; font-weight: 600; font-size: 1.0625rem; line-height: 1.35; }
.quote-result a { text-decoration: underline; }

/* Contact: a button that opens a bubble of icons. Without popover support it
   stays a plain link to the contact card. */
.contact-btn { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0 1.1rem; border-radius: 999px; font-weight: 700; white-space: nowrap; cursor: pointer; }
.top nav .nav-btn { background: var(--ink); color: var(--sand); padding: 0 1.05rem; }
.top nav .nav-btn::after { display: none; }
.top nav { align-items: center; }
.storm-btn { margin-top: 1.5rem; background: var(--butter); color: var(--ink); font-size: clamp(1.0625rem, 1.6vw, 1.25rem); }
.card-btn { margin-top: 1.25rem; background: var(--ink); color: var(--sand); font-size: 1.0625rem; }
#bubble { position: fixed; inset: auto; margin: 0; width: max-content; max-width: calc(100vw - 1.5rem); padding: 0.5rem; border: 0; border-radius: 1.25rem; background: #fff; color: var(--ink); box-shadow: 0 18px 50px rgb(8 12 40 / 0.4); }
#bubble:popover-open { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.15rem; }
#bubble a { display: grid; place-items: center; width: 3rem; height: 3rem; border-radius: 0.85rem; }
#bubble a:hover, #bubble a:focus-visible { background: var(--butter); }
#bubble svg { width: 1.5rem; height: 1.5rem; fill: currentColor; }

/* The project viewer: the live site through a riveted ship window, shaped like the screen. */
.tile-full { position: absolute; z-index: 3; top: 0.6rem; right: 0.6rem; display: grid; place-items: center; width: 2.75rem; height: 2.75rem; border-radius: 0.8rem; background: var(--ink); color: var(--sand); box-shadow: 0 4px 14px rgb(8 12 40 / 0.35); }
.tile-full:hover { background: var(--sea); }
.tile-full svg { width: 1.35rem; height: 1.35rem; }
html.viewing { overflow: hidden; }
#viewer { width: 100vw; height: 100vh; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: clamp(0.6rem, 1.5vw, 1.25rem); border: 0; background: transparent; overflow: hidden; }
#viewer::backdrop { background: rgb(14 12 38 / 0.82); }
/* A heavy brass ship's window: bevelled frame on a dark seat, bolts, corner
   braces, hinges, a latch, a rubber gasket and thick glass. All of it sits on the
   frame, so nothing covers the site inside. */
.ship { --rim: clamp(1.25rem, 2.6vw, 2.25rem); --r: calc(var(--rim) * 1.6); --bolt: radial-gradient(circle closest-side at 47% 41%, #f6e3b2 0 13%, transparent 34%), radial-gradient(circle closest-side at 50% 50%, #c99b58 0 32%, #7d5126 42%, #3a2110 48%, rgb(58 33 16 / 0.35) 56%, transparent 62%); position: relative; width: 100%; height: 100%; padding: var(--rim); border-radius: var(--r); background: linear-gradient(135deg, #f4d68f 0%, #d9a45a 20%, #ecc479 36%, #b57b3d 58%, #dcab62 76%, #8f5a29 100%);
  box-shadow: 0 0 0 2px #2a170a, 0 0 0 calc(var(--rim) * 0.3) #3b2412, 0 0 0 calc(var(--rim) * 0.3 + 2px) #1a0e06, 0 26px 80px rgb(0 0 0 / 0.65), inset 0 2px 1px rgb(255 248 214 / 0.95), inset 2px 0 1px rgb(255 240 200 / 0.55), inset 0 -3px 2px rgb(70 38 12 / 0.85), inset -3px 0 2px rgb(70 38 12 / 0.65), inset 0 0 0 calc(var(--rim) * 0.2) rgb(255 233 178 / 0.14), inset 0 0 0 calc(var(--rim) * 0.2 + 1px) rgb(70 38 12 / 0.38); transform-origin: 0 0; }
/* Bolts along the straight edges, on the frame's centre line. */
.ship::before, .ship::after { content: ""; position: absolute; z-index: 1; pointer-events: none; }
.ship::before { inset: 0 calc(var(--rim) * 2.9); background: var(--bolt) 0 0 / calc(var(--rim) * 2.6) var(--rim) round no-repeat, var(--bolt) 0 100% / calc(var(--rim) * 2.6) var(--rim) round no-repeat; background-size: calc(var(--rim) * 2.6) var(--rim); background-repeat: round no-repeat; }
.ship::after { inset: calc(var(--rim) * 2.9) 0; background: var(--bolt) 0 0, var(--bolt) 100% 0; background-size: var(--rim) calc(var(--rim) * 2.6); background-repeat: no-repeat round; }
.ship iframe { position: relative; display: block; width: 100%; height: 100%; border: 0; border-radius: calc(var(--rim) * 0.8); background: var(--sand) var(--poster, none) top left / cover no-repeat; box-shadow: 0 0 0 calc(var(--rim) * 0.2) #15100c, 0 0 0 calc(var(--rim) * 0.2 + 2px) rgb(255 233 178 / 0.55), 0 0 0 calc(var(--rim) * 0.2 + 3px) rgb(52 28 10 / 0.9); }
/* The glass: only an edge shadow and one soft reflection, so the site stays clear. */
.ship-glass { position: absolute; z-index: 1; inset: var(--rim); border-radius: calc(var(--rim) * 0.8); pointer-events: none; box-shadow: inset 0 0 calc(var(--rim) * 0.7) rgb(10 22 44 / 0.3), inset 0 3px 8px rgb(0 0 0 / 0.34); background: linear-gradient(118deg, rgb(255 255 255 / 0.1) 0%, rgb(255 255 255 / 0.03) 14%, transparent 22%); }
/* Corner braces, drawn once and turned to fit each corner. */
.ship-corner { position: absolute; z-index: 2; width: calc(var(--rim) * 2.6); height: calc(var(--rim) * 2.6); pointer-events: none; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='b' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23f7dd9b'/%3E%3Cstop offset='.5' stop-color='%23c48c4a'/%3E%3Cstop offset='1' stop-color='%23875426'/%3E%3C/linearGradient%3E%3Cg id='s'%3E%3Ccircle r='5.6' fill='%233c2210'/%3E%3Ccircle r='4.7' cy='-.3' fill='%23dcae68'/%3E%3Ccircle r='3.5' cx='-.7' cy='-1' fill='%23f5dfa8'/%3E%3Cpath d='M-4 1.6 4 -1.6' stroke='%232c1808' stroke-width='1.5' stroke-linecap='round'/%3E%3C/g%3E%3C/defs%3E%3Cpath d='M39 1H63V23H30Q24 23 24 29V63H1V39A38 38 0 0 1 39 1Z' fill='url(%23b)' stroke='%233a2110' stroke-width='2'/%3E%3Cpath d='M39 3.5H61M3.5 39A35.500 35.500 0 0 1 39 3.5M3.500 39V61' fill='none' stroke='%23fff4cf' stroke-opacity='.75' stroke-width='1.200'/%3E%3Cuse href='%23s' x='13.500' y='13.500'/%3E%3Cuse href='%23s' transform='translate(50 12) rotate(70)'/%3E%3Cuse href='%23s' transform='translate(12 50) rotate(130)'/%3E%3C/svg%3E") center / 100% 100% no-repeat; filter: drop-shadow(1px 2px 2px rgb(30 16 6 / 0.55)); }
.ship-corner.tl { top: 0; left: 0; }
.ship-corner.tr { top: 0; right: 0; transform: scaleX(-1); }
.ship-corner.bl { bottom: 0; left: 0; transform: scaleY(-1); }
.ship-corner.br { bottom: 0; right: 0; transform: scale(-1); }
/* Hinges on the left, a dog latch on the right. */
.ship-hinge { position: absolute; z-index: 2; left: calc(var(--rim) * -0.24); width: calc(var(--rim) * 1.05); height: calc(var(--rim) * 3); pointer-events: none; border-radius: calc(var(--rim) * 0.28); background: linear-gradient(90deg, rgb(255 246 208 / 0.7), transparent 34%, rgb(50 26 8 / 0.5)), repeating-linear-gradient(0deg, #d9a862 0 30%, #3a2110 30% 33%, #e8c07a 33% 64%, #3a2110 64% 67%, #c7924f 67% 100%); box-shadow: 0 2px 4px rgb(20 10 4 / 0.6), inset 0 0 0 1px rgb(60 32 12 / 0.75); }
.ship-hinge.up { top: 22%; } .ship-hinge.down { bottom: 22%; }
.ship-latch { position: absolute; z-index: 2; right: calc(var(--rim) * -0.3); top: 50%; width: calc(var(--rim) * 1.15); height: calc(var(--rim) * 3.6); transform: translateY(-50%); pointer-events: none; border-radius: calc(var(--rim) * 0.58); background: radial-gradient(circle at 50% 50%, #3b2210 0 12%, #d9ab66 13% 27%, transparent 28%), linear-gradient(90deg, #f6d994, #b47a3c 55%, #754820); box-shadow: 0 3px 6px rgb(20 10 4 / 0.65), inset 1px 1px 0 rgb(255 245 205 / 0.8), inset 0 0 0 1px rgb(60 32 12 / 0.75); }
.ship-controls { position: absolute; z-index: 3; top: calc(var(--rim) * 0.5); left: 50%; transform: translate(-50%, -50%); display: flex; gap: 0.4rem; }
.ship-controls a, .ship-controls button { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; padding: 0; border: 0; border-radius: 0.8rem; background: var(--ink); color: var(--sand); cursor: pointer; }
.ship-controls a:hover, .ship-controls button:hover { background: var(--sea); }
.ship-controls svg { width: 1.35rem; height: 1.35rem; }

/* Sections: clean sand under every word. */
section { position: relative; padding-block: clamp(3.5rem, 8vh, 6rem); }
#build { padding-top: calc(var(--hero-tail) + 3rem); scroll-margin-top: calc(-1 * var(--hero-tail)); }
h2 { font-size: clamp(2.25rem, 4.4vw, 4rem); }
.lede { margin-top: 1.25rem; max-width: 30em; font-size: 1.125rem; }
.work-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0.75rem 3rem; margin-bottom: 2rem; }
.kinds { font-size: clamp(1.125rem, 1.7vw, 1.5rem); font-weight: 600; letter-spacing: -0.01em; color: var(--muted); }
.why { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem clamp(1rem, 3vw, 2.5rem); margin: 0 0 2.5rem; padding: 0; list-style: none; font-size: clamp(1.125rem, 1.7vw, 1.4375rem); font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; text-wrap: balance; }
/* The patchwork. A tile with data-live shows a poster of that site. */
.patch { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-rows: clamp(9rem, 14vw, 12.5rem); gap: 0.75rem; }
.tile { position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-end; padding: 1rem 1.25rem; border-radius: 1rem; color: var(--ink); grid-column: span 4; }
.tile.wide { grid-column: span 7; grid-row: span 2; }
.tile.mid { grid-column: span 5; }
.tile.kipem { grid-row: span 2; }
.tile strong { position: relative; font-size: clamp(1.375rem, 2.5vw, 2.25rem); font-weight: 700; letter-spacing: -0.025em; line-height: 1.05; }
.tile.wide strong { font-size: clamp(2.5rem, 6vw, 5.5rem); letter-spacing: -0.035em; }
.tile span { position: relative; margin-top: 0.3rem; font-size: 1rem; font-weight: 500; }
.tile.kipem { background: radial-gradient(60% 80% at 100% 0%, rgb(191 226 255 / 0.9), rgb(191 226 255 / 0) 70%), linear-gradient(135deg, #fff2cc, var(--butter) 50%, var(--apricot)); }
.tile.rescue { background: linear-gradient(135deg, var(--rose), #ffd3c2); }
.tile.open { background: rgb(30 26 60 / 0.04); border: 1.5px dashed rgb(30 26 60 / 0.25); color: var(--muted); }
.tile.open strong { font-size: 1.125rem; font-weight: 500; letter-spacing: 0; }
.tile[data-live] { background: var(--ink); color: var(--sand); }
.tile[data-live] strong { font-size: clamp(1.5rem, 2.8vw, 2.5rem); letter-spacing: -0.025em; z-index: 1; }
.tile[data-live] span { z-index: 1; }
.tile.live::after { content: ""; position: absolute; inset: auto 0 0; height: 45%; background: linear-gradient(rgb(30 26 60 / 0), rgb(30 26 60 / 0.94) 60%); pointer-events: none; }
.tile-link { color: inherit; }
.tile-link::before { content: ""; position: absolute; inset: 0; z-index: 2; }
.tile-link:focus-visible { outline: none; }
.tile-link:focus-visible::before { outline: 3px solid var(--sea); outline-offset: -3px; border-radius: 1rem; }
.nobr { white-space: nowrap; }
.poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 0 0; }

/* Storm: a tall run with a pinned stage. Scroll position is the weather.
   The words ride on a dark front, a torn sheet of the same ink as the type:
   static here, redrawn by chart.js on capable devices. */
.storm { padding: 0; height: calc(var(--run) * 1vh); }
.stage { position: sticky; top: 0; z-index: 1; height: 100vh; height: 100svh; overflow-x: clip; }
.mass { position: relative; height: 100%; display: grid; align-items: center; }
.mass::before { content: ""; position: absolute; top: 0; bottom: 0; left: 0; --band: max(170px, 26vw); width: var(--front-w, min(100%, calc(max(var(--gutter), (100vw - 70rem) / 2) + min(44rem, 100vw - 2 * var(--gutter)) + 36px + var(--band)))); background: var(--tear-side) right / var(--band) 100% no-repeat, linear-gradient(90deg, #2b2450, #1e1a3c) left / calc(100% - var(--band) + 1px) 100% no-repeat; }
.inked .mass::before, .inked .words::before { display: none; }
#ink { position: absolute; left: 0; top: 0; pointer-events: none; }
.words { position: relative; isolation: isolate; width: fit-content; max-width: 44rem; color: var(--sand); }
.words h2 { font-size: clamp(3.25rem, 6.6vw, 6rem); letter-spacing: -0.035em; line-height: 1; }
.words h2 span { display: block; }
.words h2 .splash { display: inline-block; --splash: var(--butter); font-size: clamp(2rem, 4vw, 3.6rem); margin-top: 0.15em; letter-spacing: -0.03em; }
.calls { margin: 2.25rem 0 0; color: var(--butter); font-size: clamp(1.25rem, 2.1vw, 1.875rem); font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; text-wrap: balance; }
/* A viewport too short for the words: no pin, they just scroll. */
.nopin .storm { display: grid; align-items: center; }
.nopin .stage { position: relative; height: auto; }
.nopin .mass { padding-block: 2.5rem; }

/* Open source and apps, side by side. */
.two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 3rem clamp(2rem, 6vw, 6rem); }
.slots { margin: 1.5rem 0 0; padding: 0; list-style: none; }
.slot { padding: 0.8rem 0; border-top: 1.5px solid rgb(30 26 60 / 0.15); color: var(--muted); }
.slot:last-child { border-bottom: 1.5px solid rgb(30 26 60 / 0.15); }
.product { margin-top: 1.5rem; }
.product h3 { font-size: 1.75rem; margin-bottom: 0.4rem; }
.status { margin-top: 0.5rem; color: var(--muted); font-size: 1rem; }

/* Harbour: contact on the warm evening colours, which rise out of the paper
   above with no edge and run to the end of the page. */
.harbour {
  padding-top: clamp(7rem, 16vw, 13rem);
  background: linear-gradient(180deg, var(--sand) 0%, rgb(251 246 236 / 0) 52%), radial-gradient(55% 75% at 100% 45%, rgb(191 226 255 / 0.9) 0%, rgb(191 226 255 / 0) 70%), radial-gradient(50% 70% at 0% 100%, rgb(255 177 203 / 0.8) 0%, rgb(255 177 203 / 0) 70%), linear-gradient(135deg, #fff2cc 0%, var(--butter) 50%, var(--apricot) 100%);
}
.harbour .wrap { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: 2rem clamp(2rem, 6vw, 5rem); }
.reach { margin-top: 1.5rem; display: grid; gap: 0.7rem; justify-items: start; font-size: clamp(1.375rem, 2.8vw, 2.5rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; }
.reach a { overflow-wrap: anywhere; }
.about { align-self: end; display: grid; gap: 0.75rem; font-size: 1rem; line-height: 1.45; }
.links { display: flex; gap: 1.5rem; }

@media (max-width: 52rem) {
  .two, .harbour .wrap { grid-template-columns: minmax(0, 1fr); }
  .why { grid-template-columns: minmax(0, 1fr); gap: 0.6rem; }
  .quote { margin-top: 2.5rem; }
  .quote-row { flex-direction: column; align-items: stretch; }
  /* In a column, flex: 1 would override the height the box grows to. */
  .quote textarea { flex: none; }
  .quote button { min-height: 3.25rem; }
  .splash24 { right: 0; }
  .patch { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 9.5rem; }
  .tile, .tile.mid { grid-column: span 1; }
  .tile.wide { grid-column: span 2; grid-row: span 2; }
  .tile.kipem { grid-column: span 2; grid-row: auto; }
  .tile.open:last-child { grid-column: span 2; }
  .work-head h2 { line-height: 1.24; }
  .top::before { background-image: var(--cloud-narrow); }
  .top nav { gap: 0.25rem 0.9rem; }
  .top nav a { font-size: 1.0625rem; }
  .mass { align-items: end; }
  .mass::before { display: none; }
  .words { padding-bottom: 1.5rem; }
  .words::before { content: ""; position: absolute; z-index: -1; top: -130px; bottom: 0; left: calc(-1 * var(--gutter)); width: 100vw; background: var(--tear-front) top / 100% 110px no-repeat, linear-gradient(180deg, #211c42, #171430) 0 109px / 100% calc(100% - 109px) no-repeat; }
  .words h2 .splash { font-size: min(7vw, 2.1rem); }
  /* The static torn edges, not squeezed into a narrow screen. */
  #build::before, .storm::before, .storm::after, .words::before { background-size: 280% 100%; }
  .words::before { background-size: 280% 110px, 100% calc(100% - 109px); }
  .nopin .mass { padding-block: 0; }
  body { font-size: 1.0625rem; }
}

@media (prefers-reduced-motion: no-preference) {
  .mid .splash24, .high .splash24 { animation: splash24 620ms ease-in-out infinite alternate; }
  @keyframes splash24 { from { transform: rotate(-5deg) scale(1); } to { transform: rotate(-5deg) scale(1.07); } }
  .mid .hero-text > *, .high .hero-text > * { animation: rise 1100ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
  .hero .lede { animation-delay: 200ms; }
  @keyframes rise { from { opacity: 0; transform: translateY(0.75rem); } to { opacity: 1; transform: none; } }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } #sea { transition: none; } }
