/* Tiny Bit Studio: "Gallery"
   A small exhibition. One 12-column grid, three text sizes (display, text, meta), no rules or
   dividers: space does the dividing. Color comes from the apps.
   README.md says where things live and how to change them. */

/* ---------------------------------------------------------------- Fonts */

@font-face {
  font-family: "Inter Tight";
  src: url("../fonts/inter-tight-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter Tight";
  src: url("../fonts/inter-tight-arrows.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+2190-2193;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-400-arrows.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+2190-2193;
}

/* ---------------------------------------------------------------- Tokens */

:root {
  /* Light: a bright, faintly cool white wall; plinths a shade deeper, so they read as objects' fields. */
  --canvas: #F8F9FA;
  --plinth: #E9EBEE;
  --ink: #0D0E10;
  --ink-2: #53575E;          /* 6.9:1 on canvas, 6.1:1 on plinth */
  --ink-3: #62666D;          /* 5.5:1 on canvas, 4.8:1 on plinth */
  --glow: rgb(255 255 255 / 0.5);   /* a very faint daylight spot on each plinth */
  --icon-shadow: 0 1px 1.5px rgb(13 14 16 / 0.07), 0 14px 22px rgb(13 14 16 / 0.13);

  /* Color belongs to the apps: marks and bits only, never text. */
  --kozeni: #EF5F31;         /* coral, the coin: 3.1:1 on canvas */
  --lark: #3E8995;           /* teal: 3.8:1 on canvas, 3.4:1 on plinth */
  --michi: #5F86C2;          /* sky blue, the stamp's evening sky: 3.5:1 on canvas, 3.1:1 on plinth */
  --kozeni-gel: transparent;
  --lark-gel: transparent;
  --michi-gel: transparent;

  --sans: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* The three sizes. A page's content uses these and nothing else. */
  --display: clamp(2.75rem, 8.6vw, 8.5rem);
  --text: clamp(1.125rem, 0.9375rem + 0.390625vw, 1.25rem);   /* 18px, rising to 20px at 1280px */
  --meta: clamp(0.8125rem, 0.75rem + 0.125vw, 0.875rem);        /* 13px, rising to 14px */
  --ui: 1.0625rem;           /* the wordmark and the skip link only (the header doesn't count as content) */

  /* Grid */
  --m: clamp(24px, 3.75vw, 72px);    /* outer margin */
  --g: clamp(16px, 1.667vw, 24px);   /* gutter */
  --max: 1680px;

  /* Space: it does the dividing. */
  --room: clamp(7rem, 12vw, 13rem);  /* between rooms and sections */
  --step: clamp(3.5rem, 6vw, 6rem);  /* between the parts of a room */
  --beat: clamp(1.5rem, 2.4vw, 2.5rem);

  --bit: 7px;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Dark: the gallery after hours. A deep neutral wall, slightly raised plinths, a spotlight on each. */
    --canvas: #121315;
    --plinth: #1A1B1E;
    --ink: #EDEEF0;
    --ink-2: #A7ABB2;
    --ink-3: #979BA2;
    --glow: rgb(255 255 255 / 0.075);
    --icon-shadow: 0 18px 30px rgb(0 0 0 / 0.5);

    --kozeni: #FF7A47;
    --lark: #36A9B5;
    --michi: #86A8E0;
    --kozeni-gel: rgb(255 122 71 / 0.06);   /* the spotlight's gel */
    --lark-gel: rgb(54 169 181 / 0.065);
    --michi-gel: rgb(134 168 224 / 0.06);
  }
}

.is-kozeni { --app: var(--kozeni); --gel: var(--kozeni-gel); }
.is-lark { --app: var(--lark); --gel: var(--lark-gel); }
.is-michi { --app: var(--michi); --gel: var(--michi-gel); }

/* ---------------------------------------------------------------- Base */

*, *::before, *::after { box-sizing: border-box; }

html {
  color-scheme: light dark;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: 24px;
}

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--text);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0.002em;
  font-feature-settings: "kern", "calt";
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
p, h1, h2, h3, h4, h5, h6, ul, ol, dl, dd, figure, blockquote { margin: 0; padding: 0; }
h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; }
ul[role="list"], ol[role="list"] { list-style: none; }
strong, b { font-weight: 600; }
button { font: inherit; color: inherit; }
[lang="ja"] { font-family: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic", "Noto Sans JP", sans-serif; letter-spacing: 0; }

a { color: inherit; text-decoration: none; }
/* Links in running text: a quiet underline that takes the app's color on hover. */
:where(p, dd, li, td, th, figcaption) a:where(:not([class])) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  text-decoration-color: color-mix(in srgb, currentColor 42%, transparent);
  transition: text-decoration-color 200ms var(--ease);
}
:where(p, dd, li, td, th, figcaption) a:where(:not([class])):hover { text-decoration-color: var(--app, currentColor); }
:where(.site-nav, .site-foot) a { text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: color-mix(in srgb, var(--app, var(--ink)) 24%, transparent); }

