/* Solecraft: two colours and Fira in many weights. The layout is of today.
   A few details come from where the S in the logo comes from: boxes whose
   corners step by a pixel, a small hard shadow, labels in a mono, and a
   trail of pixels after the pointer in the hero. They are kept small. The
   buttons are round. */
:root {
  --blue: #0265be;
  --night: #010427;
  --sky: #5aa9ff;      /* the blue lightened, for text on night */
  --ice: #eef3fa;
  --ink: #010427;
  --muted: #5b6480;
  --pad: clamp(1.25rem, 5vw, 4rem);
  --max: 76rem;
  /* The side padding that keeps a full-width block's content inside --max. */
  --gutter: max(var(--pad), calc(50% - var(--max) / 2));
  /* One pixel of the page: frames, steps in the corners and shadows are multiples of it. */
  --px: 2px;
  /* One pixel of the pointer's trail in the hero. main.js reads it. */
  --cell: 8px;
  --mono: 'Fira Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  color-scheme: dark light;
}
@media (max-width: 40rem) { :root { --cell: 6px; } }

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-weight: 300;
  line-height: 1.5;
  background: var(--night);
  color: #fff;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--sky); outline-offset: 3px; }

.skip { position: absolute; left: -999px; top: 0; padding: .75rem 1rem; background: #fff; color: var(--night); z-index: 20; }
.skip:focus { left: 1rem; top: 1rem; }

/* A pixel frame, for the boxes. Four shadows make a thin border with its
   corners missing, which is a rounded corner at one pixel's radius. A fifth
   is the hard shadow the box stands on, where --drop and --lift ask for one. */
.service, .window, .step-n, .case-index a, .cookie-ask {
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--edge), 0 var(--px) 0 0 var(--edge),
    calc(var(--px) * -1) 0 0 0 var(--edge), var(--px) 0 0 0 var(--edge),
    var(--lift, 0px) var(--lift, 0px) 0 var(--px) var(--drop, transparent);
}