.visually-hidden {
  position: absolute !important;
  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;
}

.skip {
  position: absolute;
  left: var(--m);
  top: 12px;
  z-index: 10;
  padding: 10px 14px;
  background: var(--ink);
  color: var(--canvas);
  font-size: var(--ui);
  font-weight: 500;
  transform: translateY(-300%);
}
.skip:focus { transform: none; }

/* ---------------------------------------------------------------- Type: the three sizes */

.display {
  font-size: var(--display);
  font-weight: 500;
  line-height: 0.96;
  letter-spacing: -0.034em;
  text-wrap: balance;
  overflow-wrap: break-word;   /* only when a word can't fit at all (wider letter spacing, say) */
  text-box: trim-both cap alphabetic;
}
.meta {
  font-family: var(--mono);
  font-size: var(--meta);
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0;
}

.only-dark { display: none; }
@media (prefers-color-scheme: dark) {
  .only-light { display: none; }
  .only-dark { display: inline; }
}

/* The square full stop: the logo's bit at display size, on the baseline. */
.stop {
  display: inline-block;
  width: 0.15em;
  height: 0.15em;
  margin-left: 0.045em;
  background: currentColor;
  vertical-align: baseline;
}

/* A bit: a small square in the app's color. Filled: on the App Store. Hollow: in development. */
.bit {
  display: inline-block;
  flex: none;
  width: var(--bit);
  height: var(--bit);
  background: var(--app, currentColor);
  vertical-align: 0.02em;
}
.bit--hollow {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--app, currentColor);
}
/* Forced colors drop backgrounds and shadows, which would take the stop and the bits with them. */
@media (forced-colors: active) {
  .stop, .bit { forced-color-adjust: none; background: CanvasText; }
  .bit--hollow { background: transparent; box-shadow: inset 0 0 0 1px CanvasText; }
}

.status { color: var(--ink-3); }
.status .bit { margin-right: 10px; }

/* Inline lists joined by dots. The dots are silent to screen readers. */
.dots { display: flex; flex-wrap: wrap; }
.dots > li + li::before {
  content: "·";
  content: "·" / "";
  padding-inline: 0.55em;
}

/* A text link with an arrow. 44px tall to the finger, no taller to the eye. */
.more {
  display: inline-block;
  padding-block: 10px;
  margin-block: -10px;
  font-weight: 500;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: color-mix(in srgb, currentColor 42%, transparent);
  transition: text-decoration-color 200ms var(--ease);
}
.more:hover { text-decoration-color: var(--app, currentColor); }
.more__arrow { display: inline-block; margin-left: 0.35em; }
/* When an arrow link stands on its own line, it is a block as wide as its text; its top margin
   is the visible gap minus the 10px of hit area. */
.more--block { display: block; width: fit-content; }

/* ---------------------------------------------------------------- Grid */

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--m);
}
.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--g);
}
.grid > * { grid-column: 1 / -1; }

/* ---------------------------------------------------------------- Header */

.site-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;   /* the nav sits on the wordmark's baseline */
  justify-content: space-between;
  gap: 0 16px;
  padding-top: clamp(12px, 1.8vw, 28px);
}
.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 11px;
  min-height: 44px;
  padding-top: 9px;
  font-size: var(--ui);
  font-weight: 600;
  letter-spacing: -0.012em;
  white-space: nowrap;
}
.mark { fill: currentColor; shape-rendering: crispEdges; overflow: visible; }
.brand__mark { position: relative; top: 4px; }
.site-nav ul { display: flex; gap: clamp(4px, 1.6vw, 24px); margin-right: -8px; }
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 8px;
  color: var(--ink-2);
  transition: color 200ms var(--ease);
}
.site-nav a:hover { color: var(--ink); }

/* ---------------------------------------------------------------- Footer */

.site-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 32px;
  padding-top: 24px;
  padding-bottom: 36px;
  color: var(--ink-3);
}
.site-foot__sign { display: flex; align-items: baseline; gap: 14px; }
.site-foot__mark { position: relative; top: 5px; fill: var(--ink); }
.site-foot a { display: inline-block; padding-block: 6px; transition: color 200ms var(--ease); }
.site-foot a:hover { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.25em; }

/* ---------------------------------------------------------------- Plinth */

.plinth {
  position: relative;
  display: grid;
  place-items: center;
  background: var(--plinth);
  overflow: hidden;
  isolation: isolate;
}
.plinth::before {
  /* the light over the work, with the app's gel in it */
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(40% 46% at 50% 44%, var(--gel, transparent), transparent 70%),
    radial-gradient(56% 60% at 50% 44%, var(--glow), transparent 74%);
}
.plinth picture { display: contents; }
/* With the picture unwrapped, its <source> would become an empty grid item and take a row of its
   own, pushing the icon below the middle. Sources never render, so take them out of the layout. */
.plinth source { display: none; }
/* An app's icon is one size in every room, whatever its plinth's width: a quarter of the room's
   grid (about 44% of a seven-column plinth), never wider than 22.5rem. Its shadow is a box-shadow
   on a 26% corner, which follows the icons' own within about a pixel, not a drop-shadow on its
   pixels: Safari repaints only the icon's square when its image arrives after the first paint,
   and that cuts a drop-shadow off square (WebKit bug 236758). */
.plinth__icon {
  width: min(25cqi, 22.5rem);
  height: auto;
  border-radius: 26%;
  box-shadow: var(--icon-shadow);
}
.plinth--room { aspect-ratio: 5 / 4; max-height: 42rem; }

/* ---------------------------------------------------------------- Label */

.label { color: var(--ink-2); }
.label dd { text-wrap: balance; }   /* a line that wraps splits evenly, never leaving one word behind */
.label__lead { color: var(--ink); }

/* ---------------------------------------------------------------- Store badge */

.store { display: grid; justify-items: start; gap: 14px; }
.store__badge { display: block; border-radius: 8px; }
.store__badge img { width: auto; height: 44px; }

/* ---------------------------------------------------------------- Hero */

.hero { padding-top: clamp(2.5rem, 7.5vh, 6.5rem); }
.hero__title { margin-left: -0.06em; }
.hero__lede {
  margin-top: clamp(2.25rem, 4.6vw, 4.25rem);
  max-width: 27em;
  color: var(--ink-2);
  text-wrap: pretty;
}

/* ---------------------------------------------------------------- Rooms */

.room { padding-top: var(--room); }
.rooms > .room:first-of-type { padding-top: clamp(4rem, 7vw, 7.5rem); }
/* In-page jumps land on the content, not on the space above it (html's scroll-padding adds 24px). */
.room, .studio, .contact { scroll-margin-top: calc(-1 * var(--room)); }
.rooms, .rooms > .room:first-of-type { scroll-margin-top: calc(-1 * clamp(4rem, 7vw, 7.5rem)); }
.room__main { align-items: start; container-type: inline-size; }   /* the grid its icon is measured against */
.room__name { margin-top: 28px; margin-left: -0.055em; }
.room__gloss { margin-top: 18px; color: var(--ink-3); }
.room__pitch { margin-top: 30px; max-width: 26em; text-wrap: pretty; }
.room__store { margin-top: 32px; }