/* Header: over the hero, and over everything once you scroll. */
.top {
  position: fixed; inset: 0 0 auto 0; z-index: 10;
  display: flex; justify-content: space-between; align-items: center;
  padding: 1rem var(--gutter);
  transition: background .3s, box-shadow .3s;
}
.top.scrolled {
  background: rgb(1 4 39 / .9); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 0 rgb(255 255 255 / .08);
}
.brand img { width: clamp(118px, 14vw, 150px); }
.top nav { display: flex; gap: clamp(1.25rem, 2.5vw, 2.25rem); align-items: center; font-size: .95rem; font-weight: 500; letter-spacing: .02em; }
.top nav a { text-decoration: none; opacity: .85; transition: opacity .15s; }
.top nav a:hover, .top nav a[aria-current] { opacity: 1; }
.top .nav-cta { padding: .42rem 1.1rem; border: 1px solid rgb(255 255 255 / .45); border-radius: 999px; opacity: 1; transition: background .15s, color .15s, border-color .15s; }
.top .nav-cta:hover { background: #fff; color: var(--night); border-color: #fff; }
/* On a phone the logo and four links do not fit. The services and the process are a scroll away; the cases are another page, so that link stays. */
@media (max-width: 34rem) { .top nav a:not(.nav-cta):not(.nav-case) { display: none; } }

/* Hero: a field of soft light in the two colours, drawn by main.js. The pixels are where the pointer has been. */
.hero {
  position: relative; min-height: 100svh; overflow: hidden;
  display: flex; align-items: center;
  padding: 7rem var(--gutter) 6rem;
  isolation: isolate;
  /* What shows before the canvas draws, and without JavaScript. */
  background:
    radial-gradient(60% 70% at 80% 30%, rgb(2 101 190 / .75), transparent 70%),
    radial-gradient(50% 60% at 15% 85%, rgb(2 101 190 / .45), transparent 70%),
    var(--night);
}
/* main.js gives each canvas one pixel a cell and sizes it to whole cells.
   The browser smooths the field as it scales it up; the pointer's pixels,
   on a second canvas that main.js adds, are left sharp. */
.field { position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: -2; }
.field.pixels { image-rendering: pixelated; }
.hero-inner { width: 100%; }
h1 {
  margin: 0;
  font-size: clamp(2.6rem, 8.2vw, 7.2rem);
  font-weight: 900; line-height: 1.04; letter-spacing: -.015em;
  text-wrap: balance;
}
.flow {
  font-style: italic; font-weight: 300; letter-spacing: -.02em;
  background: linear-gradient(100deg, #9fd0ff 0%, var(--sky) 25%, #fff 50%, var(--sky) 75%, #9fd0ff 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: flow 7s linear infinite;
  padding-right: .06em;
}
@keyframes flow { to { background-position: -200% 0; } }
.lead { margin: 1.75rem 0 0; max-width: 34rem; text-wrap: balance; font-size: clamp(1.1rem, 2vw, 1.45rem); font-weight: 300; line-height: 1.4; color: rgb(255 255 255 / .9); }
.actions { margin: 2.5rem 0 0; display: flex; gap: 1.75rem; align-items: center; flex-wrap: wrap; }
/* The buttons are round, and lift a little under the pointer. */
.button {
  display: inline-block; padding: .9rem 1.7rem; border-radius: 999px;
  background: #fff; color: var(--night);
  font-family: var(--mono); font-size: .85rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; text-decoration: none;
  box-shadow: 0 10px 28px -12px rgb(2 101 190 / .9);
  transition: transform .15s, box-shadow .15s;
}
.button:hover { transform: translateY(-2px); box-shadow: 0 16px 34px -12px rgb(2 101 190 / 1); }
.button:active { transform: translateY(0); }
.link { text-decoration: none; font-weight: 500; border-bottom: 1px solid rgb(255 255 255 / .4); padding-bottom: .15rem; }
.link:hover { border-color: #fff; }
.link.dark { border-color: rgb(1 4 39 / .4); }
.link.dark:hover { border-color: var(--ink); }
/* An arrow of seven pixels, stepping down and up. */
.scroll-hint { --px: 3px; position: absolute; left: 50%; bottom: 2rem; width: calc(var(--px) * 15); height: calc(var(--px) * 12); margin-left: calc(var(--px) * -7.5); opacity: .8; }
.scroll-hint span {
  position: absolute; left: calc(var(--px) * 7); top: calc(var(--px) * 7); width: var(--px); height: var(--px);
  background: #fff;
  box-shadow:
    calc(var(--px) * -1) calc(var(--px) * -1) 0 #fff, var(--px) calc(var(--px) * -1) 0 #fff,
    calc(var(--px) * -2) calc(var(--px) * -2) 0 #fff, calc(var(--px) * 2) calc(var(--px) * -2) 0 #fff,
    calc(var(--px) * -3) calc(var(--px) * -3) 0 #fff, calc(var(--px) * 3) calc(var(--px) * -3) 0 #fff;
  animation: hint 1s steps(1) infinite;
}
@keyframes hint { 50% { transform: translateY(var(--px)); } }

/* Services: light, with the count running as you scroll. */
.services {
  background: var(--ice); color: var(--ink);
  padding: clamp(5rem, 12vw, 9rem) var(--gutter);
  display: grid; gap: 3rem;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 60rem) {
  .services { grid-template-columns: minmax(14rem, 1fr) minmax(0, 2.4fr); gap: 4rem; }
  .services-head { position: sticky; top: 7rem; align-self: start; }
}
h2 { margin: 0; font-size: clamp(2.2rem, 5vw, 3.6rem); font-weight: 800; letter-spacing: -.015em; line-height: 1.05; text-wrap: balance; }
.counter { margin: 1.75rem 0 .9rem; font-family: var(--mono); font-size: 1rem; font-weight: 500; letter-spacing: .08em; color: var(--muted); }
.counter .current { font-size: 2.2rem; font-weight: 700; letter-spacing: 0; line-height: 1; color: var(--blue); }
/* The bar is four blocks. */
.progress {
  height: 6px; width: 100%; max-width: 12rem; background: rgb(1 4 39 / .12);
  -webkit-mask: repeating-linear-gradient(90deg, #000 0 calc(25% - 3px), transparent 0 25%);
  mask: repeating-linear-gradient(90deg, #000 0 calc(25% - 3px), transparent 0 25%);
}
.progress span { display: block; height: 100%; width: 25%; background: var(--blue); transition: width .4s cubic-bezier(.2,.7,.2,1); }

.service-list { list-style: none; margin: 0; padding: var(--px); display: grid; gap: 1.25rem; }
.service {
  position: relative; overflow: hidden;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  background: #fff;
  --edge: rgb(1 4 39 / .16);
  --mx: 50%; --my: 50%;
  transition: transform .15s, box-shadow .15s, color .25s;
}
/* The spotlight: a gradient from the blue to the night that follows the pointer. */
.service::before {
  content: ''; position: absolute; inset: 0; z-index: 0; opacity: 0;
  background:
    radial-gradient(420px circle at var(--mx) var(--my), rgb(90 169 255 / .55), transparent 60%),
    linear-gradient(135deg, var(--blue), var(--night));
  transition: opacity .25s;
}
.service > * { position: relative; z-index: 1; }
.num { font-family: var(--mono); font-size: .8rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--blue); transition: color .25s; }
.service h3 { margin: .9rem 0 .6rem; font-size: clamp(1.9rem, 4.5vw, 3.2rem); font-weight: 800; letter-spacing: -.015em; line-height: 1.05; }
.service p { margin: 0; max-width: 36rem; font-size: clamp(1.02rem, 1.6vw, 1.2rem); font-weight: 300; color: var(--muted); transition: color .25s; }
/* The card under the pointer lifts onto a small hard shadow and lights up. */
.service:hover {
  transform: translate(calc(var(--px) * -1), calc(var(--px) * -1));
  --edge: var(--ink); --drop: var(--blue); --lift: calc(var(--px) * 2);
  color: #fff;
}
.service:hover::before { opacity: 1; }
.service:hover .num { color: #bfe0ff; }
.service:hover p { color: rgb(255 255 255 / .85); }
@media (hover: none) {
  /* On a phone there is no pointer to choose with, and one card fills most of
     the screen: the card in the middle is the one that lifts and lights up.
     With a pointer only the count and the bar follow the scroll, so that no
     card looks chosen when nobody chose it. */
  .service.active {
    transform: translate(calc(var(--px) * -1), calc(var(--px) * -1));
    --edge: var(--ink); --drop: var(--blue); --lift: calc(var(--px) * 2);
    color: #fff;
  }
  .service.active::before { opacity: 1; }
  .service.active .num { color: #bfe0ff; }
  .service.active p { color: rgb(255 255 255 / .85); }
}

/* Process: four steps on a dashed line, coming on as they scroll into view. */
.process { background: var(--night); padding: clamp(5rem, 12vw, 9rem) var(--gutter); }
.process h2 { max-width: 16ch; }
.steps { list-style: none; margin: clamp(2.75rem, 6vw, 4.5rem) 0 0; padding: var(--px); display: grid; gap: 2.75rem; }
.step { position: relative; display: grid; grid-template-columns: 3rem minmax(0, 1fr); column-gap: 1.5rem; }
.step-n {
  grid-row: 1 / span 2;
  display: grid; place-items: center; width: 3rem; height: 3rem;
  font-family: var(--mono); font-size: .95rem; font-weight: 700;
  background: var(--blue); color: #fff;
  --edge: var(--blue);
}
.step h3 { margin: .15rem 0 .5rem; font-size: 1.5rem; font-weight: 800; letter-spacing: -.01em; line-height: 1.1; }
.step p { margin: 0; max-width: 32rem; font-weight: 300; color: rgb(255 255 255 / .82); }
/* The line to the next step: down the side on a phone, across on a wide screen. */
.step:not(:last-child)::before {
  content: ''; position: absolute; width: var(--px);
  left: calc(1.5rem - var(--px) / 2); top: calc(3rem + 10px); bottom: calc(-2.75rem + 8px);
  background: repeating-linear-gradient(to bottom, rgb(2 101 190 / .8) 0 4px, transparent 0 8px);
}
@media (min-width: 60rem) {
  .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2.5rem; }
  .step { display: block; }
  .step-n { margin-bottom: 1.75rem; }
  .step:not(:last-child)::before {
    width: auto; height: var(--px); bottom: auto;
    left: calc(3rem + 10px); right: calc(-2.5rem + 8px); top: calc(1.5rem - var(--px) / 2);
    background: repeating-linear-gradient(to right, rgb(2 101 190 / .8) 0 4px, transparent 0 8px);
  }
}
/* From the steps to the page with what has been built. */
.more { margin: clamp(2.75rem, 6vw, 4rem) 0 0; }
/* A button that is only an outline, for the second thing to do. */
.button.ghost { background: none; color: #fff; border: 1px solid rgb(255 255 255 / .5); box-shadow: none; transition: background .15s, color .15s, border-color .15s; }
.button.ghost:hover { transform: none; background: #fff; color: var(--night); border-color: #fff; box-shadow: none; }

/* main.js puts .js on <html>. Then a step waits dimmed until it has been seen;
   without JavaScript all four are lit. */
.step-n, .step h3, .step p, .step::before { transition: opacity .35s, background .2s, color .2s, box-shadow .2s; }
.step:nth-child(2) > *, .step:nth-child(2)::before { transition-delay: .12s; }
.step:nth-child(3) > *, .step:nth-child(3)::before { transition-delay: .24s; }
.step:nth-child(4) > *, .step:nth-child(4)::before { transition-delay: .36s; }
.js .step:not(.on) .step-n { background: transparent; color: var(--sky); --edge: rgb(90 169 255 / .45); }
.js .step:not(.on) h3, .js .step:not(.on) p { opacity: .4; }
.js .step:not(.on)::before { opacity: .3; }

/* The top of a page that is not the front page: the night, a label, a heading. */
.page-head {
  position: relative; overflow: hidden; isolation: isolate;
  padding: clamp(8rem, 16vw, 11rem) var(--gutter) clamp(3rem, 7vw, 5rem);
  background: radial-gradient(70% 120% at 85% 0%, rgb(2 101 190 / .55), transparent 70%), var(--night);
}
.page-head h1 { font-size: clamp(2.5rem, 6.5vw, 5rem); }
/* Alone on its page, the head fills the screen above the footer. */
.lead.small { margin-top: 1rem; font-size: 1rem; color: rgb(255 255 255 / .7); }
.lead a { text-underline-offset: .2em; }
.page-head.lost { min-height: 72svh; display: flex; flex-direction: column; justify-content: center; padding-bottom: clamp(5rem, 12vw, 8rem); }

/* Case, on a page of its own: an index that chooses the case, and the case
   itself with its pictures in a window and what was hard about it in three lines. */
.cases { background: var(--ice); color: var(--ink); padding: clamp(3rem, 7vw, 5rem) var(--gutter) clamp(5rem, 12vw, 9rem); }
.case-index { display: grid; gap: .9rem; padding: var(--px); margin-bottom: clamp(3rem, 7vw, 5rem); }
@media (min-width: 48rem) { .case-index { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; } }
.case-index a {
  position: relative; overflow: hidden; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: .45rem 1rem; padding: 1.1rem 1.25rem 1.2rem;
  background: #fff; text-decoration: none;
  --edge: rgb(1 4 39 / .16);
  transition: transform .15s, box-shadow .15s, color .2s;
}
.case-index a::before { content: ''; position: absolute; inset: 0; opacity: 0; background: linear-gradient(135deg, var(--blue), var(--night)); transition: opacity .2s; }
.case-index a > * { position: relative; }
.case-index .num, .case-index strong { grid-column: 1; }
.case-index strong { font-size: clamp(1.15rem, 2vw, 1.45rem); font-weight: 800; letter-spacing: -.01em; line-height: 1.15; }
/* A small picture of the case, which leans when the card is pointed at. */
.case-index img { grid-column: 2; grid-row: 1 / span 2; width: 5.5rem; box-shadow: 0 0 0 var(--px) rgb(1 4 39 / .18); transition: transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .2s; }
.case-index a:hover img { transform: rotate(-4deg) scale(1.08); }
.case-index a[aria-current] img { transform: rotate(3deg); box-shadow: 0 0 0 var(--px) rgb(255 255 255 / .55); }
@media (min-width: 48rem) and (max-width: 68rem) { .case-index img { display: none; } }
.case-index a:hover { transform: translate(calc(var(--px) * -1), calc(var(--px) * -1)); --edge: var(--ink); --drop: var(--blue); --lift: calc(var(--px) * 2); }
/* The chosen case's card is lit, as the service under the pointer is. */
.case-index a[aria-current] { color: #fff; --edge: var(--ink); --drop: var(--blue); --lift: calc(var(--px) * 2); }
.case-index a[aria-current]::before { opacity: 1; }
.case-index a[aria-current] .num { color: #bfe0ff; }

.case-list { display: grid; gap: clamp(4.5rem, 9vw, 7rem); padding: var(--px); }
.case { display: grid; gap: 2.75rem; align-items: center; scroll-margin-top: 6rem; }
@media (min-width: 60rem) { .case { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 4.5rem; } }
/* main.js puts .tabbed on the list and .on on the chosen case. The case
   comes in from the side its card is on: .back when it lies before the last one. */
.tabbed .case:not(.on) { display: none; }
.tabbed .case.on { animation: case-in .45s cubic-bezier(.2,.7,.2,1); }
.tabbed .case.back { --from: -36px; }
@keyframes case-in { from { opacity: 0; transform: translateX(var(--from, 36px)); } }

.window {
  position: relative; display: block; background: #fff; text-decoration: none;
  --edge: var(--ink); --drop: var(--blue); --lift: calc(var(--px) * 2);
  transition: transform .15s, box-shadow .15s;
}
.window-bar {
  display: flex; align-items: center; gap: 6px;
  padding: .45rem .6rem .45rem .75rem; min-height: 2.4rem;
  background: var(--ink); color: #fff;
  font-family: var(--mono); font-size: .72rem; font-weight: 500; letter-spacing: .05em;
}
.window-bar i { flex: none; width: 6px; height: 6px; background: var(--sky); }
.window-bar i:last-of-type { margin-right: auto; }
.window-bar b { font-weight: 500; opacity: .85; }
a.window:hover { transform: translate(calc(var(--px) * -1), calc(var(--px) * -1)); --lift: calc(var(--px) * 3); }
/* The pictures of a case: a radio button each, its label a tab in the bar.
   The window leans towards the pointer; main.js sets --rx, --ry and where
   the light falls. */
.shots {
  --rx: 0deg; --ry: 0deg;
  transform: perspective(1100px) rotateX(var(--rx)) rotateY(var(--ry));
  transition: transform .35s cubic-bezier(.2,.7,.2,1), box-shadow .15s;
}
.shots.leaning { transition: transform .08s linear, box-shadow .15s; }
.shots input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.shots label { padding: .3rem .6rem; cursor: pointer; white-space: nowrap; opacity: .7; transition: opacity .15s, background .15s; }
.shots label:hover { opacity: 1; }
.frames { position: relative; display: grid; cursor: zoom-in; touch-action: pan-y; -webkit-user-select: none; user-select: none; }
.frames img { grid-area: 1 / 1; width: 100%; opacity: 0; transition: opacity .3s; pointer-events: none; }
.frames::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .25s;
  background: radial-gradient(45% 55% at var(--gx, 50%) var(--gy, 50%), rgb(255 255 255 / .16), transparent 70%);
}
.shots.leaning .frames::after { opacity: 1; }
/* The arrows at the sides of the picture, added by main.js: round, as the buttons are. */
.shot-nav {
  position: absolute; top: 50%; z-index: 1; width: 2.5rem; height: 2.5rem; margin-top: -1.25rem; padding: 0;
  display: grid; place-items: center;
  border: 1px solid rgb(255 255 255 / .5); border-radius: 50%;
  background: rgb(1 4 39 / .78); color: #fff;
  font: 500 1.05rem/1 var(--mono); cursor: pointer;
  transition: background .15s, color .15s, border-color .15s, transform .15s;
}
.shot-nav.before { left: .6rem; }
.shot-nav.after { right: .6rem; }
/* Only where there is a pointer to hover with: on a phone the arrow last tapped would stay lit. */
@media (hover: hover) {
  .shot-nav:hover { background: #fff; color: var(--night); border-color: #fff; }
  .shot-nav.before:hover { transform: translateX(-2px); }
  .shot-nav.after:hover { transform: translateX(2px); }
}
.shot-nav:active { background: #fff; color: var(--night); border-color: #fff; }
/* The pixels that cover one picture while the next comes in. Drawn by main.js, a pixel a cell. */
.wipe { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; pointer-events: none; }
/* The window's foot: what the picture shows, and which one it is. Written by main.js. */
.case .shot-foot {
  display: flex; justify-content: space-between; gap: 1rem; margin: 0; padding: .5rem .75rem;
  background: var(--ink); color: rgb(255 255 255 / .8);
  font-family: var(--mono); font-size: .7rem; letter-spacing: .03em; line-height: 1.4;
}
.case .shot-foot span:last-child { flex: none; color: var(--sky); }
.zoom-open { flex: none; margin-left: .15rem; padding: .3rem .45rem; border: 0; background: none; color: #fff; font: inherit; line-height: 1; opacity: .7; cursor: zoom-in; transition: opacity .15s; }
.zoom-open:hover { opacity: 1; }
/* The picture large, over the page. On a wide screen it is as large as it is
   or as the screen allows. */
.zoom { width: min(94vw, 1240px); max-width: none; max-height: none; padding: 0; border: 0; background: none; color: #fff; overflow: visible; }
.zoom::backdrop { background: rgb(1 4 39 / .94); }
.zoom-stage { text-align: center; }
.zoom-pic { position: relative; display: inline-block; vertical-align: top; }
.zoom-pic img { display: block; width: auto; height: auto; max-width: 100%; max-height: 76vh; cursor: pointer; }
.zoom-bar, .zoom-nav { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin: 0; padding: .8rem 0; font-family: var(--mono); font-size: .8rem; letter-spacing: .03em; }
.zoom-nav span { color: var(--sky); }
.zoom button { padding: .5rem 1rem; border: 1px solid rgb(255 255 255 / .45); border-radius: 999px; background: none; color: #fff; font: inherit; cursor: pointer; transition: background .15s, color .15s; }
.zoom button:hover { background: #fff; color: var(--night); }
.zoom-hint { display: none; }
@media (max-width: 48rem) {
  /* On a phone the dialog is the whole screen, and the picture is taller
     than it is wide there: it is dragged sideways, and can be read. */
  .zoom[open] { display: flex; flex-direction: column; width: 100vw; height: 100dvh; margin: 0; padding: 0 1rem; background: rgb(1 4 39 / .96); }
  .zoom-stage { flex: 1; display: flex; align-items: center; margin: 0 -1rem; overflow-x: auto; overflow-y: hidden; text-align: left; overscroll-behavior: contain; }
  .zoom-pic { flex: none; margin: 0 1rem; }
  .zoom-pic img { max-width: none; max-height: none; height: min(58dvh, 30rem); }
  .zoom-hint { display: block; margin: 0; padding-top: .6rem; text-align: center; font-size: .8rem; color: rgb(255 255 255 / .6); }
  .zoom-bar span { font-size: .72rem; }
}
.shots input:nth-of-type(1):checked ~ .frames img:nth-child(1),
.shots input:nth-of-type(2):checked ~ .frames img:nth-child(2),
.shots input:nth-of-type(3):checked ~ .frames img:nth-child(3),
.shots input:nth-of-type(4):checked ~ .frames img:nth-child(4) { opacity: 1; }
.shots input:nth-of-type(1):checked ~ .window-bar label:nth-of-type(1),
.shots input:nth-of-type(2):checked ~ .window-bar label:nth-of-type(2),
.shots input:nth-of-type(3):checked ~ .window-bar label:nth-of-type(3),
.shots input:nth-of-type(4):checked ~ .window-bar label:nth-of-type(4) { background: var(--blue); opacity: 1; }
.shots input:nth-of-type(1):focus-visible ~ .window-bar label:nth-of-type(1),
.shots input:nth-of-type(2):focus-visible ~ .window-bar label:nth-of-type(2),
.shots input:nth-of-type(3):focus-visible ~ .window-bar label:nth-of-type(3),
.shots input:nth-of-type(4):focus-visible ~ .window-bar label:nth-of-type(4) { outline: 2px solid var(--sky); outline-offset: 2px; }
@media (max-width: 34rem) {
  /* On a phone the tabs get the whole bar. */
  .window-bar i, .zoom-open { display: none; }
  .window-bar { padding: .4rem; justify-content: space-between; }
  .shots label { padding: .35rem .45rem; }
}

.case h2 { margin: .9rem 0 .6rem; font-size: clamp(1.9rem, 4.5vw, 3.2rem); }
.case p { margin: 0; font-size: clamp(1.02rem, 1.6vw, 1.2rem); color: var(--muted); }
.points { list-style: none; margin: 1.5rem 0 2rem; padding: 0; display: grid; gap: .7rem; }
.points li { position: relative; padding-left: 1.25rem; color: var(--muted); line-height: 1.45; }
.points li::before { content: ''; position: absolute; left: 0; top: .55em; width: 6px; height: 6px; background: var(--blue); }
.points strong { font-weight: 500; color: var(--ink); }
.case .case-links { display: flex; flex-wrap: wrap; gap: .9rem 2rem; font-size: 1rem; color: var(--ink); }
.next::after { content: ' →'; }

/* A page about one service: what you get, and an example. Kept short. */
.page-head .actions { margin-top: 2rem; }
.card-link { display: inline-block; margin-top: 1.1rem; font-weight: 500; text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: .1rem; }
.card-link::after { content: ' →'; }
.features { background: var(--ice); color: var(--ink); padding: clamp(4rem, 9vw, 7rem) var(--gutter); }
.feature-list { list-style: none; margin: clamp(2.25rem, 5vw, 3.5rem) 0 0; padding: var(--px); display: grid; gap: 1.25rem; }
@media (min-width: 48rem) { .feature-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.feature-list .service h3 { font-size: clamp(1.4rem, 2.4vw, 1.9rem); }
.cases h2 + .case { margin-top: clamp(2.25rem, 5vw, 3.5rem); }
/* Two light sections in a row share the space between them. */
.features + .cases { padding-top: 0; }
.case h3 { margin: .9rem 0 .6rem; font-size: clamp(1.9rem, 4.5vw, 3.2rem); font-weight: 800; letter-spacing: -.015em; line-height: 1.05; }
.case.example p + .case-links { margin-top: 1.75rem; }

/* Contact: the gradient again, slowly turning. */
.contact {
  position: relative; overflow: hidden; isolation: isolate;
  padding: clamp(5rem, 14vw, 10rem) var(--gutter);
  background: linear-gradient(120deg, var(--night) 0%, var(--blue) 45%, var(--night) 90%);
  background-size: 220% 220%;
  animation: drift 16s ease-in-out infinite alternate;
}
@keyframes drift { from { background-position: 0% 30%; } to { background-position: 100% 70%; } }
.contact h2 { font-size: clamp(2.3rem, 6.5vw, 5.4rem); font-weight: 900; line-height: 1.04; max-width: 14ch; }
.mail {
  display: inline-block; margin-top: 2.25rem;
  font-size: clamp(1.4rem, 4vw, 2.6rem); font-weight: 300; text-decoration: none;
  border-bottom: 2px solid rgb(255 255 255 / .4); padding-bottom: .2rem;
  transition: border-color .15s;
}
.mail:hover { border-color: #fff; }

/* The form beside the words, or under them on a narrow screen. Square
   fields with a thin edge, and the round button. */
.contact { display: grid; gap: clamp(2.5rem, 6vw, 4rem); align-items: end; }
@media (min-width: 62rem) { .contact { grid-template-columns: minmax(0, 1fr) minmax(0, 27rem); } }
.write { display: grid; gap: 1.1rem; }
.entry { margin: 0; display: grid; gap: .4rem; }
.entry label { font-family: var(--mono); font-size: .72rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: rgb(255 255 255 / .85); }
.entry label span { margin-left: .5em; letter-spacing: .06em; text-transform: none; color: rgb(255 255 255 / .55); }
.entry input, .entry textarea {
  width: 100%; padding: .7rem .8rem; border: 1px solid rgb(255 255 255 / .4); border-radius: 0;
  background: rgb(1 4 39 / .45); color: #fff; font: inherit; font-weight: 400;
  transition: border-color .15s, background .15s;
}
.entry textarea { display: block; min-height: 8rem; resize: vertical; }
.entry input:hover, .entry textarea:hover { border-color: rgb(255 255 255 / .7); }
.entry input:focus, .entry textarea:focus { border-color: #fff; background: rgb(1 4 39 / .65); }
/* Off the page, not out of it: a robot reads the markup and finds the field. */
.trap { position: absolute; left: -200vw; width: 1px; height: 1px; overflow: hidden; }
.send { margin: .4rem 0 0; display: flex; flex-wrap: wrap; gap: 1rem 1.5rem; align-items: center; }
.send button { border: 0; cursor: pointer; }
.send button:disabled { opacity: .65; cursor: progress; transform: none; }
.send span { flex: 1 1 12rem; font-size: .8rem; line-height: 1.45; color: rgb(255 255 255 / .75); }
.send a { text-underline-offset: .2em; }
.send-failed { margin: 0; padding: .7rem .8rem; background: #fff; color: var(--night); font-weight: 500; }

/* Footer: the logo, and under it or beside it who the company is, a line each. */
.bottom {
  display: flex; flex-wrap: wrap; gap: 2rem 4rem; align-items: flex-start; justify-content: space-between;
  padding: 3rem var(--gutter);
  border-top: 1px solid rgb(255 255 255 / .08);
  font-size: .9rem; color: rgb(255 255 255 / .65);
}
/* The pages, a line each, between the logo and the company's details. */
.foot-nav { display: grid; gap: .25rem; align-content: start; }
.foot-nav a { text-decoration: none; transition: color .15s; }
.foot-nav a:hover { color: #fff; }
/* The way to the page about cookies, under the icons.

   Nothing that has to be seen may have "cookie" in its class. Browsers that
   block cookie notices hide by name, from lists with rules such as
   ##.cookie-choice, and that took the two buttons off /kakor/ for the
   operator on the first day. The question itself keeps its name: whoever
   has asked not to see such questions is not shown ours, and gets no cookie. */
.foot-note { margin: 1.5rem 0 0; font-size: .8rem; }
.foot-note a { text-decoration: none; border-bottom: 1px solid rgb(255 255 255 / .35); transition: color .15s, border-color .15s; }
.foot-note a:hover { color: #fff; border-color: #fff; }

/* The question about the cookie, which main.js adds: a small card in a
   corner. The page works behind it, and the two answers look the same. */
.cookie-ask {
  position: fixed; left: 1rem; bottom: 1rem; z-index: 9;
  width: min(21rem, calc(100% - 2rem)); padding: 1rem 1.1rem 1.05rem;
  background: #0a1140; color: rgb(255 255 255 / .9); font-size: .9rem; line-height: 1.4;
  --edge: rgb(255 255 255 / .3);
  animation: ask .4s .8s cubic-bezier(.2,.7,.2,1) backwards;
}
@keyframes ask { from { opacity: 0; transform: translateY(.75rem); } }
.cookie-ask p { margin: 0; }
.cookie-ask a { text-underline-offset: .2em; white-space: nowrap; }
.cookie-ask p + p { margin-top: .8rem; display: flex; gap: .6rem; }
.cookie-ask button, .answer button {
  padding: .4rem 1.25rem; border: 1px solid rgb(255 255 255 / .5); border-radius: 999px;
  background: none; color: #fff; font: inherit; font-weight: 500; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.cookie-ask button:hover { background: #fff; color: var(--night); border-color: #fff; }

/* The page about cookies: text to read, on the light ground. */
.text-page { background: var(--ice); color: var(--ink); padding: clamp(4rem, 9vw, 7rem) var(--gutter); }
.text-page > * { max-width: 44rem; }
.text-page h2 { margin: 3rem 0 .75rem; font-size: clamp(1.4rem, 2.4vw, 1.9rem); letter-spacing: -.01em; }
.text-page h2:first-child { margin-top: 0; }
.text-page p { margin: 0 0 1rem; }
.text-page a { text-underline-offset: .2em; }
.text-page code { font-family: var(--mono); font-size: .9em; }
.answer { display: flex; flex-wrap: wrap; gap: .6rem 1rem; align-items: center; margin-bottom: 1rem; }
.answer[hidden] { display: none; }
.answer button { border-color: rgb(1 4 39 / .45); color: var(--ink); }
.answer button:hover { border-color: var(--ink); }
.answer button[aria-pressed="true"] { background: var(--ink); color: #fff; border-color: var(--ink); }
.answer-said { flex-basis: 100%; margin: 0; color: var(--muted); }
.stored { width: 100%; margin: 0 0 1rem; border-collapse: collapse; font-size: .95rem; }
.stored th { padding: 0 1rem .5rem 0; text-align: left; font-family: var(--mono); font-size: .72rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.stored td { padding: .7rem 1rem .7rem 0; border-top: 1px solid rgb(1 4 39 / .14); vertical-align: top; }
.stored th:last-child, .stored td:last-child { padding-right: 0; white-space: nowrap; }
.legal { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem; }
.legal a { text-decoration: none; border-bottom: 1px solid rgb(255 255 255 / .35); transition: color .15s, border-color .15s; }
.legal a:hover { color: #fff; border-color: #fff; }
.print-logo { display: none; }
/* The links to social media: a round button with an icon, drawn from icons/
   in the colour of the text. Under the pointer the button fills with pixels:
   icons/fill.svg is nine pictures side by side, from empty to full, and the
   mask steps from the first to the last. The icon turns dark halfway. */
.social { list-style: none; margin: 1.75rem 0 0; padding: 0; display: flex; gap: .75rem; }
.social a {
  position: relative; display: block; width: 2.6rem; height: 2.6rem; overflow: hidden;
  color: #fff; border: 1px solid rgb(255 255 255 / .45); border-radius: 50%;
  transition: border-color .15s, color 0s .14s;
}
.social a::before {
  content: ''; position: relative; z-index: 1; display: block; width: 100%; height: 100%; background: currentColor;
  -webkit-mask: var(--icon) center / 1.35rem 1.35rem no-repeat;
  mask: var(--icon) center / 1.35rem 1.35rem no-repeat;
}
.social a::after {
  content: ''; position: absolute; inset: 0; background: #fff;
  -webkit-mask: url(icons/fill.svg) 0 0 / 900% 100% no-repeat;
  mask: url(icons/fill.svg) 0 0 / 900% 100% no-repeat;
  transition: -webkit-mask-position .28s steps(8), mask-position .28s steps(8);
}
.social a:focus-visible, .social a:active { color: var(--night); border-color: #fff; }
.social a:focus-visible::after, .social a:active::after { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
@media (hover: hover) {
  .social a:hover { color: var(--night); border-color: #fff; }
  .social a:hover::after { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
}
.icon-linkedin { --icon: url(icons/linkedin.svg); }
.icon-instagram { --icon: url(icons/instagram.svg); }
.icon-facebook { --icon: url(icons/facebook.svg); }

@media (prefers-reduced-motion: reduce) {
  .flow, .contact, .scroll-hint span { animation: none; }
  .service, .button, .window, .case-index a, .frames img, .shot-nav, .progress span, .step-n, .step h3, .step p, .step::before { transition: none; }
  .tabbed .case.on { animation: none; }
  .shots, .case-index img { transition: none; transform: none; }
  .cookie-ask { animation: none; }
  .social a, .social a::after { transition: none; }
}

@media print {
  body { background: #fff; color: #000; }
  .top, .field, .scroll-hint, .actions, .social, .shot-nav, .foot-nav, .foot-note, .cookie-ask, .answer, .write { display: none; }
  .hero, .contact, .process { min-height: 0; background: none; padding: 1rem 0; }
  .flow { color: #000; background: none; }
  .lead, .bottom, .step p { color: #000; }
  .step-n { color: #000; background: none; }
  .bottom img:not(.print-logo) { display: none; }
  .print-logo { display: block; }
}