/* Kozeni: the object on the left, its head and label on the right. */
.room--kozeni .plinth { grid-column: 1 / span 7; grid-row: 1 / span 2; }
.room--kozeni .room__head { grid-column: 9 / -1; grid-row: 1; }
.room--kozeni .room__label { grid-column: 9 / -1; grid-row: 2; align-self: end; margin-top: 48px; }
/* Mirrored (Michi): the head and label on the left, the object on the right. */
.room--mirror .plinth { grid-column: 6 / -1; }
.room--mirror .room__head, .room--mirror .room__label { grid-column: 1 / span 4; }

/* Lark: the name and its line across the top, ending on one baseline (the badge's foot, or without a
   badge the line's last baseline, sits on the name's), then a wide plinth (the icon and the covered
   sentence), with the label under the icon and the rhythm under the sentence.
   A brief room, for an app in development, is that top line alone. */
.room--lark .room__head, .room--brief .room__head { grid-column: 1 / span 4; align-self: end; align-self: last baseline; }
.room--lark .room__intro, .room--brief .room__intro { grid-column: 5 / span 6; align-self: end; align-self: last baseline; }
.room--lark .room__pitch, .room--brief .room__pitch { margin-top: 0; }
.room--lark .stage { margin-top: var(--step); }
.room--lark .room__label { grid-column: 1 / span 4; margin-top: var(--beat); }
.room--lark .room__rhythm { grid-column: 5 / -1; margin-top: var(--beat); }

/* The stage: a wide plinth for an object and a piece beside it. It shares the page grid. */
.stage {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  place-items: initial;   /* undo the plinth's centering first, so the line below survives it */
  align-items: center;
  padding-block: clamp(3rem, 6vw, 6.5rem);
}
.stage::before {
  background:
    radial-gradient(18% 44% at 17% 50%, var(--gel, transparent), transparent 70%),
    radial-gradient(24% 58% at 17% 50%, var(--glow), transparent 74%),
    radial-gradient(40% 70% at 64% 50%, var(--glow), transparent 76%);
}
.stage__object { grid-column: 1 / span 4; justify-self: center; }
.stage__piece { grid-column: 5 / -1; padding-right: clamp(24px, 4vw, 72px); }

/* Points: run-in feature points. */
.points { margin-top: var(--step); row-gap: 32px; }
.points > li {
  grid-column: span 3;
  max-width: 24em;
  color: var(--ink-2);
  text-wrap: pretty;
}
.points strong { color: var(--ink); }

/* ---------------------------------------------------------------- Covered (Lark's exhibit) */

/* The bars are a tint of the ink, not a block of it: a quiet exhibit of Lark's redacted lines. */
.covered { --cover: rgb(13 14 16 / 0.17); }
@media (prefers-color-scheme: dark) {
  .covered { --cover: rgb(237 238 240 / 0.16); }
}
.covered__turn { color: var(--ink-2); text-box: trim-both cap alphabetic; }
.covered__turn .bit { margin-right: 10px; }
.covered__line { margin-top: var(--beat); hyphens: none; text-wrap: wrap; }
.covered__unit { white-space: nowrap; }
.covered__word { display: inline-block; position: relative; }
.covered__word::after {
  /* the redaction bar: the word's own width, punctuation included, from the baseline to about the
     x-height, with the soft corners of Lark's own placeholders, which leave no glyph showing */
  content: "";
  position: absolute;
  left: 0;
  right: 0.03em;
  top: 0.32em;
  bottom: 0.12em;
  border-radius: 0.07em;
  background: var(--cover);
  opacity: 0;
  pointer-events: none;
}
@media (forced-colors: active) {
  .covered__word::after { forced-color-adjust: none; background: CanvasText; }
}
.is-covered .covered__line { color: var(--ink-3); cursor: pointer; }
.is-covered .covered__word { visibility: hidden; }
.is-covered .covered__word::after { visibility: visible; opacity: 1; }
.covered__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 14px 36px;
  margin-top: var(--beat);
}
.covered__meaning { flex: 1 1 16em; color: var(--ink-2); text-wrap: pretty; }
.is-covered .covered__meaning { visibility: hidden; }
.covered__toggle {
  display: inline-block;
  padding: 10px 0;
  margin: -10px 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-weight: 500;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: color-mix(in srgb, currentColor 42%, transparent);
}
.covered__toggle:hover { text-decoration-color: var(--app, currentColor); }
.covered:not(.is-covered) .covered__toggle { text-decoration-color: currentColor; }
/* Its state, to the eye: a bit that fills while the sentence is shown. */
.covered__toggle::before {
  content: "";
  display: inline-block;
  width: var(--bit);
  height: var(--bit);
  margin-right: 10px;
  vertical-align: 0.02em;
  box-shadow: inset 0 0 0 1px var(--app, currentColor);
}
.covered:not(.is-covered) .covered__toggle::before { background: var(--app, currentColor); }
@media (forced-colors: active) {
  .covered__toggle::before { forced-color-adjust: none; box-shadow: inset 0 0 0 1px ButtonText; }
  .covered:not(.is-covered) .covered__toggle::before { background: ButtonText; }
}
.covered__toggle[hidden] { display: none; }

/* ---------------------------------------------------------------- Rhythm (Lark's drill) */

.rhythm {
  --rb: 10px;      /* a square */
  --rgap: 5px;
  display: flex;
  gap: var(--g);
}
.rhythm__run { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.rhythm__run--play, .rhythm__run--again { flex: 10 1 0; }
.rhythm__run--turn { flex: 17 1 0; }    /* your turn lasts 1.7 times the sentence, by default */
.rhythm__bits {
  display: block;
  height: var(--rb);
  margin-right: calc(-1 * var(--rgap));
  background-color: var(--app, currentColor);
  -webkit-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='10'><rect width='10' height='10'/></svg>") left center / calc(var(--rb) + var(--rgap)) var(--rb) space no-repeat;
  mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='10'><rect width='10' height='10'/></svg>") left center / calc(var(--rb) + var(--rgap)) var(--rb) space no-repeat;
}
/* Whole squares only. Safari ignores "space" in mask-repeat and ends a run on a sliver of a square,
   so where round() exists the run is cut to a whole number of squares and the mask simply repeats. */
@supports (width: round(down, 1px, 1px)) {
  .rhythm__bits {
    width: round(down, calc(100% + var(--rgap)), calc(var(--rb) + var(--rgap)));
    margin-right: 0;
  }
}
.rhythm__run--turn .rhythm__bits {
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='10'><rect x='0.75' y='0.75' width='8.5' height='8.5' fill='none' stroke='black' stroke-width='1.5'/></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='10'><rect x='0.75' y='0.75' width='8.5' height='8.5' fill='none' stroke='black' stroke-width='1.5'/></svg>");
}
.rhythm__label { color: var(--ink-2); text-wrap: balance; }
@media (forced-colors: active) {
  .rhythm__bits { background-color: CanvasText; }
}

/* ---------------------------------------------------------------- Studio */

.studio { padding-top: var(--room); align-items: start; }
.studio__title { color: var(--ink-3); text-box: trim-both cap alphabetic; }
.motto { margin-top: 40px; }
.motto__quote { margin-left: -0.06em; }
.motto__cite { margin-top: 30px; color: var(--ink-3); }
.studio__text {
  grid-column: 1 / span 5;
  display: grid;
  gap: 1em;
  margin-top: var(--step);
  max-width: 29em;
  color: var(--ink-2);
  text-wrap: pretty;
}
.bench { grid-column: 7 / -1; margin-top: var(--step); }
.bench__title { color: var(--ink-3); text-box: trim-both cap alphabetic; }

.workbench { display: grid; gap: 12px; margin-top: 22px; }
.workbench__item {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  column-gap: var(--g);
  align-items: baseline;
}
.workbench__app { color: var(--ink-3); white-space: nowrap; }
.workbench__text { text-wrap: balance; }   /* a subject that wraps never leaves one word behind */
.workbench__app .bit { margin-right: 10px; }
.workbench__more { margin-top: 20px; padding-left: calc(6.5rem + var(--g)); color: var(--ink-2); }

/* ---------------------------------------------------------------- Contact */

.contact { padding-block: var(--room); align-items: start; }
.contact__title { color: var(--ink-3); text-box: trim-both cap alphabetic; }
.contact__mail { margin-top: 40px; margin-left: -0.06em; }
.contact__link {
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 0.05em no-repeat;
  padding-bottom: 0.08em;
}
.contact__link:hover { background-size: 100% 0.05em; }
.contact__note { grid-column: 7 / span 5; margin-top: 48px; color: var(--ink-2); }
.contact__note p { max-width: 29em; text-wrap: pretty; }

/* ---------------------------------------------------------------- Doc pages (layout: doc) */

.doc__head { padding-top: clamp(3rem, 8vw, 8rem); align-items: baseline; }
.doc__label { grid-column: 1 / span 3; color: var(--ink-3); }
.doc__title { grid-column: 4 / -1; margin-left: -0.055em; }
.doc__updated { grid-column: 4 / -1; margin-top: 30px; color: var(--ink-3); }
.doc__body { padding-block: var(--step) var(--room); }

/* Prose: kramdown output flows into the text column with no classes. 31em of text is about 68
   characters a line (68ch would be more: ch is a zero's width, wider than the average letter). */
.prose { align-items: baseline; }
.prose > * { grid-column: 4 / span 7; max-width: 31em; }
.prose > * + * { margin-top: 1em; }
.prose > h2 { margin-top: 2.75em; font-weight: 600; }
.prose > h3 { margin-top: 2em; font-weight: 600; }
.prose > h4, .prose > h5, .prose > h6 { margin-top: 1.5em; font-weight: 600; }
.prose > :is(h2, h3, h4):where(:not(.margin)) + * { margin-top: 0.5em; }
.prose > :first-child { margin-top: 0; }
.prose :is(p, li, dd) { text-wrap: pretty; }
/* A margin label: a short mono note beside the next block (or the heading it follows). Written as
   a heading (### Label, then {: .margin}), it also names that part of the page for screen readers. */
.prose > .margin {
  grid-column: 1 / span 3;
  font-family: var(--mono);
  font-size: var(--meta);
  font-weight: 400;
  line-height: 1.55;
  color: var(--ink-3);
  text-wrap: balance;
}
/* It shares a row with its neighbor and sits on the same baseline, so it keeps no margin of its own. */
.prose > .margin { margin-top: 0; }
.prose > :is(h2, h3, h4) + .margin + * { margin-top: 0.5em; }
/* A part that stands on its own (each policy on the privacy page): a display head, with a margin
   label on its baseline, the way the page's title has one. */
.prose > h2.display { grid-column: 4 / -1; margin-top: var(--step); font-weight: 500; }
.prose > h2.display + .margin + * { margin-top: var(--beat); }
.prose > .wide { grid-column: 4 / -1; max-width: none; }
.prose ul, .prose ol { padding-left: 1.25em; }
.prose ul { list-style: square; }
.prose li + li, .prose li > ul, .prose li > ol { margin-top: 0.4em; }
.prose li::marker { color: var(--ink-3); }
.prose ol > li::marker { font-family: var(--mono); font-size: var(--meta); }
.prose code, .prose kbd, .prose samp { font-family: var(--mono); font-size: 1em; }
.prose pre { font-family: var(--mono); font-size: var(--meta); line-height: 1.6; overflow-x: auto; padding: 1.25em 1.5em; background: var(--plinth); }
.prose pre code { font-size: inherit; }
.prose blockquote { position: relative; padding-left: 1.4em; color: var(--ink-2); }
.prose blockquote::before { content: ""; position: absolute; left: 0; top: 0.6em; width: var(--bit); height: var(--bit); background: var(--app, var(--ink-3)); }
.prose blockquote > * + * { margin-top: 0.75em; }
.prose hr { height: 0; margin-block: 1.5em; border: 0; }   /* a rule, drawn as space */
.prose table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.prose th {
  font-family: var(--mono);
  font-size: var(--meta);
  font-weight: 400;
  color: var(--ink-3);
  text-align: left;
}
.prose th, .prose td { padding: 0.55em 1.25em 0.55em 0; vertical-align: baseline; }
.prose :is(th, td):last-child { padding-right: 0; }
.prose sup { font-family: var(--mono); font-size: var(--meta); line-height: 0; }
.prose .footnotes { margin-top: var(--step); font-family: var(--mono); font-size: var(--meta); line-height: 1.55; color: var(--ink-2); }
.prose .footnotes ol { padding-left: 1.75em; }
.prose .reversefootnote { margin-left: 0.4em; text-decoration: none; }

/* ---------------------------------------------------------------- 404 */

.lost { padding-top: clamp(3rem, 8vw, 8rem); padding-bottom: var(--room); align-items: stretch; }
.lost__title { margin-left: -0.06em; }
.lost__plinth { grid-column: 1 / span 7; margin-top: var(--step); }
.lost__info {
  grid-column: 9 / -1;
  margin-top: var(--step);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 48px;
}
.lost__note { max-width: 26em; color: var(--ink-2); text-wrap: pretty; }
.lost__more { margin-top: 18px; }

/* ---------------------------------------------------------------- Motion (all of it off under reduced motion) */

@media (prefers-reduced-motion: no-preference) {
  /* The hero settles once. */
  .hero__title { animation: settle 720ms var(--ease) both; }
  .hero__lede { animation: settle 720ms 90ms var(--ease) both; }
  @keyframes settle { from { opacity: 0; transform: translateY(0.5rem); } }

  /* The lights come up once as each plinth enters (site.js adds .is-in). */
  .js [data-light]::before { opacity: 0; transition: opacity 1100ms var(--ease); }
  .js [data-light].is-in::before { opacity: 1; }

  .more__arrow { transition: transform 240ms var(--ease); }
  .more:hover .more__arrow { transform: translateX(3px); }

  /* The logo's bit goes back into its notch, then comes out again. */
  .brand:hover .mark__bit, .brand:focus-visible .mark__bit { animation: bit-home 900ms var(--ease); }
  @keyframes bit-home { 40%, 62% { transform: translate(-6px, 6px); } }

  .covered__line { transition: color 360ms var(--ease); }
  .covered__word::after { transition: opacity 360ms var(--ease); }

  /* The email's underline draws itself in on hover. */
  .contact__link { transition: background-size 400ms var(--ease); }
}

/* ---------------------------------------------------------------- Tablet: 720 to 1079 */

@media (max-width: 1079px) {
  /* A column of space between the object and its words, as on desktop. */
  .room--kozeni .plinth { grid-column: 1 / span 5; grid-row: 1; aspect-ratio: 1; }
  .room--kozeni .room__head { grid-column: 7 / -1; grid-row: 1 / span 2; }
  .room--kozeni .room__label { grid-column: 1 / span 5; grid-row: 2; align-self: start; margin-top: 24px; }
  .room--mirror .plinth, .room--mirror .room__label { grid-column: 8 / -1; }
  .room--mirror .room__head { grid-column: 1 / span 6; }

  .room--lark .room__intro, .room--brief .room__intro { grid-column: 5 / -1; }
  .plinth__icon { width: 18cqi; }   /* about 44% of the five-column plinth */

  .points > li { grid-column: span 6; }

  .studio__text, .bench { grid-column: 1 / -1; max-width: 40em; }
  .contact__note { grid-column: 1 / -1; }

  .lost__plinth { grid-column: 1 / span 5; aspect-ratio: 1; }
  .lost__info { grid-column: 7 / -1; }
}

/* On tablets, prose takes the width to the right edge; 31em still keeps its lines to about 68 characters. */
@media (min-width: 720px) and (max-width: 1079px) {
  .prose > :not(.margin) { grid-column: 4 / -1; }
}

/* ---------------------------------------------------------------- Phone: under 720 */

@media (max-width: 719px) {
  .site-head { padding-top: 8px; }
  .site-nav ul { gap: 0; }
  .site-nav a { padding-inline: 7px; }

  .hero { padding-top: clamp(2.5rem, 10vw, 4rem); }
  .hero__title { margin-left: -0.05em; }

  .room__main { row-gap: 0; }
  .room--kozeni .room__head, .room--kozeni .plinth, .room--kozeni .room__label { grid-column: 1 / -1; grid-row: auto; }
  .room--kozeni .plinth { margin-top: 44px; aspect-ratio: 1; }
  .room--kozeni .room__label { margin-top: 20px; }
  .plinth__icon { width: 52cqi; }

  .room--lark .room__head, .room--lark .room__intro, .room--lark .room__label, .room--lark .room__rhythm { grid-column: 1 / -1; align-self: auto; }
  .room--brief .room__head, .room--brief .room__intro { grid-column: 1 / -1; align-self: auto; }
  .room--lark .room__pitch, .room--brief .room__pitch { margin-top: 30px; }
  .room--lark .room__label { margin-top: 20px; }
  .room--lark .room__rhythm { margin-top: 36px; }
  .stage { padding: 40px 24px 32px; row-gap: 32px; }
  .stage__object { grid-column: 1 / -1; }
  .stage__piece { grid-column: 1 / -1; padding-right: 0; }
  .stage::before {
    background:
      radial-gradient(46% 26% at 50% 20%, var(--gel, transparent), transparent 70%),
      radial-gradient(58% 34% at 50% 20%, var(--glow), transparent 74%),
      radial-gradient(70% 40% at 50% 68%, var(--glow), transparent 76%);
  }

  .points > li { grid-column: 1 / -1; }

  /* stacked: the squares keep their proportions (10 : 17 : 10), the captions get the width */
  .rhythm { flex-direction: column; gap: 18px; }
  .rhythm__run { flex: none; gap: 10px; }
  .rhythm__run--play .rhythm__bits, .rhythm__run--again .rhythm__bits { width: calc(42% + var(--rgap)); }
  .rhythm__run--turn .rhythm__bits { width: calc(71% + var(--rgap)); }
  @supports (width: round(down, 1px, 1px)) {
    .rhythm__run--play .rhythm__bits, .rhythm__run--again .rhythm__bits { width: round(down, calc(42% + var(--rgap)), calc(var(--rb) + var(--rgap))); }
    .rhythm__run--turn .rhythm__bits { width: round(down, calc(71% + var(--rgap)), calc(var(--rb) + var(--rgap))); }
  }

  .workbench { gap: 16px; }
  .workbench__item { grid-template-columns: 1fr; row-gap: 2px; }
  .workbench__item:nth-child(n+9) { display: none; }
  .workbench__more { padding-left: 0; }

  .contact__mail { margin-top: 32px; }

  .doc__label, .doc__title, .doc__updated { grid-column: 1 / -1; }
  .doc__title { margin-top: 18px; }
  .prose > *, .prose > .wide, .prose > h2.display { grid-column: 1 / -1; }
  .prose > .margin { grid-column: 1 / -1; margin-top: 2em; }
  .prose > .margin + * { margin-top: 0.35em; }
  /* A display head's label goes above it; a jump to the head (/privacy/#kozeni) keeps the label in view. */
  .prose > .margin + h2.display { margin-top: 0.35em; }
  .prose > h2.display { scroll-margin-top: 2.5rem; }
  .prose > h2.display + .margin { margin-top: var(--beat); }
  .prose > h2.display + .margin + * { margin-top: 0.35em; }

  .lost__plinth, .lost__info { grid-column: 1 / -1; }
  .lost__info { margin-top: 40px; }
}

@media (max-width: 400px) {
  :root { --m: 20px; }
  .brand { gap: 9px; font-size: 1rem; }
  .site-nav a { padding-inline: 6px; }
}
