/* The Wall: a clean white wall with the identity's faint grid, pale blue light and fine blue
   string. The detective board lends the structure only; the look is NOVUS (design.md). */

@font-face {
  font-family: "PP Neue Montreal";
  src: url("/fonts/PPNeueMontreal-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
/* Milling: Triplex is licensed for the web (205TF order 10922, 2026-11-02, novusdesignlabs.com),
   so it ships. The handwritten cut, the visitor's own note, is still a local-only trial
   (gitignored); without it the note falls back to Triplex. */
@font-face {
  font-family: "Milling Note";
  src: url("/fonts/MillingTPTrial-DuplexG3Italic.otf") format("opentype");
  font-display: swap;
}
@font-face {
  font-family: "Milling";
  src:
    url("/fonts/205TF-MillingTP-TriplexG3.woff2") format("woff2"),
    url("/fonts/205TF-MillingTP-TriplexG3.woff") format("woff");
  font-display: swap;
}

/* The tokens: design.md's, as the component lab has them (public/lab/components.html; the user,
   2026-10-29: "how do i make sure my design has these implemented"). Only the blue and grey ramps:
   indigo and Vida are left out ("we are not using purple", "remove vida"). The wall's own names
   stay, on the ramps; the thread's brighter blues are its own, not the components'. */
:root {
  --sans: "PP Neue Montreal", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --milling: "Milling", var(--sans);

  /* design.md's ramps */
  --primary-50: #e7f6ff;
  --primary-100: #c3e8ff;
  --primary-200: #88d1ff;
  --primary-300: #4cbaff;
  --primary-500: #0692e5;
  --primary-700: #0774b8;
  --primary-800: #055282;
  --primary-900: #012b45;
  --grey-50: #eeeeee;
  --grey-100: #d4d3d3;
  --grey-200: #9e9d9d;
  --grey-300: #706e6e;
  --grey-500: #575757;
  --grey-700: #474747;
  --grey-800: #333333;
  --grey-900: #0f0f0f;

  /* The wall's names, on the ramps */
  --wall: #fbfcfd;
  --ink: var(--grey-900);
  --ink-2: var(--grey-500);
  --ink-3: var(--grey-300);
  --line: var(--grey-50);
  --blue: #2ba7ff;
  --blue-50: var(--primary-50);
  --blue-100: var(--primary-100);
  --blue-200: var(--primary-200);
  --blue-700: var(--primary-700);
  --blue-800: var(--primary-800);
  --focus: var(--primary-500);

  --string: #3ea9f0;
  --string-lit: #2ba7ff;

  /* design.md's meaning, where the wall had no name. Error is #CE2C31, not design.md's #E5484D,
     which is under AA for small text; success text a darker green for the same reason. */
  --on-primary: #fff;
  --disabled-bg: var(--grey-50);
  --disabled-text: var(--grey-200);
  --success: #30a46c;
  --success-text: #18794e;
  --success-bg: #e9f9ee;
  --error: #ce2c31;
  --error-bg: #ffefef;
  --warning: #ffb224;
  --info: var(--primary-700);

  /* Type: design.md's scale, the mobile column under 768 px */
  --fs-display: 48px;
  --fs-h1: 40px;
  --fs-h2: 32px;
  --fs-h3: 24px;
  --fs-body-lg: 18px;
  --fs-body: 16px;
  --fs-body-sm: 14px;
  --fs-button: 15px;
  --fs-label: 12px;
  --fs-metric: 36px;
  --lh-tight: 1.25;
  --lh-body: 1.55;
  --tr-button: 0.005em;
  --tr-label: 0.04em;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;
  --space-5: 32px;
  --space-6: 48px;
  --space-7: 64px;
  --space-8: 96px;
  --space-9: 128px;

  --radius: 8px;
  --radius-sm: 8px;
  --radius-lg: 24px;
  --radius-pill: 999px;

  --shadow-paper: 0 1px 2px rgba(16, 42, 67, 0.06), 0 10px 28px -8px rgba(16, 42, 67, 0.14);
  --shadow-lift: 0 30px 80px -20px rgba(16, 42, 67, 0.32), 0 8px 24px rgba(16, 42, 67, 0.08);
  --shadow-1: 0 1px 2px rgba(16, 42, 67, 0.06), 0 1px 3px rgba(16, 42, 67, 0.08);
  --shadow-2: 0 4px 12px rgba(16, 42, 67, 0.08), 0 2px 4px rgba(16, 42, 67, 0.04);
  --shadow-3: 0 12px 28px rgba(16, 42, 67, 0.1), 0 4px 8px rgba(16, 42, 67, 0.05);
  --shadow-4: 0 24px 56px rgba(16, 42, 67, 0.14), 0 8px 16px rgba(16, 42, 67, 0.06);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-emphasized: var(--ease);
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --duration-fast: 150ms;
  --duration-base: 250ms;
  --duration-slow: 400ms;
  color-scheme: light;
}

@media (min-width: 768px) {
  :root {
    --fs-display: 80px;
    --fs-h1: 56px;
    --fs-h2: 40px;
    --fs-h3: 28px;
    --fs-body-lg: 20px;
    --fs-button: 16px;
    --fs-metric: 48px;
  }
}

* {
  box-sizing: border-box;
}

html {
  /* No rubber-band past the ends: the wall is fixed behind the page, so a bounce at the foot
     showed it under the footer (the user, 2026-10-23: "im able to scroll past this"). */
  overscroll-behavior-y: none;
  background: var(--wall);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--wall);
  overscroll-behavior-x: none;
  overscroll-behavior-y: none;
}

html.is-page,
html.is-lifted,
html.is-board {
  overflow: hidden;
}

/* The board holds the scrollbar's room while it is up (the user, 2026-11-03: opening and closing it
   "is not seamless"). Without it, where scrollbars take room (Windows), the page went 15 px wider the
   moment the board opened and back as it closed, and the wall's canvas resized under the growing
   board and again just after it had folded away, so the wall jumped both times. */
html.is-board {
  scrollbar-gutter: stable;
}

/* That room (the board can't cover it: 100vw leaves it out) in the board's own panel colour
   (.board__paper), so it doesn't show as a strip at its right edge. */
html.is-board {
  background: #f1f7fc;
}

img {
  display: block;
  max-width: 100%;
}

button {
  font: inherit;
  color: inherit;
}

a {
  color: inherit;
}

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

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.label {
  font-size: 12px;
  line-height: 1.33;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* ------------------------------------------------------------------------------------------ */
/* Phosphor icons set with words (ui/icons.tsx): an em high, sitting on their line. */
.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.14em;
}

/* Nav (the user, 2026-10-27, from three directions: "lock in C"; "this currently looks like a
   really poor implementation, including the hover states"): one pill in the middle of the top,
   the wordmark and Explore, which drops the three products in under it; on a phone the wordmark
   and a hamburger, which opens the menu. Bright frosted glass, a little off the wall by its shadow,
   no line round it. The glass of the first screen goes once you have come in, rather than become a
   bar over the wall. */

.nav {
  position: fixed;
  top: 14px;
  left: 0;
  right: 0;
  /* Over the pages too (40), so they keep it. */
  z-index: 45;
  display: flex;
  justify-content: center;
  pointer-events: none;
  transition: transform 360ms var(--ease);
}

.nav > * {
  pointer-events: auto;
}

/* Reading a page, it goes up out of the way as you scroll down and comes back as you scroll up
   (ui/PageView.tsx; the user's pick, 2026-10-25). */
html.nav-away .nav--page {
  transform: translateY(calc(-100% - 20px));
}

/* The glass. On the pill it lies on a layer behind what the pill holds, not on the pill: a frosted
   element inside another frosted one can only blur what its parent holds, so the panel inside it
   showed the wall through it unblurred (the user, 2026-10-27: "fix the bg in all the blend mode is
   incorrect"). The panels hold nothing frosted. */
.nav__pill::before,
.drop,
.menu {
  background: rgba(251, 252, 253, 0.8);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  box-shadow:
    0 12px 32px rgba(9, 38, 64, 0.08),
    0 1px 3px rgba(9, 38, 64, 0.06);
}

.nav__pill {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  height: 48px;
  padding: 0 6px 0 22px;
  border-radius: 999px;
}

.nav__pill::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

.nav__logo {
  display: flex;
  align-items: center;
}

/* The wordmark a size down (the user: "reduce the size of the novus labs text"), lifted 2 px so its
   baseline is the label's ("not aligned", "still off"), which also centres its lowercase on the
   pill. */
.nav__logo img {
  position: relative;
  top: -2px;
  display: block;
  height: 12.5px;
  width: auto;
}

/* The panel hangs from the pill, not from its button. */
.nav__group {
  position: static;
}

/* Explore ("i dont know if products is the right ux copy"; their pick), in capitals at the nav's 12
   px ("no do all caps not small caps", after sentence case and small capitals were tried; "dont
   increase the font size"), as tall as the wordmark's lowercase, centred in its
   chip, as much room above it as below ("the top padding and bottom padding are odd in the
   hoverstate"); the wordmark meets its baseline. Bare until the pointer is on it or its panel is
   open ("looks really bad with the constant hover state on"). */
.nav__trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 14px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  transition: background-color 160ms;
}

.nav__trigger:hover,
.nav__trigger:focus-visible,
.nav__trigger[aria-expanded="true"] {
  background: rgba(15, 15, 15, 0.06);
}

/* Phosphor's CaretDown (ui/icons.tsx), turning over as the panel opens. */
.nav__caret {
  width: 12px;
  height: 12px;
  margin-top: -1px;
  transition: transform 260ms var(--ease);
}

.nav__trigger[aria-expanded="true"] .nav__caret {
  transform: rotate(180deg);
}

/* The hamburger, on a phone ("mobile should be a hamburegr menu along with novus labs"): Phosphor's
   List, and its X while the menu is open (ui/icons.tsx); bare until touched or open. */
.nav__burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 36px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink);
  cursor: pointer;
  transition: background-color 160ms;
}

.nav__burger:hover,
.nav__burger:focus-visible,
.nav__burger[aria-expanded="true"] {
  background: rgba(15, 15, 15, 0.06);
}

.nav__burger-icon {
  width: 18px;
  height: 18px;
}

/* The products' panel: it drops in centred under the pill, a little down and in from small. */
.drop {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  translate: -50% 0;
  padding: 8px;
  border-radius: 22px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  transform-origin: top center;
  transition:
    opacity 180ms var(--ease),
    transform 280ms var(--ease),
    visibility 0s 280ms;
}

.drop[data-open] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity 180ms var(--ease),
    transform 280ms var(--ease);
}

/* The pointer crosses the gap above the panel without leaving the group. */
.drop::before {
  content: "";
  position: absolute;
  inset: -14px 0 auto 0;
  height: 14px;
}

/* The products ("the product images can be in the drop down"): in the phone's menu a list, each
   photograph small beside its name and line. */
.drop__rows {
  display: grid;
  gap: 2px;
}

.drop__row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding: 6px;
  border-radius: 12px;
  color: var(--ink);
  text-decoration: none;
  transition: background-color 160ms;
}

.drop__row:hover,
.drop__row:focus-visible {
  background: rgba(15, 15, 15, 0.04);
}

.drop__thumb {
  width: 64px;
  height: 64px;
  overflow: hidden;
  border-radius: 10px;
  background: var(--blue-50);
}

.drop__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 600ms var(--ease);
}

.drop__row:hover img {
  transform: scale(1.05);
}

.drop__words {
  display: grid;
  gap: 3px;
}

.drop__name {
  font-size: 15px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -0.005em;
}

.drop__line {
  font-size: 12px;
  line-height: 1.35;
  color: var(--ink-3);
}

/* In Explore's panel (a wide screen only) they sit side by side in one row, each photograph large
   over its name and line (the user, 2026-10-27: "instead of something so small can we try it where
   the image is larger and theyre next to each other in one row?", "only for desktop"). */
.drop .drop__rows {
  grid-template-columns: repeat(3, 236px);
  gap: 4px;
}

/* Corners nested by what lies between them, so they run parallel (the user, 2026-10-27: "in the
   hover state the nested rounded radius looks off"): the panel's 22 less its 8 of padding for the
   card, the card's 14 less its 6 for the photograph. */
.drop .drop__row {
  grid-template-columns: none;
  align-items: start;
  gap: 12px;
  padding: 6px 6px 12px;
  border-radius: 14px;
}

.drop .drop__thumb {
  width: auto;
  height: auto;
  aspect-ratio: 3 / 2;
  border-radius: 8px;
}

.drop .drop__words {
  padding: 0 4px;
}

/* Each line on one line in English ("keep nex 1 in 1 line too"): the longest, NEX 1's, is 209 px,
   and a card 236 px wide leaves 216 for it. A longer one (the Italian NEX 2's) goes over two
   balanced lines in its own card: kept on one, it pushed its card and photograph out over NEX 3's
   (the user, 2026-11-02). */
.drop .drop__row {
  min-width: 0;
  /* All three cards are the tallest's height: what's in them stays at their top, so the names line
     up across (the user, 2026-11-02: "alignment"; the shorter cards spread the spare height). */
  align-content: start;
}

.drop .drop__line {
  text-wrap: balance;
}

/* The phone's menu: the products, just them ("dont add follow and the 'products' tag to the menu"). */
/* At most 400 px, centred under the nav's pill: edge to edge it ran 650 px wide on a large phone
   or a small tablet (the user, 2026-11-03: "fix the width"). */
.menu {
  position: fixed;
  z-index: 46;
  top: 68px;
  left: 50%;
  width: min(calc(100vw - 20px), 400px);
  box-sizing: border-box;
  transform: translateX(-50%);
  display: grid;
  padding: 8px;
  border-radius: 20px;
}

.menu[hidden] {
  display: none;
}

/* The glass of the first screen goes once you have come in: the nav has its own. */
.veil.is-nav {
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 420ms var(--ease),
    visibility 0s 420ms;
}

html.is-in .veil {
  visibility: hidden;
}

/* ------------------------------------------------------------------------------------------ */
/* The wall */

.viewport {
  position: fixed;
  inset: 0;
  overflow: hidden;
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}

html.is-dragging .viewport {
  cursor: grabbing;
}

.viewport canvas {
  display: block;
}

/* ------------------------------------------------------------------------------------------ */
/* A card's face in HTML, for reading (ui/CardFace.tsx): the same millimetres as its painted 3D
   face (world/faces.ts). --mm is CSS px per millimetre. */

.face {
  position: relative;
  overflow: hidden;
  background: #fcfcfb;
  color: var(--ink);
  font-size: calc(var(--mm) * 4);
  line-height: 1.4;
  box-shadow: var(--shadow-lift);
}

.face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.face .label {
  font-size: calc(var(--mm) * 2.8);
  color: var(--ink-3);
}

.face__door {
  position: absolute;
  top: calc(var(--mm) * 8);
  right: calc(var(--mm) * 8);
  padding: calc(var(--mm) * 1) calc(var(--mm) * 2.5);
  border-radius: 999px;
  background: var(--blue-50);
  color: var(--blue-700) !important;
}

/* As on the wall (faces.ts, `frost`): clean cool white to the palest blue, light from the top left. */
.face--acrylic {
  background:
    radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0) 90%),
    linear-gradient(160deg, rgba(253, 254, 255, 0.96), rgba(238, 246, 252, 0.96));
  border: 1px solid rgba(255, 255, 255, 0.95);
  box-shadow: 0 4px 12px rgba(16, 42, 67, 0.08), inset 0 -1px 0 rgba(16, 42, 67, 0.06);
  border-radius: calc(var(--mm) * 0.6);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.face--board {
  border-radius: calc(var(--mm) * 0.3);
}

.face--question,
.face--insight,
.face--note {
  padding: calc(var(--mm) * 9);
}

.face--question.is-large,
.face--insight.is-large {
  padding: calc(var(--mm) * 12);
}

.face--question,
.face--section {
  display: flex;
  flex-direction: column;
}

/* A section card: its number and name at the head, one line set large at the foot, on paper
   printed with the brand book's linear dots (blue dots on white, every 3 mm). */
.face--section {
  padding: calc(var(--mm) * 14);
  background-color: #fcfcfb;
  background-image: radial-gradient(circle, rgba(88, 202, 255, 0.7) calc(var(--mm) * 0.32), transparent calc(var(--mm) * 0.4));
  background-size: calc(var(--mm) * 3) calc(var(--mm) * 3);
}

.face--section.is-a3 {
  padding: calc(var(--mm) * 20);
}

/* A notebook page (as on the wall, faces.ts): pale blue rules 9 mm apart, a warm margin line. */
.face.is-ruled {
  padding-left: calc(var(--mm) * 36);
  background:
    linear-gradient(to right, transparent calc(var(--mm) * 30 - 1px), rgba(255, 126, 76, 0.5) calc(var(--mm) * 30 - 1px), rgba(255, 126, 76, 0.5) calc(var(--mm) * 30), transparent calc(var(--mm) * 30)),
    repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--mm) * 9 - 1px), rgba(88, 202, 255, 0.55) calc(var(--mm) * 9 - 1px), rgba(88, 202, 255, 0.55) calc(var(--mm) * 9)) 0 calc(var(--mm) * 17) / 100% calc(100% - var(--mm) * 17) no-repeat,
    #fcfcfb;
}

/* A transparent layer over the card, whole, small in its top right corner (as on the wall). */
.face .face__overlay {
  position: absolute;
  top: calc(var(--mm) * 17);
  right: calc(var(--mm) * 20);
  width: 30%;
  height: auto;
  object-fit: contain;
}

.face--section.is-a3 .face__tag {
  font-size: calc(var(--mm) * 4.2);
}

.face--section.is-a3 .face__question {
  font-size: calc(var(--mm) * 32);
}

.face--section .face__tag,
.face--invite.is-large .face__tag {
  font-size: calc(var(--mm) * 3.2);
}

.face__section {
  margin-left: 1.6em;
}

.face--section .face__question {
  font-size: calc(var(--mm) * 22);
}

/* The question set large and anchored to the foot of the card, the tag at its head. */
.face__question {
  margin: auto 0 0;
  font-size: calc(var(--mm) * 10.5);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: -0.012em;
}

.face--question.is-large {
  padding: calc(var(--mm) * 14);
}

.face--question.is-large .face__question {
  font-size: calc(var(--mm) * 20);
}

/* Words on one line as large as the card is wide (`large`: the "What we build" cards), the size the
   wall's face fits them to. */
.face.is-words-large .face__question {
  font-size: calc(var(--mm) * 21.25);
  white-space: nowrap;
}

.face--insight,
.face--note {
  display: flex;
  flex-direction: column;
}

/* As a question: the tag at the head, the words anchored to the foot. */
.face--insight .face__title,
.face--note .face__title {
  display: block;
  margin-top: auto;
  font-size: calc(var(--mm) * 9.5);
  line-height: 1.06;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.face--insight.is-large .face__title {
  font-size: calc(var(--mm) * 11);
}

.face__text {
  display: block;
  margin-top: calc(var(--mm) * 3);
  color: var(--ink-2);
}

.face--insight .face__text {
  font-size: calc(var(--mm) * 5);
  line-height: 1.32;
}

.face--insight.is-large .face__text {
  font-size: calc(var(--mm) * 5.6);
}

/* A stage's brushstroke illustration (world/brush.ts), filling the space between its tag and its
   words, as on the wall. */
.face__art {
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  margin: calc(var(--mm) * 2) 0 calc(var(--mm) * 3);
  object-fit: contain;
}

/* The foot card's words, as on the wall (faces.ts): two lines, set large (their size and spacing
   from `ruledType`, inline), the second in NOVUS blue; the invitation under them in small spaced
   capitals (the user, 2026-10-25: "bigger font size, give it some typographic treatment", "the wall
   isnt finished in pp neue montreal"). */
.face.is-ruled .face__title {
  font-weight: 500;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.face.is-ruled .face__title > span {
  display: block;
}

.face.is-ruled .face__title > span + span {
  color: var(--blue-700);
}

.face.is-ruled .face__text {
  margin-top: calc(var(--mm) * 9);
  font-size: calc(var(--mm) * 4.4);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.face--photo,
.face--film,
.face--feature.is-print {
  display: flex;
  flex-direction: column;
  /* A thin border, as on the wall (faces.ts, BORDER). */
  padding: calc(var(--mm) * 2) calc(var(--mm) * 2) 0;
}

.face--photo .face__img,
.face--film .face__img,
.face--feature.is-print .face__img {
  position: relative;
  flex: 1;
  min-height: 0;
}

.face__band,
.face--feature.is-print .face__body {
  display: block;
  height: calc(var(--mm) * 13);
  padding-top: calc(var(--mm) * 2.4);
}

.face__caption {
  display: block;
  font-size: calc(var(--mm) * 3.2);
  line-height: 1.2;
}

.face__play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--mm) * 18);
  height: calc(var(--mm) * 18);
  margin: calc(var(--mm) * -9);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.95);
}

.face__play::after {
  content: "";
  position: absolute;
  left: 40%;
  top: 30%;
  border-style: solid;
  border-width: calc(var(--mm) * 3.6) 0 calc(var(--mm) * 3.6) calc(var(--mm) * 6);
  border-color: transparent transparent transparent var(--blue-700);
}

.face__soon {
  float: right;
}

/* A sheet trimmed square to its photograph and words: the words anchored to its foot. */
.face--feature:not(.is-print) {
  display: flex;
  flex-direction: column;
  padding: calc(var(--mm) * 5);
}

/* The photograph fills the sheet down to just above its words (faces.ts, `featureWords`). */
.face--feature:not(.is-print) .face__img {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
}

.face--feature:not(.is-print) .face__body {
  display: block;
  margin-top: auto;
  padding-top: calc(var(--mm) * 4);
}

.face--feature .face__title {
  display: block;
  margin-top: calc(var(--mm) * 3);
  font-size: calc(var(--mm) * 6.8);
  line-height: 1.12;
  font-weight: 500;
}

.face--feature.is-print .face__title {
  font-size: calc(var(--mm) * 3.4);
  margin-top: calc(var(--mm) * 1);
}

.face--feature .face__text {
  font-size: calc(var(--mm) * 4);
}

.face__parked {
  display: block;
  margin-top: calc(var(--mm) * 1);
}

/* The finished thing: its photograph full bleed on a large board, its name set large in white
   across the foot over a soft fade, the way into its page in a white pill at the bottom right (as
   its painted face, world/faces.ts). */
.face--product {
  padding: 0;
}

.face--product .face__img {
  position: absolute;
  inset: 0;
  height: 100%;
}

.face--product::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(1, 43, 69, 0) 38%, rgba(1, 43, 69, 0.66));
}

.face--product .face__body {
  position: absolute;
  z-index: 1;
  left: calc(var(--mm) * 16);
  right: calc(var(--mm) * 16);
  bottom: calc(var(--mm) * 16);
  display: block;
  color: #fff;
}

.face--product .face__tag {
  font-size: calc(var(--mm) * 3.8);
  color: rgba(255, 255, 255, 0.85);
}

.face--product .face__door {
  z-index: 1;
  top: auto;
  bottom: calc(var(--mm) * 16);
  right: calc(var(--mm) * 16);
  font-size: calc(var(--mm) * 3.6);
  background: rgba(255, 255, 255, 0.9);
}

.face__name {
  display: block;
  margin-top: calc(var(--mm) * 2);
  font-size: calc(var(--mm) * 12);
  line-height: 1.1;
  font-weight: 500;
}

.face--product .face__name {
  font-size: calc(var(--mm) * 44);
  line-height: 0.94;
  letter-spacing: -0.02em;
}

.face--product .face__text {
  display: block;
  max-width: 70%;
  font-size: calc(var(--mm) * 8.5);
  line-height: 1.25;
  margin-top: calc(var(--mm) * 5);
  color: rgba(255, 255, 255, 0.92);
}

/* ------------------------------------------------------------------------------------------ */
/* Hint */

.hint {
  padding: 10px 16px;
  border-radius: 16px;
  background: rgba(251, 252, 253, 0.8);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  position: fixed;
  z-index: 5;
  left: 50%;
  bottom: 32px;
  margin: 0;
  transform: translateX(-50%);
  text-align: center;
  color: var(--blue-700);
  pointer-events: none;
  transition: opacity 400ms var(--ease);
  /* As written, not in capitals (the user, 2026-10-27: "dont keep all caps"). */
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

.hint span {
  display: inline-block;
  margin-top: 6px;
  color: var(--ink-3);
}

.hint.is-gone {
  opacity: 0;
}

/* ------------------------------------------------------------------------------------------ */
/* Lifted */

.lift {
  position: fixed;
  inset: 0;
  z-index: 25;
}

.lift[hidden] {
  display: none;
}

.lift__catch {
  position: absolute;
  inset: 0;
  background: rgba(251, 252, 253, 0.35);
}

.lift__card {
  position: absolute;
  transform-origin: 50% 50%;
  perspective: 1600px;
  outline: none;
  cursor: pointer;
}

.lift__inner {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 600ms var(--ease);
}

.lift__card.is-flipped .lift__inner {
  transform: rotateY(180deg);
}

.lift__front,
.lift__back {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* The back may need more room than the front: it grows evenly above and below it. */
.lift__back {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  min-height: 100%;
  max-height: calc((100vh - 140px) / var(--s));
  overflow: auto;
  transform: translateY(-50%) rotateY(180deg);
  padding: calc(24px / var(--s)) calc(26px / var(--s));
  background: #fff;
  box-shadow: var(--shadow-lift);
  font-size: calc(17px / var(--s));
  line-height: 1.45;
  color: var(--ink-2);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 0;
}

.lift__back .label {
  font-size: calc(11px / var(--s));
}

.back__meta {
  margin: 0 0 0.8em;
  color: var(--blue-700);
}

.back__title {
  margin: 0 0 0.4em;
  font-size: calc(28px / var(--s));
  letter-spacing: -0.01em;
  line-height: 1.2;
  font-weight: 500;
  color: var(--ink);
}

.back__text {
  margin: 0 0 0.6em;
}

.back__label {
  margin: 1.2em 0 0.3em;
  color: var(--ink-3);
}

.back__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.back__link {
  padding: 1px 0;
  border: 0;
  background: none;
  color: var(--blue-700);
  font-size: inherit;
  text-align: left;
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 2px;
  cursor: pointer;
}

/* Why the thread runs there: under the card it runs to. */
.back__why {
  display: block;
  margin: 0.1em 0 0.7em;
  font-size: calc(15px / var(--s));
  line-height: 1.4;
  color: var(--ink-2);
}

.lift__hint {
  position: absolute;
  left: 50%;
  bottom: 28px;
  margin: 0;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 32px);
  text-align: center;
  color: var(--blue-700);
}

/* ------------------------------------------------------------------------------------------ */
/* The footer: under the foot of the wall, coming up over it (ui/Footer.tsx). */

.foot {
  position: relative;
  z-index: 6;
  background: var(--wall);
  /* The page's white runs on a little under the footer (a shadow, so it adds no scroll): nothing of
     the wall shows below it in a rounding pixel at the end. */
  box-shadow: 0 48px 0 var(--wall);
}

.foot__inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 80px 32px 56px;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  row-gap: 72px;
}

/* The lab's line, and under it the region (ui/RegionPicker.tsx). */
.foot__lead {
  grid-column: 1 / span 5;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 28px;
}

.foot__line {
  max-width: 22ch;
  margin: 0;
  font-size: 20px;
  line-height: 1.25;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--ink-3);
  text-wrap: balance;
}

.foot__brand {
  color: var(--ink);
}

/* Three columns, each under its label, so every label sits on one line and every column's first
   entry on the next (the user, 2026-10-25: "aligment fully off!!!", when only Follow and Contact
   had labels): the products, where to follow the lab, and Hero MotoCorp and VIDA. Each as wide as
   its words, a set gap apart, not spread across the half (the user, 2026-10-28: "reduce spacing
   here"), and against the right margin, so the footer's edges match on both sides ("left and
   right padding should be equal"). */
.foot__cols {
  grid-column: 7 / -1;
  display: grid;
  grid-template-columns: repeat(4, max-content);
  justify-content: end;
  column-gap: 64px;
  font-size: 14px;
  line-height: 1.2;
}

.foot__col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: var(--ink);
}

.foot__col a {
  width: max-content;
  color: var(--ink);
  text-decoration: none;
  transition: color 150ms;
}

.foot__col a:hover,
.foot__link:hover {
  color: var(--blue-700);
}

/* A link that opens the board rather than an address, set as the links are. */
.foot__link {
  width: max-content;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: color 150ms;
}

.foot__head {
  margin: 0 0 4px;
  font-size: 11px;
  line-height: 1;
  color: var(--ink-3);
}

/* The lab's mark, under the line. */
.foot__mark {
  grid-column: 1 / span 2;
  width: 88px;
  height: 88px;
  margin: -12px 0 -16px -12px;
}

/* Along the foot, the brand's pale blue coming up out of the page (the user, 2026-10-25: "use the
   pale blue for the gradient"; it ran on into NOVUS blue and violet, with the words in white), with
   © and the policies in ink. No rule. */
.foot__band {
  background: linear-gradient(to bottom, var(--wall) 0%, var(--blue-50) 45%, var(--blue-100) 100%);
}

.foot__band-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 88px 32px 26px;
  display: flex;
  justify-content: space-between;
  gap: 16px 32px;
  font-size: 13px;
  color: var(--ink-2);
}

.foot__policies {
  display: flex;
  gap: 28px;
}

.foot__policies a {
  color: inherit;
  text-decoration: none;
  transition: color 150ms;
}

.foot__policies a:hover {
  color: var(--blue-700);
}

/* The two sides of the columns (the lab's pages; where to go outside it): on a wide screen the
   three columns go across as one row. */
.foot__side {
  display: contents;
}

.foot__col--products {
  order: 1;
}

.foot__col--collaborate {
  order: 2;
}

.foot__col--follow {
  order: 3;
}

.foot__col--visit {
  order: 4;
}

/* Between a phone and a wide screen (the user, 2026-11-03: "spacing on the footer at this
   breakpoint": at 768 px the four columns, 64 px apart, ran left into the line): the mark, then
   the line and the region across, the region against the right margin level with the line ("add the
   language selector to the right hand side aligned to the novus labs text"), and under them the
   four columns across the whole width, one to each quarter of the grid. */
@media (min-width: 768px) and (max-width: 1199px) {
  .foot__inner {
    row-gap: 56px;
  }

  /* The same four quarters as the columns under it, so the region starts where Visit does ("align
     the picker to the visit"). */
  .foot__lead {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: center;
    gap: 32px;
  }

  .foot__line {
    grid-column: 1 / span 3;
  }

  .foot__lead .dropbtn {
    grid-column: 4;
    justify-self: start;
  }

  /* The mark over the line, as on a phone (the user, 2026-11-03, from a screenshot). */
  .foot__mark {
    order: -1;
    width: 48px;
    height: 48px;
    margin: 0 0 -20px -6px;
  }

  /* On the right, its list opens from its right edge, so it stays on the screen. */
  .foot__lead .dropbtn__panel {
    left: auto;
    right: 0;
    transform-origin: top right;
  }

  .foot__line {
    max-width: 28ch;
  }

  .foot__cols {
    grid-column: 1 / -1;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    justify-content: stretch;
    column-gap: 32px;
  }
}

/* On a phone (the user, 2026-10-26: "footer needs work": a grid of two left Visit on its own and
   the gaps wide; then a table of labels beside links, "footer terrible!!"): the mark small over the
   line, then two columns of the groups as on a wide screen, label over links, the lab's own pages
   on the left and Follow and Visit on the right, so none is left alone; the band tight,
   clear of the phone's home bar. */
@media (max-width: 767px) {
  .foot__inner {
    grid-template-columns: minmax(0, 1fr);
    padding: 48px 16px 40px;
    row-gap: 32px;
  }

  .foot__mark {
    order: -1;
    width: 48px;
    height: 48px;
    margin: 0 0 -16px -6px;
  }

  .foot__lead {
    grid-column: 1 / -1;
    gap: 20px;
  }

  .foot__line {
    font-size: 18px;
  }

  .foot__cols {
    grid-column: 1 / -1;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 32px 24px;
  }

  /* Two rows, so the second row's labels line up across (the user, 2026-11-02: "align these"):
     Products and Follow, then Collaborate and Visit. */
  .foot__col--follow {
    order: 2;
  }

  .foot__col--collaborate {
    order: 3;
  }

  .foot__band-inner {
    flex-direction: column;
    gap: 10px;
    padding: 48px 16px calc(20px + env(safe-area-inset-bottom));
    font-size: 12px;
  }

  .foot__policies {
    flex-wrap: wrap;
    gap: 8px 20px;
  }
}

/* ------------------------------------------------------------------------------------------ */
/* The pages (stubs) */

.page {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: var(--wall);
}

/* The print becomes the page: the card's photograph travelling between the wall and the page's
   image (ui/PageView.tsx). The page's words wait, then rise in as it lands. */
.page__travel {
  position: fixed;
  z-index: 41;
  overflow: hidden;
  visibility: hidden;
  pointer-events: none;
  transform-origin: 50% 50%;
}

.page__travel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.page__heading,
.page__body {
  transition: opacity 420ms var(--ease), transform 640ms var(--ease);
}

.page__top::after {
  transition: opacity 420ms var(--ease);
}

.page.is-arriving .page__heading,
.page.is-arriving .page__body {
  opacity: 0;
  transform: translateY(24px);
}

.page.is-arriving .page__top::after {
  opacity: 0;
}

.page.is-still .page__heading,
.page.is-still .page__body,
.page.is-still .page__top::after {
  transition: none;
}

.page[hidden] {
  display: none;
}

.page__scroll {
  position: relative;
  height: 100%;
  overflow: auto;
  /* Up and down only: the story's photographs bleed to the edge and wipe in from beyond it, which
     would otherwise let a finger on an iPad pan the page sideways. */
  overflow-x: hidden;
  outline: none;
  /* The story's photographs are sized to the page's width (cqw), not the viewport's (vw counts
     the scrollbar). */
  container-type: inline-size;
}

.page__top {
  position: relative;
  min-height: 62vh;
  display: flex;
  align-items: flex-end;
  padding: 120px 32px 48px;
  background:
    radial-gradient(60% 80% at 70% 20%, rgba(195, 232, 255, 0.7), rgba(231, 246, 255, 0) 70%),
    #fff;
}

.page--image .page__top {
  min-height: 78vh;
  color: #fff;
}

.page__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.page--image .page__top::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(1, 43, 69, 0.55), rgba(1, 43, 69, 0) 55%);
}

.page__heading {
  position: relative;
  z-index: 1;
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
}

.page__tag {
  margin: 0 0 12px;
  color: var(--blue-700);
}

.page--image .page__tag {
  color: #fff;
}

.page__title {
  margin: 0;
  font-size: 80px;
  line-height: 1.05;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.page__lede {
  margin: 16px 0 0;
  font-size: 20px;
  line-height: 1.5;
}

.page__body {
  max-width: 1280px;
  margin: 0 auto;
  padding: 64px 32px 128px;
}

.page__body > section + section {
  margin-top: 112px;
}

.page__eyebrow {
  margin: 0 0 20px;
  color: var(--blue-700);
}

.page__statement {
  max-width: 22ch;
  text-wrap: balance;
  margin: 0;
  font-size: 44px;
  line-height: 1.12;
  font-weight: 500;
  letter-spacing: -0.015em;
}

.page__intro .page__statement,
.page__products .page__statement {
  max-width: 26ch;
}

.page__photo {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  background: var(--blue-50);
}

/* A product page opens on a banner: its photograph edge to edge (the print from its card on the
   wall travels into it), its name and line set over it. */
.page--product .page__top {
  min-height: 82vh;
  padding: 120px max(32px, calc((100% - 1216px) / 2)) 64px;
}

.page--product .page__heading {
  margin: 0;
}

.page--product .page__title {
  font-size: 104px;
}

.page--product .page__lede {
  max-width: 22ch;
  margin-top: 16px;
  font-size: 32px;
  line-height: 1.15;
  font-weight: 500;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

/* A product's story (the user, 2026-10-22, after tengilemalamala.com and their moodboard): the
   overview on a sheet of frosted glass, an index of its lane from the wall, then each feature on a
   12-column grid, its words set large and its name set across its photograph. */

/* The banner holds still while, on a product's page, a sheet of the wall's frosted glass rises over
   it carrying the overview (the user, 2026-10-22, from the moodboard's "A long way of
   rediscovering"); once the sheet is up the two go on together: the banner is sticky inside .hero,
   which ends where the sheet does. As the glass comes up the banner's words and shade go
   (ui/storyMotion.ts sets --hero-words), so the glass lies over the photograph alone. */
.hero {
  position: relative;
}

.page--product .page__top {
  position: sticky;
  top: 0;
}

.page.has-motion:not(.is-arriving) .page__heading {
  opacity: var(--hero-words, 1);
  transform: translateY(calc((1 - var(--hero-words, 1)) * -40px));
}

.page.has-motion:not(.is-arriving) .page__top::after {
  opacity: var(--hero-words, 1);
}

/* As the glass comes up, the banner's foot fades into the page, so where the photograph ends never
   shows, through the glass or beside it (the user: "overlaps and end state looks really bad"). */
.page__fade {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(251, 252, 253, 0) 40%, rgba(251, 252, 253, 0.7) 72%, var(--wall) 96%);
  pointer-events: none;
}

.page.has-motion .page__fade {
  opacity: calc(1 - var(--hero-words, 1));
}

/* The sheet: a panel of the wall's own frosted glass (the veil over the wall on the first screen),
   set in from the page's edges with round corners (the user: "give padding and rounded radius"),
   clear enough that the banner shows through (the user: "the glass can be more transparent"),
   blurred enough that it reads as light and colour behind the words; light across its face, a hairline at its edge, and toward its foot it settles
   into the page. Just the words on it. */
.sheet {
  position: relative;
  z-index: 1;
  margin: 0 32px;
  padding: 112px max(48px, calc((100% - 1216px) / 2)) 128px;
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 28px;
  background: linear-gradient(to bottom, rgba(247, 250, 253, 0.4), rgba(245, 249, 252, 0.56) 55%, rgba(251, 252, 253, 0.9));
  -webkit-backdrop-filter: blur(30px) saturate(1.15);
  backdrop-filter: blur(30px) saturate(1.15);
}

.sheet::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(112deg, rgba(255, 255, 255, 0) 24%, rgba(255, 255, 255, 0.14) 36%, rgba(255, 255, 255, 0) 48%, rgba(255, 255, 255, 0.07) 68%, rgba(255, 255, 255, 0) 80%);
  pointer-events: none;
}

/* The headline at the head, the paragraph lower and to the right. */
.sheet__inner {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  row-gap: 72px;
}

/* One sentence, flowing (the user: "why are we dividing this into two lines like this?"): the
   first part in ink, the rest in blue, both PP Neue Montreal (Milling was tried on the blue part
   and turned down: "change this back to pp neue montreal"). */
.sheet__headline {
  grid-column: 1 / span 8;
  margin: 0;
  font-size: 72px;
  line-height: 1.04;
  font-weight: 500;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

/* A tablet: the full width, a step smaller, so it doesn't break into short lines down a narrow
   column (the user, 2026-10-29: "on tablet the text shouldnt get cut off like this"). */
@media (max-width: 1199px) {
  .sheet__headline {
    grid-column: 1 / -1;
    font-size: 60px;
  }
}

.sheet__blue {
  color: var(--blue-700);
}

.sheet__words {
  grid-column: 8 / -1;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.sheet__text {
  max-width: 40ch;
  margin: 0;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-2);
}

.sheet__more {
  align-self: flex-start;
  display: inline-flex;
  gap: 8px;
  font-size: 15px;
  color: var(--blue-700);
  text-decoration: none;
}

.sheet__more:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* A product's wordmark in the words (its name, as the NOVUS site draws it): its shape, in their
   colour, at their capital height. */
.logo {
  display: inline-block;
  height: 0.72em;
  vertical-align: baseline;
  background-color: currentColor;
  -webkit-mask: var(--logo) no-repeat center / contain;
  mask: var(--logo) no-repeat center / contain;
}

/* Words that rise in as the glass comes up (ui/storyMotion.ts sets --in, 0 to 1). */
[data-rise] {
  opacity: var(--in, 1);
  transform: translateY(calc((1 - var(--in, 1)) * 28px));
}

/* Its lane from the wall, as an index: where it started, set large on the left, and each step on
   a numbered row on the right with why the thread runs there; a row takes you to its feature. */
.index {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  scroll-margin-top: 80px;
}

.index__start {
  grid-column: 1 / span 6;
}

.index__steps {
  grid-column: 8 / -1;
}

.index__question {
  max-width: 16ch;
  margin: 0;
  font-size: 56px;
  line-height: 1.04;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.index__back {
  max-width: 34ch;
  margin: 32px 0 0;
  font-size: 22px;
  line-height: 1.4;
  color: var(--ink-3);
}

.index__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.index__row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  column-gap: 12px;
  row-gap: 6px;
  padding: 20px 0;
  color: inherit;
  text-decoration: none;
}

.index__no {
  grid-row: 1 / span 2;
  padding-top: 6px;
  font-size: 15px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.index__name {
  font-size: 24px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -0.01em;
  transition: color 200ms var(--ease);
}

.index__why {
  grid-column: 2;
  max-width: 40ch;
  font-size: 15px;
  line-height: 1.45;
  color: var(--blue-700);
}

a.index__row:hover .index__name {
  color: var(--blue-700);
}

/* Each feature: no rule above it (the user, 2026-10-25: "remove these faint lines!!! how many
   times do i tell"), a large light numeral (the one light weight on the page) on the left, a small label and its words set large on the right, the first sentence in ink and the
   rest grey; then its photograph, a tall print hard left or a smaller one hard right. */
.story__step {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  margin-top: 136px;
  scroll-margin-top: 80px;
}

.story__block {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  padding-top: 24px;
}

/* The numerals in Milling (the user, 2026-10-22), the brand's engraved line. */
.story__number {
  grid-column: 1 / span 4;
  margin: -4px 0 0;
  font-family: var(--milling);
  font-size: 128px;
  line-height: 0.8;
  font-weight: 400;
  letter-spacing: 0;
}

.story__words {
  grid-column: 6 / -1;
}

.story__label {
  margin: 0 0 28px;
  color: var(--blue-700);
}

.story__lead {
  max-width: 30ch;
  margin: 0;
  font-size: 34px;
  line-height: 1.18;
  font-weight: 500;
  letter-spacing: -0.012em;
  text-wrap: pretty;
}

.story__quiet {
  color: var(--ink-3);
}

/* Grey to ink, word by word, as the words come up the screen (the user, 2026-10-23: "this can
   become black on scroll from grey"; storyMotion sets --ink-in, 0 to 1). */
.has-motion .story__word {
  color: color-mix(in srgb, var(--ink) calc(var(--ink-in, 0) * 100%), var(--ink-3));
}

/* Each photograph three quarters of the page wide (the user, 2026-10-22: "3/4th screen not
   1/4th"), run off the page's outer edge: hard left, then hard right. Its name set large across
   it: the same line twice, in the same place, one in ink behind the print and one in white inside
   it (clipped by the print's edge), so it reads ink on the page and white where it crosses the
   photograph. Both are placed from the print's outer edge, so they line up; most of the name
   sits on the print, the rest runs out past its inner edge. */
.story__figure {
  --bleed: 24px;
  --frame-w: 75cqw;
  --name-size: clamp(56px, 7cqw, 120px);
  --name-w: min(50cqw, 780px);
  --name-x: calc(var(--frame-w) - var(--name-w) * 0.6);
  position: relative;
  display: flex;
  margin: 0;
  transform-origin: 0 0;
  will-change: transform;
}

/* The page's full width, still: it clips the print where it runs --bleed past the page's edge
   (sideways only), so the print can sway without a gap showing at the edge. */
.story__bleed {
  grid-column: 1 / -1;
  width: 100cqw;
  margin: 112px 0 0 calc(50% - 50cqw);
  overflow-x: clip;
}

.story__step--right .story__figure {
  justify-content: flex-end;
  transform-origin: 100% 0;
}

.story__frame {
  position: relative;
  z-index: 1;
  flex: none;
  width: calc(var(--frame-w) + var(--bleed));
  height: min(calc(var(--frame-w) * 0.66), 88vh);
  overflow: hidden;
  background: var(--blue-50);
  will-change: transform;
}

/* What the frame shows: held still while the frame wipes in over it (ui/storyMotion.ts moves the
   two against each other), so the photograph is uncovered from the outer edge, not slid in. */
.story__reveal {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.story__reveal::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(1, 43, 69, 0.5), rgba(1, 43, 69, 0) 60%);
  pointer-events: none;
}

.story__step--left .story__frame {
  margin-left: calc(-1 * var(--bleed));
  border-radius: 0 var(--radius) var(--radius) 0;
}

.story__step--right .story__frame {
  margin-right: calc(-1 * var(--bleed));
  border-radius: var(--radius) 0 0 var(--radius);
}

/* The picture is a little taller than its frame and drifts slower than it. */
.story__photo {
  position: absolute;
  top: -8%;
  left: 0;
  display: block;
  width: 100%;
  height: 116%;
  will-change: transform;
}

.story__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.story__name {
  position: absolute;
  z-index: 0;
  bottom: 48px;
  width: max-content;
  margin: 0;
  font-size: var(--name-size);
  line-height: 0.94;
  font-weight: 500;
  letter-spacing: -0.035em;
  pointer-events: none;
  will-change: transform;
}

.story__line {
  display: block;
  width: max-content;
  white-space: nowrap;
}

.story__step--right .story__line {
  margin-left: auto;
}

/* On the page the name is in Milling, on the photograph in PP Neue Montreal (the user,
   2026-10-22). Each Milling letter is centred in the slot its Montreal letter takes, and the copy
   sits on the Montreal baseline (ui/storyMotion.ts), so they meet at the photograph's edge. */
.story__figure > .story__name {
  font-family: var(--milling);
  font-weight: 400;
  letter-spacing: 0;
}

.story__ch {
  display: inline-block;
  text-align: center;
}

/* Where a line's baseline is, to set the two copies on the same one. */
.story__base {
  display: inline-block;
  width: 0;
  height: 0;
}

.story__name--on {
  z-index: 1;
  color: #fff;
}

.story__step--left .story__name {
  left: var(--name-x);
}

.story__step--right .story__name {
  right: var(--name-x);
  text-align: right;
}

/* The white copy sits in the frame, which starts --bleed past the page's edge. */
.story__step--left .story__name--on {
  left: calc(var(--name-x) + var(--bleed));
}

.story__step--right .story__name--on {
  right: calc(var(--name-x) + var(--bleed));
}

/* Each block of words rises in once, the first time it comes into view. */
.page.has-motion .story__block {
  transition: opacity 700ms var(--ease), transform 900ms var(--ease);
}

.page.has-motion .story__block:not(.is-in) {
  opacity: 0;
  transform: translateY(32px);
}

/* ------------------------------------------------------------------------------------------ */
/* Lab marks on a product's page (ui/PageView.tsx; the user, 2026-10-23: "more annotations and lab
   marks like this inside the product pages", like the wall's "{04} WHAT WE BUILD"). */

/* A section's number in braces and its name, at its head. */
.lab-tag {
  display: flex;
  gap: 1.6em;
  margin: 0 0 40px;
  color: var(--ink-3);
}

.sheet__tag {
  grid-column: 1 / -1;
  margin: -48px 0 -24px;
}

.story__tag {
  margin: 136px 0 -96px;
}

.lineup .lab-tag {
  margin-bottom: 32px;
}

/* Its figure number, in the photograph's outer top corner. */
.story__fig {
  position: absolute;
  z-index: 1;
  top: 20px;
  margin: 0;
  color: #fff;
  text-shadow: 0 1px 6px rgba(1, 43, 69, 0.45);
}

.story__step--left .story__fig {
  left: calc(var(--bleed) + 24px);
}

.story__step--right .story__fig {
  right: calc(var(--bleed) + 24px);
}

/* Crop marks at its inner corners. No tape over its corner (the user, 2026-10-27: "remove the
   tape not the crop rulers"). */
.story__crop {
  position: absolute;
  z-index: 2;
  width: 18px;
  height: 18px;
  border-color: var(--ink-3);
  border-style: solid;
  border-width: 0;
  pointer-events: none;
}

.story__crop--top {
  top: -14px;
}

.story__crop--bottom {
  bottom: -14px;
}

.story__step--left .story__crop {
  left: calc(var(--frame-w) + 6px);
}

.story__step--right .story__crop {
  right: calc(var(--frame-w) + 6px);
}

.story__step--left .story__crop--top {
  border-width: 0 0 1px 1px;
}

.story__step--left .story__crop--bottom {
  border-width: 1px 0 0 1px;
}

.story__step--right .story__crop--top {
  border-width: 0 1px 1px 0;
}

.story__step--right .story__crop--bottom {
  border-width: 1px 1px 0 0;
}

@media (max-width: 767px) {
  /* The photograph runs the column's width, so its inner edge is the column's: there the marks
     are short ticks above and below the corner, in line with the edge, inside the page (the user,
     2026-10-26: "the drawing lines breaking on mobile"; set by the wide screen's 3/4 frame, they
     stood in the middle of the photograph). */
  .story__crop {
    width: 0;
    height: 12px;
  }

  .story__crop--top {
    top: -20px;
  }

  .story__crop--bottom {
    bottom: -20px;
  }

  .story__step--left .story__crop {
    left: auto;
    right: 0;
  }

  .story__step--right .story__crop {
    right: auto;
    left: 0;
  }

  .story__step--left .story__crop--top,
  .story__step--left .story__crop--bottom {
    border-width: 0 1px 0 0;
  }

  .story__step--right .story__crop--top,
  .story__step--right .story__crop--bottom {
    border-width: 0 0 0 1px;
  }
}

/* The end of a product's page: the site's last line on one line, then all three products as large
   editorial cards, just their photographs (the user, 2026-10-22: no names, lines or links on
   them); the other two are ways in. Laid out as the user's mock (2026-10-23, "use this layout for
   the next cards"): the line large, no rule above it, and the cards across the whole page, 8 px in
   from its edges and 6 px apart (out of the column: `cqw` is `.page__scroll`'s width). */
.page__body > section.lineup {
  margin-top: 136px;
}

.lineup .page__closing {
  max-width: none;
  margin-top: 0;
  font-size: clamp(36px, 5.3vw, 76px);
  line-height: 1.05;
}

.lineup__row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  width: calc(100cqw - 16px);
  margin-top: 40px;
  margin-left: calc(50% - 50cqw + 8px);
}

.lineup__card {
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
}

.lineup__photo {
  position: relative;
  display: block;
  aspect-ratio: 482 / 588;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--blue-50);
}

.lineup__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 900ms var(--ease);
}

a.lineup__card:hover .lineup__photo img {
  transform: scale(1.03);
}

.page.has-motion .lineup {
  transition: opacity 700ms var(--ease), transform 900ms var(--ease);
}

.page.has-motion .lineup:not(.is-in) {
  opacity: 0;
  transform: translateY(32px);
}

/* Pages without a story end on the site's last line and the way on. */
.page__answer .page__next {
  margin-top: 40px;
}

/* The finished things, each a way into its page. */
.page__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
}

.page__products > p + .page__grid {
  margin-top: 48px;
}

.page__product {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  color: inherit;
  text-decoration: none;
}

.page__product .page__photo {
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform 600ms var(--ease);
}

.page__product:hover .page__photo {
  transform: scale(1.015);
}

.page__name {
  margin-top: 20px;
  font-size: 36px;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.page__line {
  margin-top: 6px;
  font-size: 18px;
  color: var(--ink-2);
}

.page__explore {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-top: 20px;
  padding: 0 20px;
  border-radius: 999px;
}

.page__product:hover .page__explore {
  transform: translateY(-1px);
}

.page__product:active .page__explore {
  transform: scale(0.95, 0.92);
  transition-duration: 90ms;
}

.page__closing {
  max-width: 14ch;
  text-wrap: balance;
  margin: 0;
  font-size: 72px;
  line-height: 1.04;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.page__stub {
  margin: 0 0 12px;
  color: var(--ink-3);
}

.page__holds {
  max-width: 640px;
  margin: 0;
  font-size: 20px;
  line-height: 1.5;
  color: var(--ink-2);
}

.page__next {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 48px;
  min-height: 64px;
  padding: 0 30px;
  border-radius: 999px;
  font-size: 24px;
  font-weight: 500;
  text-decoration: none;
}

/* ------------------------------------------------------------------------------------------ */
/* Phone first: one column, branches a swipe to the side. */

@media (max-width: 767px) {
  .page__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }

  .page--product .page__top {
    min-height: 72vh;
    padding: 88px 16px 88px;
  }

  /* The sheet and the story in one column: no stagger; every photograph full width, its name in
     white across its foot. The sheet starts over the banner's foot, so where the photograph ends
     lies under its glass, and its tag inside it (the user, 2026-10-26: "nex 1 hero section
     breaking": the photograph stopped short over the page's white, the tag half over it). */
  .sheet {
    margin: -48px 8px 0;
    padding: 32px 20px 32px;
    border-radius: 20px;
  }

  .sheet__tag {
    margin: 0 0 -8px;
  }

  .sheet__inner {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 32px;
  }

  .sheet__headline {
    font-size: 36px;
  }

  .page__body > section.lineup {
    margin-top: 72px;
  }

  .lineup__row {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
    margin-top: 20px;
  }

  .index,
  .story__step,
  .story__block,
  .story__figure {
    grid-template-columns: minmax(0, 1fr);
  }

  .sheet__headline,
  .sheet__words,
  .index__start,
  .index__steps,
  .story__number,
  .story__words,
  .story__step--left .story__frame,
  .story__step--right .story__frame {
    grid-column: 1 / -1;
  }

  .index {
    row-gap: 56px;
  }

  .index__question {
    font-size: 34px;
  }

  .index__back {
    font-size: 18px;
  }

  .index__name {
    font-size: 20px;
  }

  .story__step {
    margin-top: 80px;
  }

  .story__number {
    margin-bottom: 28px;
    font-size: 88px;
  }

  .story__lead {
    font-size: 26px;
  }

  .story__bleed {
    width: auto;
    margin: 40px 0 0;
  }

  .story__figure {
    --bleed: 0px;
  }

  .story__step--left .story__frame,
  .story__step--right .story__frame {
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 5;
    border-radius: var(--radius);
  }

  .story__figure > .story__name {
    display: none;
  }

  .story__step .story__name--on {
    left: 20px;
    right: 20px;
    bottom: 20px;
    width: auto;
    font-size: clamp(30px, 10vw, 44px);
    text-align: left;
  }

  .story__step .story__name--on .story__line {
    margin-left: 0;
  }

  .page--product .page__title {
    font-size: 56px;
  }

  .page--product .page__lede {
    font-size: 24px;
  }

  .page__statement {
    font-size: 30px;
  }

  .page__closing {
    font-size: 44px;
  }

  /* One space between the sections on a phone, 72 px from one's last line to the next's tag (the
     user, 2026-11-02: "unify it"; they were 72 to 136): between sections, before the lineup, before
     Features and after the sheet (its own foot and the page's top together). */
  .page__body > section + section {
    margin-top: 72px;
  }

  /* Room between the tag and the first feature's numeral (the user, 2026-11-02: "add some space
     between features and the number"; it sat on it). */
  .story__tag {
    margin: 72px 0 -64px;
  }
}

@media (max-width: 767px) {
  /* On a phone: the wordmark and the hamburger, which opens the menu. */
  .nav {
    top: 10px;
  }

  .nav__pill {
    gap: 12px;
    height: 44px;
    padding-left: 18px;
  }

  .nav__group {
    display: none;
  }

  .nav__burger {
    display: inline-flex;
  }

  /* Small and light, on one line (the user, 2026-10-26: "this cant be so big and so bold"). */
  .hint {
    bottom: 24px;
    width: max-content;
    max-width: calc(100vw - 32px);
    padding: 8px 14px;
    border-radius: 12px;
    font-size: 12px;
  }

  .lift__hint {
    bottom: 20px;
  }

  .page__top {
    padding: 96px 16px 32px;
  }

  .page__title {
    font-size: 48px;
  }

  .page__lede {
    font-size: 18px;
  }

  .page__body {
    padding: 48px 16px 96px;
  }

  .page--product .page__body {
    padding-top: 39px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 1ms !important;
  }
}

/* ------------------------------------------------------------------------------------------ */
/* The glass: a sheet of frosted glass over the whole board on the first screen. Scrolling raises
   the sheet (the board under it stays still) until it is the nav bar's glass, where it stays
   (once, on first load: world.cameIn). A little milky: the board comes through as soft light and
   colour, with a little light across its face and a hairline where it ends. */

.veil {
  position: fixed;
  z-index: 28;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  overflow: hidden;
  contain: layout paint;
  /* Frosted glass, a little milky (the user, 2026-10-21: "slightly opaque"): the wall behind
     reads as soft light and colour, not as pictures. A faint cool tint in its thickness. */
  background: linear-gradient(to bottom, rgba(247, 250, 253, 0.6), rgba(240, 246, 252, 0.52));
  backdrop-filter: blur(24px) saturate(1.1);
  -webkit-backdrop-filter: blur(24px) saturate(1.1);
}

/* Light across the face of the sheet. */
.veil::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(112deg, rgba(255, 255, 255, 0) 24%, rgba(255, 255, 255, 0.12) 36%, rgba(255, 255, 255, 0) 48%, rgba(255, 255, 255, 0.06) 68%, rgba(255, 255, 255, 0) 80%);
  pointer-events: none;
}

/* The lower edge: just a hairline where the glass ends. */
.veil__edge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.55);
  pointer-events: none;
}

/* Already in when the page loads (once a session: controller.ts): the glass is the nav bar from the
   first paint, and the welcome never shows. */
html.is-in .veil {
  height: 72px;
}

html.is-in .veil__intro {
  visibility: hidden;
}

/* As the nav bar, a touch more frost so the links read over anything. */
.veil.is-nav {
  background: linear-gradient(to bottom, rgba(250, 252, 254, 0.66), rgba(246, 250, 253, 0.58));
}

.veil__intro {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 100vh;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 28px;
  padding: 24px;
  will-change: transform, opacity;
}

.veil__line {
  max-width: 14ch;
  margin: 0;
  font-family: var(--sans);
  font-size: 84px;
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-align: center;
  color: var(--ink);
}

.veil__hint {
  margin: 0;
  color: var(--blue-700);
}

@media (max-width: 767px) {
  html.is-in .veil {
    height: 60px;
  }

  .veil__line {
    font-size: 46px;
  }
}

/* The blank card: a question at its head, faint rules, and the visitor's words in blue ink. */
.face--invite {
  display: flex;
  flex-direction: column;
  padding: calc(var(--mm) * 9);
}

.face--invite .face__tag {
  color: var(--blue-700);
}

.face__invite {
  margin: calc(var(--mm) * 4) 0 calc(var(--mm) * 4);
  font-size: calc(var(--mm) * 5.6);
  font-weight: 500;
  line-height: 1.12;
}

.face--invite.is-large {
  padding: calc(var(--mm) * 14);
}

.face--invite.is-large .face__invite {
  margin-top: calc(var(--mm) * 8);
  font-size: calc(var(--mm) * 11);
  line-height: 1.08;
  letter-spacing: -0.01em;
}

.face__write {
  flex: 1;
  width: 100%;
  padding: 0;
  border: 0;
  resize: none;
  outline: none;
  background: repeating-linear-gradient(to bottom, transparent 0 calc(var(--mm) * 7.3), rgba(88, 202, 255, 0.35) calc(var(--mm) * 7.3) calc(var(--mm) * 7.5));
  color: var(--blue-700);
  font-family: "Milling Note", var(--milling);
  font-size: calc(var(--mm) * 5.4);
  line-height: calc(var(--mm) * 7.5);
}

.face__write::placeholder {
  color: rgba(7, 116, 184, 0.4);
}

.lift__actions {
  position: absolute;
  left: 50%;
  bottom: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 32px);
}

.lift__pin {
  min-height: 48px;
  padding: 0 28px;
  border: 0;
  border-radius: 999px;
  background: var(--blue-700);
  color: #fff;
  font-weight: 500;
  cursor: pointer;
}

.lift__pin:disabled {
  background: var(--color-disabled-bg, #eeeeee);
  color: var(--ink-3);
  cursor: default;
}

.lift__link {
  color: var(--blue-700);
  text-decoration: none;
}

/* ------------------------------------------------------------------------------------------ */
/* Glass controls: pale blue frosted glass for the page buttons and the phone menu (the user,
   2026-10-21; src/ui/glass.ts). Clear: a blur of what is behind, no tint of its own (the user,
   "remove blue tint, should be transparent"), and a faint hairline edge, flat: no bevel (no light along the top or bottom edge, no bright rim; the user, "remove
   the button bevel"); a highlight that follows the pointer; a small squish when pressed that
   springs back. */
.glass {
  --gx: 50%;
  --gy: 0%;
  isolation: isolate;
  color: var(--blue-700);
  /* A frosted lens (ui/lens.ts sets the bend where the browser can): what is behind bulges a
     little and blurs softly, under a faint milky tint, just a touch more opaque than clear. */
  background:
    radial-gradient(120px circle at var(--gx) var(--gy), rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 70%),
    rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.28);
  box-shadow:
    0 1px 2px rgba(7, 70, 120, 0.06),
    0 8px 24px -12px rgba(7, 70, 120, 0.28);
  transition:
    transform 520ms cubic-bezier(0.34, 1.56, 0.64, 1),
    box-shadow 240ms var(--ease);
  -webkit-tap-highlight-color: transparent;
}

a.glass:hover,
button.glass:hover {
  box-shadow:
    0 1px 2px rgba(7, 70, 120, 0.06),
    0 12px 30px -12px rgba(7, 70, 120, 0.34);
  transform: translateY(-1px);
}

a.glass:active,
button.glass:active {
  transform: scale(0.95, 0.92);
  transition-duration: 90ms;
  transition-timing-function: ease-out;
}

.glass--panel {
  background:
    radial-gradient(220px circle at var(--gx) var(--gy), rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 70%),
    rgba(255, 255, 255, 0.78);
}

.glass--panel a {
  color: var(--blue-700);
}

.glass--panel a:hover,
.glass--panel a:focus-visible {
  background: rgba(255, 255, 255, 0.55);
}

/* What a click does, beside the pointer over a story card (ui/CursorTag.tsx): the same frosted
   lens as the glass controls (ui/lens.ts), flat, no bevel. */
.cursor-tag {
  position: fixed;
  z-index: 5;
  top: 0;
  left: 0;
  padding: 9px 16px;
  border-radius: 999px;
  white-space: nowrap;
  pointer-events: none;
  color: var(--blue-700) !important;
  font-weight: 500;
  background: rgba(255, 255, 255, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 1px 2px rgba(7, 70, 120, 0.06), 0 8px 24px -12px rgba(7, 70, 120, 0.28);
  opacity: 0;
  scale: 0.92;
  transition:
    opacity 220ms var(--ease),
    scale 260ms var(--ease);
}

.cursor-tag.is-on {
  opacity: 1;
  scale: 1;
}

@media (hover: none) {
  .cursor-tag {
    display: none;
  }
}

/* ------------------------------------------------------------------------------------------ */
/* Components: the set picked on the component lab (public/lab/components.html, the user,
   2026-10-29), as React in ui/Button.tsx, ui/Field.tsx, ui/Dropdown.tsx, ui/DropdownButton.tsx and
   ui/Tag.tsx. Change one here and in the lab together. */

/* Buttons: four, all from the wall (the user: five filled colours were "too loud", "too many
   variants", "doesn't match the wall"): solid NOVUS blue for the one thing to do, the region
   picker's white pill, the glass (.glass and its lens, above), and words with an arrow. Pills,
   44 px tall at the least. Hover: a filled one goes darker, one without a fill takes a pale blue
   one. Pressed is only the squish (a step deeper in colour was "i dont like this at all"). Focus
   as the form fields have it: its own edge in the focus blue and a soft halo ("i like the form
   focus state ... for the buttons"); primary, with no edge to turn, only the halo. */
.btn {
  --h: 48px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--h);
  padding: 0 24px;
  border: 0;
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: var(--fs-button);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-button);
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color var(--duration-base) var(--ease-standard),
    color var(--duration-base) var(--ease-standard),
    box-shadow var(--duration-base) var(--ease-standard),
    transform 520ms var(--spring);
}

.btn .icon {
  width: 18px;
  height: 18px;
  vertical-align: 0;
}

.btn:active:not(:disabled) {
  transform: scale(0.97, 0.94);
  transition-duration: 90ms;
  transition-timing-function: ease-out;
}

.btn--sm {
  --h: 44px;
  padding: 0 18px;
  font-size: var(--fs-body-sm);
}

.btn--sm .icon {
  width: 16px;
  height: 16px;
}

.btn--lg {
  --h: 56px;
  padding: 0 32px;
  font-size: 18px;
}

.btn--lg .icon {
  width: 22px;
  height: 22px;
}

.btn--icon {
  width: var(--h);
  padding: 0;
}

.btn--primary {
  background: var(--primary-700);
  color: var(--on-primary);
}

.btn--secondary {
  background: #fff;
  color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--blue-100);
}

.btn--text {
  background: transparent;
  color: var(--blue-700);
}

.btn--text .icon {
  transition: transform var(--duration-base) var(--ease-emphasized);
}

@media (hover: hover) {
  .btn--primary:hover:not(:disabled) {
    background: var(--primary-800);
  }

  .btn--secondary:hover:not(:disabled) {
    background: var(--blue-50);
    box-shadow: inset 0 0 0 1.5px var(--blue-200);
  }

  .btn--text:hover:not(:disabled) {
    background: var(--blue-50);
    color: var(--blue-800);
  }

  .btn--text:not(.btn--icon):hover:not(:disabled) .icon {
    transform: translateX(3px);
  }
}

.btn:focus-visible {
  outline: none;
}

.btn--primary:focus-visible:not(:disabled) {
  box-shadow: 0 0 0 3px rgba(6, 146, 229, 0.35);
}

.btn--secondary:focus-visible:not(:disabled),
.btn--text:focus-visible:not(:disabled) {
  box-shadow: inset 0 0 0 1.5px var(--focus), 0 0 0 3px rgba(6, 146, 229, 0.2);
}

.btn.glass:focus-visible {
  box-shadow: inset 0 0 0 1.5px var(--focus), 0 0 0 3px rgba(6, 146, 229, 0.25), 0 8px 24px -12px rgba(7, 70, 120, 0.28);
}

.btn:disabled {
  background: var(--disabled-bg);
  color: var(--disabled-text);
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  cursor: not-allowed;
}

.btn--text:disabled {
  background: transparent;
}

/* Disabled keeps its kind: secondary stays a white pill with an edge, in grey. */
.btn--secondary:disabled {
  background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--grey-100);
}

.btn[aria-busy="true"] {
  cursor: progress;
}

.btn[aria-busy="true"] > :not(.btn__spinner) {
  opacity: 0;
}

.btn__spinner {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  animation: btn-spin 700ms linear infinite;
}

/* The white pill's spinner in NOVUS blue, not its black words. */
.btn--secondary .btn__spinner {
  border-color: var(--blue-700);
  border-right-color: transparent;
}

@keyframes btn-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Form fields: white on the wall, the region picker's pale blue edge, the label always there; an
   error says what's wrong under its own field, with an icon as well as the colour. */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.field__label {
  padding: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  font-weight: 500;
  color: var(--ink-2);
}

.field__label em {
  font-style: normal;
  font-weight: 400;
  color: var(--ink-3);
}

.field__help {
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  color: var(--ink-3);
}

.field__error {
  display: flex;
  gap: 6px;
  align-items: flex-start;
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  color: var(--error);
}

.field__error .icon {
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 1px;
}

.control {
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  border: 1.5px solid var(--blue-100);
  border-radius: var(--radius-sm);
  background: #fff;
  font-family: inherit;
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}

.control::placeholder {
  color: var(--ink-3);
}

@media (hover: hover) {
  .control:hover:not(:disabled):not(:focus) {
    border-color: var(--blue-200);
  }
}

.control:focus,
.control[aria-expanded="true"] {
  outline: none;
  border-color: var(--focus);
  box-shadow: 0 0 0 3px rgba(6, 146, 229, 0.2);
}

.control[aria-invalid="true"] {
  border-color: var(--error);
}

.control[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px rgba(206, 44, 49, 0.18);
}

.control:disabled {
  background: var(--disabled-bg);
  border-color: var(--disabled-bg);
  color: var(--disabled-text);
  cursor: not-allowed;
}

.control:disabled::placeholder {
  color: var(--disabled-text);
}

textarea.control {
  min-height: 120px;
  padding: 14px 16px;
  resize: vertical;
}

/* Checkbox and radio: a box of our own, the real input hidden over it. */
.choice {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
}

.choice input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.choice__box {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--primary-200);
  color: transparent;
  transition: background-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard);
}

.choice__box .icon {
  width: 14px;
  height: 14px;
  vertical-align: 0;
}

.choice--radio .choice__box {
  border-radius: 50%;
}

.choice--radio .choice__box::after {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
  transform: scale(0);
  transition: transform 320ms var(--spring);
}

@media (hover: hover) {
  .choice:hover input:not(:disabled):not(:checked) + .choice__box {
    box-shadow: inset 0 0 0 1.5px var(--primary-500);
  }
}

.choice input:checked + .choice__box {
  background: var(--blue-700);
  box-shadow: none;
  color: #fff;
}

.choice--radio input:checked + .choice__box::after {
  transform: scale(1);
}

.choice input:focus-visible + .choice__box {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

.choice input[aria-invalid="true"] + .choice__box {
  box-shadow: inset 0 0 0 1.5px var(--error);
}

.choice input:disabled + .choice__box {
  background: var(--disabled-bg);
  box-shadow: none;
}

.choice input:disabled:checked + .choice__box {
  color: var(--disabled-text);
}

.choice input:disabled ~ .choice__text {
  color: var(--disabled-text);
}

.choice:has(input:disabled) {
  cursor: not-allowed;
}

/* Dropdown (a form field) and dropdown button (a way somewhere, like the region picker): the
   nav's frosted panel under them, a row per choice, a tick by the one chosen. */
.dropdown,
.dropbtn {
  position: relative;
}

.dropdown {
  width: 100%;
}

.dropbtn {
  display: inline-block;
}

.dropdown__button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-align: left;
  cursor: pointer;
}

.dropdown__value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dropdown__value[data-empty] {
  color: var(--ink-3);
}

.dropdown__button:disabled .dropdown__value {
  color: var(--disabled-text);
}

.dropdown__caret,
.dropbtn__caret {
  flex: none;
  width: 11px !important;
  height: 11px !important;
  color: var(--ink-3);
  transition: transform 260ms var(--ease-emphasized);
}

.dropdown__button[aria-expanded="true"] .dropdown__caret,
.dropbtn__button[aria-expanded="true"] .dropbtn__caret {
  transform: rotate(180deg);
}

.dropbtn__button {
  gap: 10px;
  padding: 0 16px 0 11px;
  font-size: var(--fs-body-sm);
  line-height: 1;
}

.dropbtn__button--plain {
  padding: 0 16px 0 20px;
}

.dropbtn__button[aria-expanded="true"] {
  background: var(--blue-50);
  box-shadow: inset 0 0 0 1.5px var(--blue-200);
}

.dropbtn__name {
  font-weight: 500;
}

.dropbtn__aside {
  font-weight: 400;
  color: var(--ink-3);
}

.flag {
  flex: none;
  width: 22px;
  height: 22px;
  clip-path: circle(50%);
}

.dropdown__panel,
.dropbtn__panel {
  position: absolute;
  z-index: 10;
  top: calc(100% + 8px);
  left: 0;
  display: grid;
  gap: 2px;
  margin: 0;
  list-style: none;
  border: 1.5px solid var(--blue-100);
  background: rgba(251, 252, 253, 0.92);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  transition:
    opacity 180ms var(--ease),
    transform 280ms var(--ease),
    visibility 0s 280ms;
}

.dropdown__panel {
  right: 0;
  max-height: 288px;
  overflow-y: auto;
  padding: 6px;
  border-radius: 14px;
  box-shadow: var(--shadow-2);
  transform-origin: top center;
}

.dropdown__panel:focus {
  outline: none;
}

/* A floating panel (`float`): on the page over everything, placed by the component; opening upward it
   grows from its foot. */
.dropdown__panel--float {
  z-index: 1000;
}

.dropdown__panel--float[data-up] {
  transform-origin: bottom center;
}

.dropdown__panel--float[data-up]:not([data-open]) {
  transform: translateY(6px) scale(0.98);
}

.dropbtn__panel {
  min-width: 248px;
  padding: 8px;
  border-radius: 22px;
  transform-origin: top left;
}

.dropdown__panel[data-open],
.dropbtn__panel[data-open] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity 180ms var(--ease),
    transform 280ms var(--ease);
}

/* Rows' corners nested in their panel's: 14 less 6, 22 less 8. */
.dropdown__option {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 16px;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 16px;
  line-height: 1.3;
  color: var(--ink);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.dropdown__option small {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-body-sm);
  color: var(--ink-3);
}

.dropdown__option[data-active] {
  background: var(--blue-50);
}

.dropdown__option[aria-selected="true"] {
  color: var(--blue-700);
  font-weight: 500;
}

.dropdown__option[aria-selected="true"] small {
  font-weight: 400;
}

.dropbtn__row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) 16px;
  align-items: center;
  gap: 12px;
  min-height: 52px;
  padding: 8px 12px;
  border-radius: 14px;
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.dropbtn__row--plain {
  grid-template-columns: minmax(0, 1fr) 16px;
  min-height: 44px;
}

.dropbtn__row:hover,
.dropbtn__row:focus-visible {
  outline: none;
  background: var(--blue-50);
}

.dropbtn__row .flag {
  width: 26px;
  height: 26px;
}

.dropbtn__words {
  display: grid;
  gap: 4px;
  font-size: var(--fs-body-sm);
  line-height: 1.1;
}

.dropdown__check,
.dropbtn__check {
  width: 16px;
  height: 16px;
  color: var(--blue-700);
}

/* ------------------------------------------------------------------------------------------ */
/* The board (ui/Board.tsx): the foot card grown to fill the screen, landing as a piece of the wall's
   own panel: white, micro-perforated every 8 mm, lit from behind in soft pools, white to pale blue
   (three/World.tsx, Board). The holes run on as you pan; the light behind stays put. What is pinned
   to it is in the wall's materials, held by its glass pins and tied with its thread. */

.board {
  position: fixed;
  inset: 0;
  z-index: 60;
  overflow: hidden;
  touch-action: none;
}

.board__paper {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
  overflow: hidden;
  background:
    radial-gradient(60% 55% at 22% 30%, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0) 70%),
    radial-gradient(55% 60% at 78% 72%, rgba(214, 238, 255, 0.8), rgba(214, 238, 255, 0) 70%),
    radial-gradient(45% 45% at 72% 16%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 70%),
    #f1f7fc;
  box-shadow: var(--shadow-lift);
}

/* The perforations: 1.6 mm holes every 8 mm, as on the wall's panel. */
.board__holes {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at center, rgba(7, 116, 184, 0.16) 0 1.2px, rgba(7, 116, 184, 0) 1.65px);
}

/* The foot card itself, white, which the panel shows through as it lands. */
.board__card {
  position: absolute;
  inset: 0;
  background: #fcfcfb;
}

.board__content {
  position: absolute;
  inset: 0;
}

.board__surface {
  position: absolute;
  inset: 0;
  cursor: grab;
}

.board--write .board__surface:active {
  cursor: grabbing;
}

.board__space {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
}

.board__ink {
  position: absolute;
  left: 0;
  top: 0;
  overflow: visible;
  pointer-events: none;
}

/* The canvas, filling the board. */
.board__canvas {
  position: absolute;
  inset: 0;
  animation: board-mode-in 420ms var(--ease) both;
}

@keyframes board-mode-in {
  from {
    opacity: 0;
  }
}

/* ---- The way in (Canvas, Choose): two of the wall's cards over its panel, the parts drifting
   behind in NOVUS blue line. */
.board__choose {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: auto;
}

.board__drift {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.board__drift-item {
  position: absolute;
  opacity: 0.32;
  animation: board-drift var(--dur) ease-in-out var(--delay) infinite alternate;
}

.board__drift-art svg {
  display: block;
  width: 100%;
  height: auto;
}

.board__drift-item.is-spin .board__drift-art {
  animation: board-spin calc(var(--dur) * 0.6) linear var(--delay) infinite;
}

@keyframes board-spin {
  to {
    transform: rotate(360deg);
  }
}

.board__choose-in {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 8px;
  padding: 96px 16px 48px;
  text-align: center;
  animation: board-rise 620ms var(--ease) 360ms both;
}

@keyframes board-rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}

.board__ways {
  display: grid;
  grid-template-columns: repeat(2, 264px);
  gap: 24px;
  margin-top: 32px;
}

/* A way in is one of the wall's heavy cards on a glass pin, just its icon, its name and one line;
   under the pointer it comes off the panel a little and grows about its pin, as what can be clicked
   on the wall does. */
.board__way {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  min-height: 240px;
  padding: 32px 24px 24px;
  border: 0;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(16, 42, 67, 0.06), 0 4px 12px rgba(16, 42, 67, 0.08);
  font-family: inherit;
  text-align: left;
  color: var(--ink);
  cursor: pointer;
  transform-origin: 50% 12px;
  transition: transform 360ms var(--ease), box-shadow 360ms var(--ease);
}

.board__way:focus-visible {
  transform: scale(1.025);
  box-shadow: 0 0 0 1px rgba(16, 42, 67, 0.06), 0 12px 32px rgba(16, 42, 67, 0.12);
}

.board__way:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
}

.board__way-pin {
  left: 50%;
  top: 6px;
}

.board__way-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 32px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.board__way-line {
  font-size: 15px;
  line-height: 1.4;
  color: var(--ink-2);
}

/* ---- Write: notes in the wall's materials on its panel. */

/* Heavy matte card, as the wall's question cards: the words large. */

@keyframes board-note-in {
  from {
    opacity: 0;
    transform: translateY(-8px) scale(0.97);
  }
}

/* Frosted acrylic, as the wall's notes: cool white to the palest blue, a sheen from the top left and
   a bright bevel (faces.ts, frost). */

/* Faintly blue see-through film, as Why NOVUS exists' sheets: the holes show through it. */

/* Writing in a note shows the focus ring the rest of the site has. */

/* The wall's frosted glass push pin at its head: clear glass, a bright point where the light
   catches it, its shadow down and to the right. */
.board__pin {
  position: absolute;
  width: 13px;
  height: 13px;
  margin-left: -6.5px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, #fff 0 16%, rgba(255, 255, 255, 0) 30%),
    radial-gradient(circle at 60% 65%, rgba(220, 238, 250, 0.55), rgba(150, 190, 220, 0.6) 75%, rgba(120, 165, 200, 0.75) 100%);
  box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.8), 3px 4px 4px rgba(16, 42, 67, 0.22);
  pointer-events: none;
}

.board__tag {
  margin: 0;
  color: var(--ink-2);
}

.board__tag span {
  margin-right: 8px;
  color: var(--blue-700);
}

.board__title {
  margin: 0;
  font-size: 48px;
  line-height: 1.05;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink);
}

/* As on the foot card: the first words in ink, the rest in NOVUS blue. */
.board__title em {
  font-style: normal;
  color: var(--blue-700);
}

.board__hint {
  margin: 0;
  font-size: 15px;
  color: var(--ink-2);
}

.board__close {
  position: absolute;
  z-index: 3;
  top: 16px;
  right: 32px;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 18px;
  cursor: pointer;
}

/* The toolbar is the lab's nav pill (styles.css, Nav): bright frosted glass, its shadow lifting it
   off the board, no line round it, the items in capitals in ink, each a chip that greys under the
   pointer; the tool in hand keeps the chip. No dividers: a little more room between groups. */
.board__tools {
  position: absolute;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  box-shadow:
    0 12px 32px rgba(9, 38, 64, 0.14),
    0 1px 3px rgba(9, 38, 64, 0.1);
  white-space: nowrap;
}

.has-library .board__tools {
  left: calc((100% - 340px) / 2);
}

.board__tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  min-width: 36px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  transition: background-color 160ms;
}

.board__tool:hover,
.board__tool:focus-visible {
  background: rgba(15, 15, 15, 0.06);
}

/* The tool in hand: a pale blue chip, its word in NOVUS blue. */
.board__tool[aria-pressed="true"] {
  background: var(--primary-50);
  color: var(--blue-700);
}

.board__tool:disabled {
  color: var(--ink-3);
  cursor: default;
  background: none;
}

/* Back to the way in: the arrow turned round, on a round chip. */
.board__back {
  width: 36px;
  padding: 0;
  font-size: 16px;
}

.board__back svg {
  transform: rotate(180deg);
}

/* Which way in this is, in NOVUS blue beside the arrow. */

/* A swatch: a 22 px dot in a 36 px chip, as the nav's items are. */

/* What to do first, over the toolbar, while there is nothing yet: a small pill of the same glass. */
.board__tip {
  position: absolute;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%);
  margin: 0;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  backdrop-filter: blur(16px) saturate(1.4);
  box-shadow: 0 8px 24px rgba(9, 38, 64, 0.1), 0 1px 3px rgba(9, 38, 64, 0.08);
  font-size: 13px;
  color: var(--ink-2);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  translate: 0 6px;
  transition: opacity 260ms var(--ease), translate 360ms var(--ease);
}

.has-library .board__tip,
.has-library .board__done {
  left: calc((100% - 340px) / 2);
}

.board__tip.is-on {
  opacity: 1;
  translate: 0 0;
}

/* ---- Draw: a plain white sheet, a pen and an eraser, and parts to build with. */
.board__sheet {
  position: absolute;
  inset: 0;
  background: #fff;
}

.board--draw .board__surface {
  cursor: crosshair;
}

/* The eraser: a round of frosted white under the pointer, its reach. */
.board--draw.is-erasing .board__surface {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='12' cy='12' r='10' fill='white' fill-opacity='0.85' stroke='%230774b8' stroke-width='1.5'/%3E%3C/svg%3E") 12 12, crosshair;
}

/* What is drawn: NOVUS blue, a marker's weight, as the stages' scribbles are (world/brush.ts). */
.board__drawn path {
  fill: none;
  stroke: var(--blue-700);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Where a part has snapped on: a ring in Vida orange at the joint. */
.board__snap {
  fill: none;
  stroke: #ff5310;
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

/* A part on the sheet, turned and mirrored about its origin, its line in NOVUS blue. */
.board__piece-at {
  position: absolute;
  width: 0;
  height: 0;
  transform-origin: 0 0;
}

.board__piece {
  position: absolute;
  cursor: grab;
  touch-action: none;
}

.board__piece:active {
  cursor: grabbing;
}

.board__piece svg {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.board__piece.is-picked {
  outline: 1.5px dashed rgba(7, 116, 184, 0.6);
  outline-offset: 6px;
  border-radius: 8px;
}

/* A picked part's controls: the toolbar's glass pill, small, just above it. */
.board__piece-bar {
  position: absolute;
  z-index: 2;
  display: flex;
  gap: 4px;
  padding: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 8px 24px rgba(9, 38, 64, 0.14), 0 1px 3px rgba(9, 38, 64, 0.1);
  transform: translate(-50%, -100%);
  white-space: nowrap;
  animation: board-bar-in 260ms var(--ease) both;
}

@keyframes board-bar-in {
  from {
    opacity: 0;
    translate: 0 4px;
  }
}

.board__piece-bar .board__tool {
  gap: 8px;
}

/* Delete in Vida's text orange, the one thing on the bar that can't be put back but by Undo. */
.board__delete {
  color: #d43d02;
}

.board__delete:hover,
.board__delete:focus-visible {
  background: rgba(212, 61, 2, 0.08);
}

/* The parts library, to design.md: a large module (24 px radius, padding on the spacing scale,
   --shadow-3 as an overlay), the kinds of part as filter pills in one row that scrolls (44 px
   targets), the parts as cards (8 px radius, a subtle border, --shadow-1 resting and --shadow-2 under
   the pointer), named in Body Small. */
.board__library {
  position: absolute;
  z-index: 2;
  top: 88px;
  right: 16px;
  bottom: 16px;
  width: 320px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 24px 0 0;
  border-radius: 24px;
  background: rgba(255, 255, 255, 0.92);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  box-shadow: 0 12px 32px rgba(16, 42, 67, 0.12);
  overflow: hidden;
  animation: board-library-in 460ms var(--ease) both;
}

@keyframes board-library-in {
  from {
    opacity: 0;
    transform: translateX(24px);
  }
}

.board__library-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
}

.board__library-close {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: -12px -12px -12px 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--blue-700);
  font-size: 16px;
  cursor: pointer;
}

.board__library-close:hover {
  background: rgba(15, 15, 15, 0.05);
}

/* Its fold: the caret pointing right, towards the edge it folds to. */
.board__library-close svg {
  transform: rotate(-90deg);
}

.board__library {
  transition: transform 460ms var(--ease), opacity 300ms var(--ease);
}

.board__library.is-folded {
  transform: translateX(calc(100% + 24px));
  opacity: 0;
  pointer-events: none;
}

/* Folded, a tab of the same glass at the right edge, the caret pointing back in. */
.board__library-tab {
  position: absolute;
  z-index: 2;
  top: 88px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 16px 0 12px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  box-shadow: 0 12px 32px rgba(16, 42, 67, 0.12);
  color: var(--blue-700);
  font-family: inherit;
  cursor: pointer;
  opacity: 0;
  transform: translateX(8px);
  pointer-events: none;
  transition: opacity 300ms var(--ease), transform 460ms var(--ease);
}

.board__library-tab svg {
  transform: rotate(90deg);
}

.board__library-tab.is-on {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* The filters: one row, scrolled sideways, fading out at its right edge. */
.board__groups {
  display: flex;
  gap: 8px;
  padding: 6px 24px;
  margin: -6px 0;
  overflow-x: auto;
  scrollbar-width: none;
  flex-shrink: 0;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
}

.board__groups::-webkit-scrollbar {
  display: none;
}

.board__group-chip {
  position: relative;
  flex-shrink: 0;
  height: 32px;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: rgba(15, 15, 15, 0.05);
  color: var(--ink);
  font-family: inherit;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 160ms, color 160ms;
}

.board__group-chip:last-child {
  margin-right: 24px;
}

.board__group-chip::before {
  content: "";
  position: absolute;
  inset: -6px 0;
}

.board__group-chip:hover {
  background: rgba(15, 15, 15, 0.09);
}

.board__group-chip[aria-selected="true"] {
  background: var(--blue-700);
  color: #fff;
}

.board__group-chip:focus-visible,
.board__part:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.board__parts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-content: start;
  gap: 8px;
  padding: 4px 24px 24px;
  overflow: auto;
}

.board__part {
  display: grid;
  gap: 8px;
  padding: 16px 16px 12px;
  border: 1px solid rgba(16, 42, 67, 0.06);
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(16, 42, 67, 0.06);
  font-family: inherit;
  text-align: left;
  cursor: grab;
  animation: board-part-in 420ms var(--ease) both;
  transition: transform 260ms var(--ease), box-shadow 260ms var(--ease);
}

@keyframes board-part-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

.board__part:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(16, 42, 67, 0.08);
}

.board__part:active {
  cursor: grabbing;
}

.board__part-art {
  display: block;
  height: 72px;
}

.board__part-art svg {
  display: block;
  width: 100%;
  height: 72px;
}

/* Body Small: 14 px, Book, 1.5. */
.board__part-name {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--ink);
}

@media (max-width: 699px) {
  .board__close {
    top: 16px;
    right: 16px;
  }

  .board__title {
    font-size: 32px;
  }

  .board__ways {
    grid-template-columns: minmax(0, 300px);
    gap: 16px;
    margin-top: 24px;
  }

  .board__way {
    min-height: 200px;
  }

  .board__tools,
  .has-library .board__tools {
    left: 50%;
    bottom: 16px;
    max-width: calc(100vw - 24px);
    overflow-x: auto;
  }

  .board__tool {
    padding: 0 11px;
  }

  .board__tip,
  .has-library .board__done {
    left: 50%;
  }

  .has-library .board__tip {
    left: 50%;
    white-space: normal;
    width: calc(100vw - 32px);
    text-align: center;
  }

  /* On a phone the library is a sheet over the foot of the screen, above the toolbar. */
  .board__library {
    top: auto;
    left: 12px;
    right: 12px;
    bottom: 76px;
    width: auto;
    max-height: 52vh;
  }
}

/* Save, at the end of the toolbar: the one filled chip, in NOVUS blue. */
.board__save {
  background: var(--blue-700);
  color: #fff;
}

.board__save:hover:not(:disabled),
.board__save:focus-visible {
  background: var(--primary-800);
}

/* Pressed, design.md's primary active step. */
.board__save:active:not(:disabled) {
  background: var(--primary-900);
}

.board__save:disabled {
  background: rgba(15, 15, 15, 0.05);
}

/* Saving: a modal of the nav's glass over the board (design.md: 24 px radius, --shadow-4). */

/* The product pages' form (Your take, on the forms branch), its field, consent and buttons as they
   are there,
   so the two read as one: a 22 px box that fills NOVUS blue with a tick; fields 56 px,
   their label over them; the primary the gradient {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}


/* Said for a moment once saved, over the toolbar. */
.board__done {
  position: absolute;
  left: 50%;
  bottom: 88px;
  z-index: 4;
  margin: 0;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 12px 32px rgba(16, 42, 67, 0.12);
  font-size: 14px;
  color: var(--ink);
  transform: translate(-50%, 8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease), transform 420ms var(--ease);
}

.board__done.is-on {
  opacity: 1;
  transform: translate(-50%, 0);
}


/* The library starts under the head. */
.board__library-tab {
  top: 78px;
}

@media (min-width: 700px) {
  .board__library {
    top: 78px;
  }
}

@media (max-width: 699px) {
  .board__bar {
    left: 16px;
  }
}

/* The way in, laid out (the user, 2026-10-28: "change the alignment"): on a wide screen the words
   and the two cards on the left, the scooter being put together on the right, both centred on the
   screen's height; upright (an iPad held upright, a phone) one column, the scooter under the cards. */
.board__choose-in {
  display: grid;
  grid-template-columns: minmax(0, 552px) minmax(0, 1fr);
  /* The scooter stands on the cards' foot line (the user: "bottom align the scooter end and the cards"). */
  align-items: end;
  gap: 72px;
  width: min(1320px, 100%);
  padding: 96px 48px 48px;
  text-align: left;
  justify-items: stretch;
}

.board__choose-words {
  display: grid;
  justify-items: start;
  gap: 8px;
}

.board__choose-in .board__ways {
  margin-top: 24px;
}

/* The line over two, so the scooter has the room beside it. */
.board__choose-words .board__title {
  max-width: 12em;
  font-size: 56px;
}

@media (max-width: 1100px), (orientation: portrait) {
  .board__choose-in {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: 32px;
    padding: 96px 24px 32px;
    text-align: center;
  }

  .board__choose-words {
    justify-items: center;
  }

}

/* A part being carried out of the library: its drawing under the pointer, a little lifted. */
.board__ghost {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 100;
  color: #0774b8;
  filter: drop-shadow(6px 12px 10px rgba(16, 42, 67, 0.18));
  pointer-events: none;
  will-change: transform;
}

.board__ghost svg {
  display: block;
  width: 100%;
  height: 100%;
}

.board__part.is-carried {
  opacity: 0.5;
}

/* On a touch screen the tiles scroll the list up and down; a sideways drag takes a part. */
.board__part {
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.board__tool,
.board__group-chip,
.board__way,
.board__piece {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.board__piece {
  touch-action: none;
}

@media (hover: hover) {
  .board__way:hover {
    transform: scale(1.025);
    box-shadow: 0 0 0 1px rgba(16, 42, 67, 0.06), 0 12px 32px rgba(16, 42, 67, 0.12);
  }

  .board__part:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(16, 42, 67, 0.08);
  }
}

/* Bodies a tile wide: one to a row in the column, their drawing taller. */
.board__parts.is-wide {
  grid-template-columns: minmax(0, 1fr);
}

.board__parts.is-wide .board__part-art,
.board__parts.is-wide .board__part-art svg {
  height: 96px;
}

/* An iPad held upright: the library stays at the right (the user, 2026-10-28: "let the parts stay
   on the right"), narrower, one part to a row, so the sheet keeps the most of the width and the
   toolbar stays whole in the middle of what is left (at 320 px it was pushed to the screen's edge). */
@media (min-width: 700px) and (orientation: portrait) {
  .board__library {
    width: 264px;
  }

  .board__parts,
  .board__parts.is-wide {
    grid-template-columns: minmax(0, 1fr);
  }

  .board__part-art,
  .board__part-art svg {
    height: 84px;
  }

  .has-library .board__tools,
  .has-library .board__tip,
  .has-library .board__done {
    left: calc((100% - 280px) / 2);
  }
}

/* The toolbar's rhythm (the user, 2026-10-28: "spacing is uneven, proper padding"): every item a
   36 px chip with the same 16 px at its sides, the same 4 px between each, and the same 6 px of
   glass all round; the mode's name is padded as a chip is, and there are no wider gaps between
   groups (they read as holes). */
.board__tools {
  gap: 4px;
  padding: 6px;
}

.board__tools .board__tool {
  height: 36px;
  padding: 0 16px;
}

/* The swatches sit in the same rhythm: a 36 px chip each. */

/* The panel's heading in the nav's style: 15 px Medium, ink then NOVUS blue (the head's line it
   matched is gone with the title). */
.board__library-title {
  margin: 0;
  font-size: 15px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}

.board__library-title em {
  font-style: normal;
  color: var(--blue-700);
}

.board__library-head {
  min-height: 44px;
}

/* In Write and Draw there is no close button (the user, 2026-10-28: "remove"): the head's arrow goes
   back to the way in, which keeps the ✕ to fold the board back onto the wall. The library moves
   up into its place, level with the head. */
.board__content:has(.board--write, .board--draw) > .board__close {
  display: none;
}

@media (min-width: 700px) {
  .board__library,
  .board__library-tab {
    top: 80px;
  }
}

/* The way in, with no scooter (the user, 2026-10-29: "remove the motor cycle motion"): one column
   in the middle of the screen, the line over the two cards. */
.board__choose-in {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  width: min(760px, 100%);
  text-align: center;
}

.board__choose-words {
  justify-items: center;
}

/* Each card's pictogram, painted in the wall's brush (world/brush.ts) at the top of the card, as
   the stages' are above their words. */
/* Trimmed to its ink and set at this height from the left edge, in line with the name under it
   (Pictogram in board/Canvas.tsx). */
.board__way-art {
  display: block;
  width: 140px;
  height: 64px;
  margin: 8px 0 auto;
}

/* The wall's own glass pin (pin-sprite.ts: rendered from the kit with the wall's glass, steel,
   light and drawn shadow), the same on every pin of the board: its head where the pin goes in. */
.board__pin {
  /* The picture is 44 mm square round the head (pin-sprite.ts: PIN_SPAN, PIN_HEAD), at the wall's own
     px a mm on this screen (--pin-k, set by Board), so it is the wall's pin at the wall's size; its
     head at (17 mm, 17 mm), where the pin goes in. */
  width: calc(44px * var(--pin-k, 1.6));
  height: calc(44px * var(--pin-k, 1.6));
  margin: calc(7px - 17px * var(--pin-k, 1.6)) 0 0 calc(-17px * var(--pin-k, 1.6));
  border-radius: 0;
  background: url("/images/board/wall-pin.png") center / contain no-repeat;
  box-shadow: none;
}

/* ---- Polish (the user, 2026-10-28: "polish it better, smoother"). One ease for all of it, the
   site's (--ease), and nothing that jumps. */

/* The way in fades up as the board lands, its two cards one after the other. */
.board__choose {
  animation: board-mode-in 420ms var(--ease) both;
}

.board__way {
  animation: board-rise 620ms var(--ease) both;
}

.board__way:nth-child(1) {
  animation-delay: 480ms;
}

.board__way:nth-child(2) {
  animation-delay: 560ms;
}

.board__choose-in {
  animation-duration: 720ms;
}

.board__way:active {
  transform: scale(0.99);
  transition-duration: 120ms;
}

/* Every chip eases its colour and gives under a press. */
.board__tool,
.board__group-chip,
.board__library-close,
.board__library-tab {
  transition: background-color 200ms var(--ease), color 200ms var(--ease), box-shadow 200ms var(--ease), transform 160ms var(--ease), opacity 300ms var(--ease);
}

.board__tool:active:not(:disabled),
.board__group-chip:active {
  transform: scale(0.95);
}

/* A note lifts while it is carried: its shadow longer and softer, a degree askew, settling back when
   let go, as the wall's cards come off the panel under the pointer. */

/* A part comes onto the sheet with a small settle, and lifts while it is carried. */
.board__piece {
  animation: board-piece-in 420ms var(--ease) both;
}

@keyframes board-piece-in {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
}

.board__piece svg {
  transition: filter 260ms var(--ease);
}

.board__piece.is-held {
  z-index: 1;
}

.board__piece.is-held svg {
  filter: drop-shadow(6px 12px 10px rgba(16, 42, 67, 0.16));
}

/* The snap: a ring at the joint that breathes while it is held there. */
.board__snap {
  animation: board-snap 900ms ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}

@keyframes board-snap {
  50% {
    transform: scale(1.5);
    opacity: 0.5;
  }
}

/* The pen: a small round of NOVUS blue, its point where the line starts. */
.board--draw .board__surface {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='3.5' fill='%230774b8'/%3E%3Ccircle cx='8' cy='8' r='6.5' fill='none' stroke='%230774b8' stroke-opacity='0.25'/%3E%3C/svg%3E") 8 8, crosshair;
}

.board__drawn path {
  shape-rendering: geometricPrecision;
}

/* The part's bar follows it smoothly as it is turned or sized. */
.board__piece-bar {
  transition: left 200ms var(--ease), top 200ms var(--ease);
}

/* The library's tiles: the drawing comes forward a touch under the pointer. */
.board__part-art svg {
  transition: transform 360ms var(--ease);
}

.board__part:hover .board__part-art svg {
  transform: scale(1.06);
}

/* The dialog blurs the board behind it. */

.board__done {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.board__done svg {
  color: var(--blue-700);
}

/* Write's Save stays above the keyboard while it is up. */
.board--write .board__done {
  translate: 0 calc(0px - var(--kb, 0px));
  transition: translate 250ms var(--ease-standard);
}

/* Save at the top right, level with the way back at the top left. */
.board__save-bar {
  position: absolute;
  z-index: 3;
  top: 16px;
  right: 32px;
}

@media (max-width: 699px) {
  .board__save-bar {
    right: 16px;
  }
}

/* The word that it saved comes up at once: a quick fade and rise, not the slower one it had. */
.board__done {
  transition: opacity 160ms var(--ease-standard), transform 200ms var(--ease);
}

/* Draw on plain white (the user, 2026-10-29: "I want a plain white background"), the wall's dots on
   it; the panel's light behind it doesn't show through. */
.board--draw {
  background: #ffffff;
}

/* The page's paper: the wall's foot card's rules, painted (faces.ts, paintRules), under the words. */
.board__page-paper {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  pointer-events: none;
}

/* Draw: its Save is in the toolbar, so the library goes up to the top right again. */
@media (min-width: 700px) {
  .board--draw .board__library,
  .board--draw .board__library-tab {
    top: 16px;
  }
}

/* Draw's dots: a quarter larger apart (SHEET_PITCH) and a touch larger themselves. */
.board__holes--sheet {
  background-image: radial-gradient(circle at center, rgba(7, 116, 184, 0.16) 0 1.5px, rgba(7, 116, 184, 0) 2.05px);
}

/* The parts library on the design system (design.md; the user, 2026-10-29: "follow the design.md
   and design system … the header sizing and all padding"), about 10% narrower than it was: a
   feature panel (--radius-lg) with 24 px sides on the spacing scale, its heading in Body Medium as
   the other panels' titles are, the kinds of part as Label pills, the parts as cards (--radius)
   named in Body Small. The toolbar and the word that it saved centre in what it leaves. */
.board__library {
  width: 288px;
  gap: var(--space-3);
  padding: var(--space-4) 0 0;
  border-radius: var(--radius-lg);
}

.board__library-head,
.board__groups {
  padding-left: var(--space-4);
  padding-right: var(--space-4);
}

.board__library-head {
  min-height: 32px;
}

.board__library-title {
  font-size: var(--fs-body);
  line-height: var(--lh-tight);
  letter-spacing: -0.005em;
}

/* Its fold keeps a 44 px target, drawn into the head's 32 px line. */
.board__library-close {
  margin: -6px -12px -6px 0;
}

.board__groups {
  gap: var(--space-2);
}

.board__group-chip {
  height: 32px;
  padding: 0 var(--space-3);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
}

.board__group-chip:last-child {
  margin-right: var(--space-4);
}

.board__parts {
  gap: var(--space-2);
  padding: var(--space-1) var(--space-4) var(--space-4);
}

.board__part {
  gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-2);
  border-radius: var(--radius);
}

.board__part-art,
.board__part-art svg {
  height: 64px;
}

.board__part-name {
  font-size: var(--fs-body-sm);
  line-height: 1.3;
}

.has-library .board__tools,
.has-library .board__tip,
.has-library .board__done {
  left: calc((100% - 304px) / 2);
}

@media (min-width: 700px) and (orientation: portrait) {
  .board__library {
    width: 240px;
  }

  .board__part-art,
  .board__part-art svg {
    height: 72px;
  }

  .has-library .board__tools,
  .has-library .board__tip,
  .has-library .board__done {
    left: calc((100% - 256px) / 2);
  }
}

@media (max-width: 699px) {
  .has-library .board__tools,
  .has-library .board__tip,
  .has-library .board__done {
    left: 50%;
  }
}

/* The kinds of part as the design system's chips (.chip: 44 px, a 1.5 px blue-100 rim, white, Body
   Small Medium), the chosen one as a chip that's on: pale blue, NOVUS blue words. */
.board__groups .board__group-chip {
  height: auto;
  min-height: 44px;
  padding: 0 var(--space-3);
  background: #fff;
  color: var(--ink);
  font-size: var(--fs-body-sm);
  letter-spacing: 0;
  text-transform: none;
}

.board__groups .board__group-chip::before {
  content: none;
}

.board__groups .board__group-chip[aria-selected="true"] {
  background: var(--blue-50);
  border-color: var(--blue-50);
  color: var(--blue-700);
}

.board__groups {
  padding-top: 2px;
  padding-bottom: 2px;
  margin: -2px 0;
}

/* Every kind in one list, under its name in the Label style. */
.board__parts {
  position: relative;
  display: block;
  padding-top: var(--space-2);
}

.board__kind + .board__kind {
  margin-top: var(--space-4);
}

.board__kind-name {
  margin: 0 0 var(--space-2);
  color: var(--ink-2);
  font-weight: 500;
}

.board__kind-parts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}

@media (min-width: 700px) and (orientation: portrait) {
  .board__kind-parts {
    grid-template-columns: 1fr;
  }
}

/* The cards with no rim (the user, 2026-10-29: "let us take a look on the ui without the out
   stroke"): white on the panel's glass, lifted by --shadow-1 alone; names smaller, at 12 px. */
.board__part {
  border-color: transparent;
}

.board__part-name {
  font-size: var(--fs-label);
  line-height: 1.33;
}

/* The list's scrollbar, slim (the user, 2026-10-29: "reduce the size of the scroll"): a 4 px pill
   in the system's blue-100 on no track, clear of the panel's rounded corners; Firefox takes its thin
   one in the same colour. */
.board__parts::-webkit-scrollbar {
  width: 12px;
}

.board__parts::-webkit-scrollbar-track {
  background: transparent;
  margin: var(--space-2) 0 var(--space-4);
}

.board__parts::-webkit-scrollbar-thumb {
  border: 4px solid transparent;
  border-right-width: 4px;
  border-radius: var(--radius-pill);
  background: var(--blue-100) padding-box;
}

.board__parts::-webkit-scrollbar-thumb:hover {
  background-color: var(--blue-200);
}

.board__parts::-webkit-scrollbar-button {
  display: none;
}

@supports (-moz-appearance: none) {
  .board__parts {
    scrollbar-width: thin;
    scrollbar-color: var(--blue-100) transparent;
  }
}

/* The panel's sides down to 16 px (the user, 2026-10-29: "the side padding ... is occupying more
   space, instead give that space to the cards"), so the cards are wider in the same panel. */
.board__library-head,
.board__groups {
  padding-left: var(--space-3);
  padding-right: var(--space-3);
}

.board__group-chip:last-child {
  margin-right: var(--space-3);
}

.board__parts {
  padding-left: var(--space-3);
  padding-right: var(--space-3);
}

/* The kinds of part as the design system's tags (Tag.tsx, .tag), smaller than the chips and with no
   rim or black (the user: "reduce the size of the capsule ... the black & stroke is not good"):
   Label type on a pale grey pill, the chosen one as the blue tag. A 44 px target round each. */
.board__groups .board__group-chip {
  min-height: 0;
  height: 28px;
  padding: 0 var(--space-3);
  border: 0;
  background: var(--grey-50);
  color: var(--ink-2);
  font-size: var(--fs-label);
  line-height: 1.33;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}

.board__groups .board__group-chip::before {
  content: "";
  position: absolute;
  inset: -8px 0;
}

@media (hover: hover) {
  .board__groups .board__group-chip:hover:not([aria-selected="true"]) {
    background: var(--grey-100);
    border-color: transparent;
  }
}

.board__groups .board__group-chip[aria-selected="true"] {
  background: var(--primary-50);
  color: var(--primary-700);
}

.board__groups {
  padding-top: 8px;
  padding-bottom: 8px;
  margin: -8px 0;
}

/* The parts in the panel drawn in grey (the user, 2026-10-29: "have the colors of the build the
   parts ... like a grey"), so the panel is quiet beside the sheet; a part turns NOVUS blue under the
   pointer and while carried, the blue it has on the sheet. (Its drawing sets its colour inline, so
   this has to outrank that.) */
.board__part-art svg {
  color: var(--grey-500) !important;
  transition: transform 360ms var(--ease), color var(--duration-fast) var(--ease-standard);
}

@media (hover: hover) {
  .board__part:hover .board__part-art svg {
    color: var(--blue-700) !important;
  }
}

.board__part.is-carried .board__part-art svg,
.board__part:active .board__part-art svg {
  color: var(--blue-700) !important;
}

/* Build from parts as a sheet of the wall's paper (the user, 2026-10-29): the cards' paper white
   (faces.ts, PAPER.card) with a faint blue grid printed on it, corners all but square, lying flat
   (a hairline edge and a contact shadow, no float), and its name in the top left in small spaced
   capitals, the way the wall's cards carry their tags. */
.board__library {
  --rule: rgba(16, 42, 67, 0.08);
  border-radius: 2px;
  background-color: #fcfcfb;
  background-image:
    linear-gradient(rgba(88, 202, 255, 0.12) 1px, transparent 1px),
    linear-gradient(90deg, rgba(88, 202, 255, 0.12) 1px, transparent 1px);
  background-size: 16px 16px;
  background-position: -1px -1px;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 0 0 1px var(--rule), 0 1px 2px rgba(16, 42, 67, 0.06);
  padding-top: var(--space-3);
}

.board__library-title {
  font-size: 11px;
  font-weight: 500;
  line-height: 1.33;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #706e6e;
}

.board__library-title em {
  color: var(--blue-700);
}

.board__library-head {
  min-height: 28px;
}

.board__library-close {
  margin: -8px -14px -8px 0;
  font-size: 14px;
}

.board__library-close:hover {
  background: rgba(16, 42, 67, 0.04);
}

/* The folded tab: the same paper, square-ish and flat. */
.board__library-tab {
  border-radius: 2px;
  background: #fcfcfb;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 0 0 1px rgba(16, 42, 67, 0.08), 0 1px 2px rgba(16, 42, 67, 0.06);
}

/* The parts as small swatches of the same paper, lying flat in a grid of fine rules: no box, no
   lift; under the pointer a faint blue wash. */
.board__kind-parts {
  gap: 0;
  border-top: 1px solid var(--rule);
  background: #fcfcfb;
}

.board__part {
  padding: var(--space-3) var(--space-2) var(--space-2);
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.board__kind-parts > .board__part:nth-child(odd) {
  border-right: 1px solid var(--rule);
}

.board__part:focus-visible {
  transform: none;
  box-shadow: none;
  outline-offset: -2px;
}

@media (hover: hover) {
  .board__part:hover {
    transform: none;
    box-shadow: none;
    background: rgba(7, 116, 184, 0.04);
  }

  .board__part:hover .board__part-art svg {
    transform: none;
  }
}

.board__part:active {
  background: rgba(7, 116, 184, 0.06);
}

.board__part-name {
  text-align: center;
  color: var(--grey-500);
}

@media (min-width: 700px) and (orientation: portrait) {
  .board__kind-parts > .board__part:nth-child(odd) {
    border-right: 0;
  }
}

/* The Write page taped up at its top corners (the user, 2026-10-29: "i want these tapes for the
   write ui in the top corners of the ruled paper, use the same asset"): the wall’s own tape, taken
   from its render (ui/board/tape-sprite.ts), at its real size on the page (32 by 12 mm and 2 mm
   round it), across each corner. */
.board__tape {
  position: absolute;
  z-index: 2;
  top: calc(var(--page-mm, 3px) * 5);
  width: calc(var(--page-mm, 3px) * 36);
  height: calc(var(--page-mm, 3px) * 16);
  background: url("/images/board/wall-tape.png") center / 100% 100% no-repeat;
  pointer-events: none;
}

.board__tape--left {
  left: calc(var(--page-mm, 3px) * 5);
  transform: translate(-50%, -50%) rotate(-42deg);
}

.board__tape--right {
  right: calc(var(--page-mm, 3px) * 5);
  transform: translate(50%, -50%) rotate(44deg);
}

/* Draw's colours on the NOVUS palette (the user, 2026-10-29: "match with the novus lab branding ...
   the current side panel looks ashy"). design.md: neutrals and whitespace dominate, the blue ramp
   carries the brand, the Card surface is white; the wall uses only the blue and grey ramps. So no
   off-white paper, grey drawings, grey pills or navy-grey rules (the ash): white paper ruled in the
   palest blue, as the Write page's rules are; the parts drawn in the deepest blue; the kinds as blue
   tags; a scrollbar in NOVUS blue. Grey stays for secondary words only. */
.board__library {
  --rule: var(--primary-50);
  background-color: #fff;
  background-image:
    linear-gradient(rgba(6, 146, 229, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(6, 146, 229, 0.07) 1px, transparent 1px);
  box-shadow: 0 0 0 1px var(--primary-100), 0 1px 2px rgba(1, 43, 69, 0.06);
}

.board__library-tab {
  background: #fff;
  box-shadow: 0 0 0 1px var(--primary-100), 0 1px 2px rgba(1, 43, 69, 0.06);
}

.board__library-title {
  color: var(--grey-500);
}

.board__kind-name {
  color: var(--primary-700);
}

.board__kind-parts {
  background: #fff;
  border-top-color: var(--primary-100);
}

.board__part,
.board__kind-parts > .board__part:nth-child(odd) {
  border-color: var(--primary-50);
}

.board__part-art svg {
  color: var(--primary-900) !important;
}

@media (hover: hover) {
  .board__part:hover {
    background: var(--primary-50);
  }

  .board__part:hover .board__part-art svg {
    color: var(--primary-700) !important;
  }
}

.board__part:active {
  background: var(--primary-50);
}

.board__part-name {
  color: var(--grey-500);
}

/* The kinds: pale blue tags, the chosen one filled NOVUS blue with white words (design.md's
   primary, 700 for text-bearing fills). */
.board__groups .board__group-chip {
  background: var(--primary-50);
  color: var(--primary-800);
}

@media (hover: hover) {
  .board__groups .board__group-chip:hover:not([aria-selected="true"]) {
    background: var(--primary-100);
  }
}

.board__groups .board__group-chip[aria-selected="true"] {
  background: var(--primary-700);
  color: var(--on-primary);
}

/* The scrollbar: NOVUS blue, light enough to stay out of the way, full under the pointer. */
.board__parts::-webkit-scrollbar-thumb {
  background-color: rgba(7, 116, 184, 0.35);
}

.board__parts::-webkit-scrollbar-thumb:hover {
  background-color: var(--primary-700);
}

@supports (-moz-appearance: none) {
  .board__parts {
    scrollbar-color: rgba(7, 116, 184, 0.35) transparent;
  }
}

/* No blue line round the paper (the user, 2026-10-29: "dont add a blue stroke against the paper"):
   the Write page keeps its own shadow while it is written on (the caret shows where), and the parts
   panel lies on the sheet by a soft contact shadow alone. */
.board__page:focus-within {
  box-shadow: var(--shadow-2), 6px 14px 28px -12px rgba(16, 42, 67, 0.22);
}

.board__library,
.board__library-tab {
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.06), 0 2px 10px rgba(16, 42, 67, 0.06);
}

/* Build from parts in NOVUS's own manner (the user, 2026-10-29: "align with the vibe that novus is
   going for"; design.md: future-focused without feeling distant, generous whitespace, minimal visual
   noise, never "cold machine-like"). The two grids came out technical and busy: the paper is plain
   white now, its name set as the wall's lines are (sentence case, Medium, the end in NOVUS blue), each
   kind under a tag numbered as the wall's are ({01} Wheels), the parts given room on the white with
   no rules between them, a pale blue wash round one under the pointer; the tabs quiet until chosen. */
.board__library {
  background-image: none;
  padding-top: var(--space-4);
  gap: var(--space-3);
}

.board__library-head {
  min-height: 32px;
}

.board__library-title {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
}

.board__library-title em {
  color: var(--primary-700);
}

/* The tabs: words on the white, the chosen one on a pale blue pill (design.md's blue tag). */
.board__groups {
  gap: var(--space-1);
}

.board__groups .board__group-chip {
  padding: 0 12px;
  background: transparent;
  color: var(--grey-500);
}

@media (hover: hover) {
  .board__groups .board__group-chip:hover:not([aria-selected="true"]) {
    background: var(--primary-50);
    color: var(--primary-800);
  }
}

.board__groups .board__group-chip[aria-selected="true"] {
  background: var(--primary-50);
  color: var(--primary-700);
}

/* Each kind under its tag: the number in NOVUS blue, the name in grey, on a fine line. */
.board__kind + .board__kind {
  margin-top: var(--space-5);
}

.board__kind-name {
  display: flex;
  gap: 8px;
  margin: 0 0 var(--space-2);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--grey-50);
  color: var(--grey-300);
}

.board__kind-no {
  color: var(--primary-700);
}

.board__kind-parts,
.board__kind-parts > .board__part,
.board__kind-parts > .board__part:nth-child(odd) {
  border: 0;
}

.board__kind-parts {
  gap: var(--space-1);
  background: transparent;
}

.board__part {
  padding: var(--space-3) var(--space-2) var(--space-2);
  border-radius: var(--radius);
}

.board__part-art svg {
  color: var(--primary-800) !important;
}

@media (hover: hover) {
  .board__part:hover {
    background: var(--primary-50);
  }
}

.board__part-name {
  color: var(--grey-500);
  font-size: var(--fs-label);
}

/* The panel's edges to design.md, its type as it was (the user, 2026-10-29: "add the corner radius
   alone from the ds"): the panel a feature panel (Large, 24 px), the wash round a part a container
   (Medium, 8 px), the tabs and the folded tab filters (Pill). */
.board__library {
  border-radius: var(--radius-lg);
}

.board__library-tab,
.board__groups .board__group-chip {
  border-radius: var(--radius-pill);
}

.board__part {
  border-radius: var(--radius);
}

/* "Build from parts." set as a label (the user, 2026-10-29: "build from parts is a label"):
   design.md's Label, 12 px Medium capitals at +0.04em, the end still in NOVUS blue. */
.board__library-title {
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: 1.33;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
}

/* The panel's top and bottom on design.md's scale (the user, 2026-10-29: "adjust the top and
   bottom padding ... design md"): 24 px to the label at the top and under the last part at the foot,
   as a card's padding is. The head is the label's own height; the fold keeps its 44 px target,
   drawn out over the padding. */
.board__library {
  padding-top: var(--space-4);
}

.board__library-head {
  min-height: 0;
  height: 16px;
  flex-shrink: 0;
}

.board__library-close {
  margin: -14px -14px -14px 0;
}

.board__parts {
  padding-bottom: var(--space-4);
}

/* The panel's vertical rhythm on design.md's scale (the user, 2026-10-29: "adjust vertical padding
   inside the build the parts through design md"): smaller steps within a group, larger between
   them. 16 px from the label to the tabs and inside each part, above and below alike; 8 px from a
   kind's tag to its parts and between their rows; 24 px from the tabs to the first kind; 32 px from
   one kind to the next. */
.board__part {
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
}

.board__kind-parts {
  row-gap: var(--space-2);
}

.board__kind + .board__kind {
  margin-top: var(--space-5) !important;
}

/* Parts in the toolbar opens and folds the panel, so the tab at the screen's edge goes. Its icon
   and word side by side, the icon a touch larger than the capitals. */
.board__library-tab {
  display: none;
}

.board__tool--parts {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* Its icon as large as the other tools' (it read as a word alone at 14 px; the user: "add a menu for parts as well"). */
.board__tool--parts .icon {
  width: 18px;
  height: 18px;
}

/* The way in's cards as the wall's own paper (the user, 2026-10-29: "the cards are not blending in
   with the bg, refer the home ui"): the wall's card white (faces.ts, PAPER.card), a little see-through
   so the lit panel shows in it, as the wall's translucent cards are; corners all but square; lying
   on the panel with a short contact shadow and a soft fall, as the wall's hang; lifting a touch
   under the pointer. */
.board__way {
  border-radius: 2px;
  background: rgba(252, 252, 251, 0.72);
  -webkit-backdrop-filter: blur(6px) saturate(1.1);
  backdrop-filter: blur(6px) saturate(1.1);
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.06), 6px 14px 28px -14px rgba(16, 42, 67, 0.22);
}

@media (hover: hover) {
  .board__way:hover {
    transform: translateY(-2px) rotate(-0.4deg);
    box-shadow: 0 1px 2px rgba(16, 42, 67, 0.06), 8px 20px 36px -14px rgba(16, 42, 67, 0.26);
  }
}

.board__way:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.06), 8px 20px 36px -14px rgba(16, 42, 67, 0.26);
}

/* The way back to the wall at the top left, where Write's and Draw's are. */
.board__close {
  left: 32px;
  right: auto;
}

@media (max-width: 699px) {
  .board__close {
    left: 16px;
    right: auto;
  }
}

/* The lab's nav stays over the board (the user: "lets retain the nav here as well"). */
html.is-board .nav {
  z-index: 70;
}

/* And the phone's menu with it: it is the nav's sibling, not inside it, and at its own 46 it opened
   under the board (60), the hamburger turning to its X over nothing (the user, 2026-11-03: "that
   hamburger menu is not working"). */
html.is-board .menu {
  z-index: 71;
}

/* Write's Save in the middle under the page, risen over the keyboard while it is up. */
.board__save-bar {
  top: auto;
  right: auto;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  translate: 0 calc(0px - var(--kb, 0px));
  transition: translate 250ms var(--ease-standard);
}

@media (max-width: 699px) {
  .board__save-bar {
    right: auto;
  }
}

/* Write, quieter (the user, 2026-10-29: "the whole page is in focus when I'm writing, which is a bit
   distracting": dim everything else, and the page smaller). The page about four-fifths the size
   it was, more of the wall round it; while it is written on, the nav, the way back and the panel's
   holes fall back, and only the paper and its toolbar stay bright. */
@media (min-width: 700px) {
  .board--write .board__page {
    --mm: min(calc((100vw - 48px) / 297 * 0.8), calc((100vh - 260px) / 210), 2.6px);
  }
}

.board--write .board__holes,
.board--write .board__bar,
html.is-board .nav {
  transition: opacity var(--duration-base) var(--ease-standard);
}

.board--write:has(.board__page-a:focus) .board__holes {
  opacity: 0.35;
}

.board--write:has(.board__page-a:focus) .board__bar {
  opacity: 0.35;
}

html.is-board:has(.board__page-a:focus) .nav {
  opacity: 0.3;
}

/* Write's toolbar: Type, Handwrite (and Undo while writing by hand), Save. In the middle under the
   page, risen over the keyboard while it is up. */
.board--write .board__tools {
  translate: 0 calc(0px - var(--kb, 0px));
  transition: translate 250ms var(--ease-standard);
}

.board__tool--with-icon {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.board__tool--with-icon .icon {
  width: 14px;
  height: 14px;
}

/* Handwriting: a canvas over the whole page, taking the finger or pencil only while Handwrite is on. */
.board__page-ink {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
  touch-action: none;
}

.board__page-ink.is-on {
  pointer-events: auto;
  cursor: crosshair;
}

/* In the margin: where and when, as the wall's labels are (Label type at the page's scale). */
.board__page-meta {
  position: absolute;
  left: calc(var(--page-mm, 3px) * 5);
  top: calc(var(--page-mm, 3px) * 17);
  display: grid;
  gap: calc(var(--page-mm, 3px) * 1.2);
  margin: 0;
  font-size: max(9px, calc(var(--page-mm, 3px) * 2.4));
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  pointer-events: none;
}

.board__page-tag {
  color: var(--primary-700);
}

/* A photograph from the wall, taped over the page's right edge near its foot, a little askew. */
.board__page-photo {
  position: absolute;
  z-index: 2;
  right: calc(var(--page-mm, 3px) * -12);
  bottom: calc(var(--page-mm, 3px) * 14);
  width: calc(var(--page-mm, 3px) * 46);
  margin: 0;
  padding: calc(var(--page-mm, 3px) * 1.6) calc(var(--page-mm, 3px) * 1.6) calc(var(--page-mm, 3px) * 5);
  background: #fbfbfa;
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.08), 4px 10px 20px -10px rgba(16, 42, 67, 0.25);
  transform: rotate(4deg);
  pointer-events: none;
}

.board__page-photo img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.board__tape--photo {
  top: calc(var(--page-mm, 3px) * -1);
  left: 50%;
  transform: translate(-50%, -50%) rotate(-3deg);
}

@media (max-width: 699px) {
  .board__page-photo {
    display: none;
  }
}

/* Draw's toolbar, its tip and the word that it saved in the middle of the screen, as the nav is
   (the user, 2026-10-29: "center align the floating button to the page, just like the top nav"),
   not of what the parts panel leaves. */
.has-library .board__tools,
.has-library .board__tip,
.has-library .board__done {
  left: 50%;
}

@media (min-width: 700px) and (orientation: portrait) {
  .has-library .board__tools,
  .has-library .board__tip,
  .has-library .board__done {
    left: 50%;
  }
}

/* The parts panel opens and folds as the NOVUS component library's panels do (public/lab/
   components.html, .dropdown__panel; the user, 2026-10-29: "follow the motion library of novus"):
   from 6 px above and 98% its size to in place, opacity over 180 ms and the move over 280 ms, both on
   the emphasized ease, hidden once it has gone. Its first arrival plays once and lets go (fill
   backwards), or it would hold the panel and the fold would snap. Under reduced motion it just
   shows and hides. */
.board__library {
  animation-fill-mode: backwards;
  transform-origin: top right;
  visibility: visible;
  transition: opacity 180ms var(--ease-emphasized), transform 280ms var(--ease-emphasized);
}

.board__library.is-folded {
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  filter: none;
  transition: opacity 180ms var(--ease-emphasized), transform 280ms var(--ease-emphasized), visibility 0s 280ms;
}

@media (prefers-reduced-motion: reduce) {
  .board__library,
  .board__library.is-folded {
    transition: none;
  }
}

/* The buttons in the parts panel in design.md's colours (the user, 2026-10-29: "refer design.md").
   Its Buttons: the chosen kind a primary button (--color-primary: Primary 700 with white words,
   800 under the pointer, 900 pressed); the others the outline secondary (Primary 700 rim and
   words, Primary 50 under the pointer). Pill, as filters are; the 2 px focus ring in Primary 500 on
   everything; the parts Primary 50 under the pointer, as that outline button is. */
.board__groups .board__group-chip {
  border: 1.5px solid var(--primary-700);
  background: transparent;
  color: var(--primary-700);
  border-radius: var(--radius-pill);
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    transform 420ms var(--spring);
}

@media (hover: hover) {
  .board__groups .board__group-chip:hover:not([aria-selected="true"]) {
    background: var(--primary-50);
    border-color: var(--primary-700);
    color: var(--primary-700);
  }

  .board__groups .board__group-chip[aria-selected="true"]:hover {
    background: var(--primary-800);
    border-color: var(--primary-800);
  }
}

.board__groups .board__group-chip[aria-selected="true"] {
  background: var(--primary-700);
  border-color: var(--primary-700);
  color: var(--on-primary);
}

.board__groups .board__group-chip[aria-selected="true"]:active {
  background: var(--primary-900);
  border-color: var(--primary-900);
}

.board__groups .board__group-chip:focus-visible,
.board__part:focus-visible {
  outline: 2px solid var(--primary-500);
  outline-offset: 2px;
}

.board__groups .board__group-chip:active {
  transform: scale(0.96);
  transition-duration: 90ms;
}

@media (hover: hover) {
  .board__part:hover {
    background: var(--primary-50);
  }
}

.board__part:active {
  background: var(--primary-50);
}

/* The kinds of part are the design system's small Buttons (.btn--sm: primary for the kind in view,
   secondary for the rest), in one row that scrolls sideways; they keep their own size in it. */
.board__groups .board__group-tab {
  flex-shrink: 0;
}

/* Rubbing out on the page: a ring for a pointer, the size the eraser takes. */
.board__page-ink.is-on.is-rubbing {
  cursor: cell;
}

/* The pen's hint on the page, where the answer starts: the placeholder's grey, with the pen. */
.board__page-hint {
  position: absolute;
  left: calc(var(--mm) * 36);
  top: calc(var(--mm) * 17 + var(--rule) * 4.2);
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: max(15px, calc(var(--mm) * 5.6));
  color: var(--ink-3);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--duration-base) var(--ease-emphasized), transform var(--duration-base) var(--ease-emphasized);
  pointer-events: none;
}

.board__page-hint.is-on {
  opacity: 1;
  transform: none;
}

.board__page-hint .icon {
  width: 1em;
  height: 1em;
  color: var(--primary-700);
}



/* The pad: the page with two more sheets under it, a little askew, as the wall's cards lie over one
   another; in the same paper, their shadow softer, coming in just after the page. */
.board__pad {
  position: relative;
  display: grid;
}

.board__pad > * {
  grid-area: 1 / 1;
}

.board__under {
  border-radius: 2px;
  background: #f8f8f6;
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.05), 4px 10px 22px -12px rgba(16, 42, 67, 0.18);
  pointer-events: none;
  animation: board-rise 620ms var(--ease) 120ms both;
  transition: opacity var(--duration-slow) var(--ease-standard);
}

.board__under--1 {
  transform: translate(6px, 8px) rotate(1.4deg);
}

.board__under--2 {
  background: #f4f5f4;
  transform: translate(-8px, 12px) rotate(-1.8deg);
}

/* A pale blue note in the margin's foot, as the wall's sticky notes are (layout.ts, NOTE_BLUE), a
   touch askew, with a word for whoever hesitates. */
.board__page-note {
  position: absolute;
  z-index: 2;
  left: calc(var(--page-mm, 3px) * 3.5);
  bottom: calc(var(--page-mm, 3px) * 18);
  width: calc(var(--page-mm, 3px) * 23);
  margin: 0;
  padding: calc(var(--page-mm, 3px) * 2.4) calc(var(--page-mm, 3px) * 2.2) calc(var(--page-mm, 3px) * 4);
  background: rgba(190, 228, 255, 0.62);
  box-shadow: 0 1px 2px rgba(16, 42, 67, 0.06), 2px 6px 12px -8px rgba(16, 42, 67, 0.2);
  transform: rotate(-3deg);
  font-size: max(10px, calc(var(--page-mm, 3px) * 3));
  font-weight: 500;
  line-height: 1.2;
  color: var(--primary-800);
  pointer-events: none;
}

/* How much room is left, under the note, once writing has started: Label type, quiet. */
.board__page-count {
  position: absolute;
  left: calc(var(--page-mm, 3px) * 5);
  bottom: calc(var(--page-mm, 3px) * 8);
  margin: 0;
  font-size: max(9px, calc(var(--page-mm, 3px) * 2.4));
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-standard);
  pointer-events: none;
}

.board__page-count.is-on {
  opacity: 1;
}

/* Writing (the caret in the answer, or the pen in hand): only the words, the page and the toolbar
   stay bright (the user, 2026-10-29: "the whole page is in focus when I'm writing, which is a bit
   distracting"). The nav, the way back and the panel's holes fall well back; on the page, the
   photograph, the note and the margin's labels fade; the pad under it too. */
.board--write .board__holes,
.board--write .board__bar,
.board__page-photo,
.board__page-note,
.board__page-meta,
html.is-board .nav {
  transition: opacity var(--duration-slow) var(--ease-standard);
}

.board--write.is-writing .board__holes {
  opacity: 0.25;
}

.board--write.is-writing .board__bar {
  opacity: 0.3;
}

html.is-board:has(.board--write.is-writing) .nav {
  opacity: 0.2;
}

.board--write.is-writing .board__page-photo,
.board--write.is-writing .board__page-note,
.board--write.is-writing .board__page-meta {
  opacity: 0.35;
}

.board--write.is-writing .board__under {
  opacity: 0.55;
}

/* Fallen back, they come forward again under the pointer. */
@media (hover: hover) {
  html.is-board:has(.board--write.is-writing) .nav:hover,
  .board--write.is-writing .board__bar:hover {
    opacity: 1;
  }
}


/* The board takes focus as it opens, with no ring of its own (a ring shows only on what is tabbed to). */
.board__content:focus {
  outline: none;
}

/* Write's card: square, plain, just the question and the answer (the user, 2026-10-29: "square: no
   ruler; remove everything except the header"). 210 mm a side at the screen's scale; the words
   18 mm in from either side, as the wall's cards keep an even margin. */
.board--write .board__page,
.board__page {
  --mm: min(calc((100vw - 48px) / 210), calc((100vh - 260px) / 210), 2.6px);
  width: calc(var(--mm) * 210);
  height: calc(var(--mm) * 210);
}

@media (max-width: 699px) {
  .board--write .board__page,
  .board__page {
    --mm: min(calc((100vw - 32px) / 210), calc((100vh - 200px) / 210));
  }
}

/* Write's card on design.md (the user, 2026-10-29: "fix padding alignment based on the design
   system"): one padding all round, a step of the spacing scale (--space-6, 48 px; 24 px on a
   phone); the question in H3 (28 px, 24 under 768, line height 1.2, Medium), the answer in Body
   (16 px, 1.55), --space-4 under it (set in Page). The words wrap inside the padding, long words too. */
.board__page {
  --pad: var(--space-6);
}

@media (max-width: 699px) {
  .board__page {
    --pad: var(--space-4);
  }
}

.board__page .board__page-q {
  left: var(--pad);
  right: var(--pad);
  top: var(--pad);
  font-size: var(--fs-h3);
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.board__page .board__page-a {
  left: var(--pad);
  right: var(--pad);
  bottom: var(--pad);
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  overflow-wrap: anywhere;
}

.board__page .board__page-hint {
  left: var(--pad);
  right: var(--pad);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

/* The answer's count in the card's foot (Label, quiet), NOVUS blue near the limit; the answer
   stops above it. */
.board__page .board__page-a {
  bottom: calc(var(--pad) + 24px);
}

.board__page-count {
  position: absolute;
  right: var(--pad);
  bottom: var(--pad);
  left: auto;
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--tr-label);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  opacity: 1;
  pointer-events: none;
}

.board__page-count.is-near {
  color: var(--primary-700);
}

/* Saved, as the site's own thanks (.take__stage--thanks): the card left, square to the page,
   wiping in from its edge and leaning a little with the pointer; the words right, the site's
   44 px line in ink then NOVUS blue, its 18 px line in grey, Start again as a secondary button.
   One above the other on a phone. */
.board__sent-in {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 520px);
  align-items: center;
  justify-content: center;
  gap: var(--space-7);
  width: 100%;
  padding: 96px 32px 48px;
  box-sizing: border-box;
}

.board__sent-card {
  --lean: 0deg;
  position: relative;
  margin: 0;
  aspect-ratio: 1;
  transform: rotate(var(--lean));
  transform-origin: 50% 12px;
  transition: transform 900ms var(--ease-emphasized);
}

/* The card itself: the Write card's paper, wiping in from its left edge. */
.board__sent-face {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--space-6) var(--space-4) var(--space-4);
  box-sizing: border-box;
  border-radius: 2px;
  background: #fcfcfb;
  box-shadow: var(--shadow-2), 6px 14px 28px -12px rgba(16, 42, 67, 0.22);
  animation: board-sent-wipe 900ms var(--ease-emphasized) both;
}

.board__sent-card.has-image .board__sent-face {
  padding: var(--space-6) var(--space-3) var(--space-3);
}

.board__sent-face img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.board__sent-text {
  display: -webkit-box;
  -webkit-line-clamp: 8;
  -webkit-box-orient: vertical;
  overflow: hidden;
  align-self: start;
  width: 100%;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink);
  overflow-wrap: anywhere;
}

@keyframes board-sent-wipe {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

/* The wall's glass pin through its top, over the card. */
.board__sent-card .board__sent-pin {
  z-index: 2;
  left: 50%;
  top: 14px;
  animation: board-rise 420ms var(--ease) 700ms both;
}

/* The wall's own thread, at the wall's scale (--pin-k, its px a mm; the user, 2026-10-29: "make sure
   the pin and thread behaviour matches with the novus wall ... reuse the same"): three/World.tsx's
   cord, 0.64 mm across in #58CAFF, a touch self-lit; and its drawn shade (SHADE, threadShade): a
   soft line of rgb(33, 51, 71), 1.3 mm across and 65% at its middle, fading to its edges, moved
   along the key light (from the upper left: 0.42 of the height across, 0.55 down) by the thread's
   height off the card, 3 mm here (never under SHADE_MIN, 2.5). Tied just under the pin's glass head
   (its head 3 mm up and left of the tie, as the wall's pins lean), it runs taut up and to the right,
   off the top of the screen, drawn out once the card is up. */
.board__sent-thread {
  --k: var(--pin-k, 1.6);
  position: absolute;
  z-index: 1;
  left: calc(50% + 3px * var(--k));
  top: calc(21px + 3px * var(--k));
  width: 0;
  height: 0;
  pointer-events: none;
}

.board__sent-cord,
.board__sent-shade {
  position: absolute;
  left: 0;
  width: 140vmax;
  transform-origin: 0 50%;
  transform: rotate(-58deg) scaleX(0);
  animation: board-sent-thread 1100ms var(--ease-emphasized) 900ms forwards;
}

.board__sent-cord {
  top: calc(-0.32px * var(--k));
  height: calc(0.64px * var(--k));
  min-height: 1px;
  background: #58caff;
  box-shadow: 0 0 0 0.25px rgba(88, 202, 255, 0.5);
}

.board__sent-shade {
  top: calc(-0.66px * var(--k));
  height: calc(1.32px * var(--k));
  translate: calc(3px * 0.42 * var(--k)) calc(3px * 0.55 * var(--k));
  background: linear-gradient(rgba(33, 51, 71, 0), rgba(33, 51, 71, 0.65) 50%, rgba(33, 51, 71, 0));
}

@keyframes board-sent-thread {
  to {
    transform: rotate(-58deg) scaleX(1);
  }
}

/* The thread runs off the screen; the screen doesn't scroll for it. */
.board__sent {
  overflow: hidden;
}

.board__sent-words {
  display: grid;
  justify-items: start;
  animation: take-rise 400ms 300ms var(--ease) both;
}

.board__sent-title {
  max-width: 26ch;
  margin: 0;
  font-size: 44px;
  line-height: 1.1;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-wrap: pretty;
  color: var(--ink);
}

.board__sent-title em {
  font-style: normal;
  color: var(--blue-700);
}

.board__sent-hint {
  max-width: 40ch;
  margin: 16px 0 32px;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-3);
}

@media (max-width: 899px) {
  .board__sent-in {
    grid-template-columns: minmax(0, 300px);
    gap: var(--space-5);
    padding: 88px 24px 40px;
  }

  .board__sent-words {
    justify-items: center;
    text-align: center;
  }

  .board__sent-title {
    font-size: 32px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .board__sent-face,
  .board__sent-card .board__sent-pin,
  .board__sent-words {
    animation: none;
  }

  .board__sent-cord,
  .board__sent-shade {
    animation: none;
    transform: rotate(-58deg);
  }
}

/* Write's card colours: the wall's paper, its frosted acrylic, its pale blue film, design.md's
   Primary 50, and NOVUS blue with white words. */
.board__page.board__page--frost {
  background: radial-gradient(90% 90% at 0 0, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 70%), linear-gradient(160deg, #fdfeff, #e9f4fc);
}

.board__page.board__page--film {
  background: #d8eeff;
}

.board__page.board__page--sky {
  background: var(--primary-50);
}

.board__page.board__page--novus {
  background: var(--primary-700);
  color: var(--on-primary);
}

.board__page--novus .board__page-q,
.board__page--novus .board__page-a {
  color: var(--on-primary);
}

.board__page--novus .board__page-q em,
.board__page--novus .board__page-count.is-near {
  color: var(--primary-100);
}

.board__page--novus .board__page-a::placeholder,
.board__page--novus .board__page-count,
.board__page--novus .board__page-hint {
  color: rgba(255, 255, 255, 0.72);
}

.board__page--novus .board__page-hint .icon {
  color: var(--primary-100);
}

.board__page {
  transition: background-color var(--duration-base) var(--ease-standard);
}

/* A little more room between the writing tools and the card's own (colour, Save). */
.board__tool-gap {
  width: var(--space-2);
}

/* The tray: the toolbar's frosted glass, over its middle, opening as the component library's panels
   do (6 px and 98% to in place; opacity 180 ms, the move 280 ms, emphasized). */
.board__tray {
  position: absolute;
  z-index: 4;
  left: 50%;
  bottom: 88px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-3);
  max-width: min(560px, calc(100vw - 32px));
  padding: var(--space-3);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  box-shadow: var(--shadow-3);
  box-sizing: border-box;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 6px) scale(0.98);
  transform-origin: 50% 100%;
  translate: 0 calc(0px - var(--kb, 0px));
  transition: opacity 180ms var(--ease-emphasized), transform 280ms var(--ease-emphasized), visibility 0s 280ms;
}

.board__tray.is-open {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  transition: opacity 180ms var(--ease-emphasized), transform 280ms var(--ease-emphasized);
}

/* A colour: a round of it, 44 px to touch; chosen, ringed in NOVUS blue. */
.board__swatch {
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--fill);
  box-shadow: inset 0 0 0 1px rgba(16, 42, 67, 0.12);
  cursor: pointer;
  transition: box-shadow var(--duration-fast) var(--ease-standard), transform 420ms var(--spring);
}

.board__swatch[aria-pressed="true"] {
  box-shadow: inset 0 0 0 1px rgba(16, 42, 67, 0.12), 0 0 0 2px #fff, 0 0 0 4px var(--primary-700);
}

.board__swatch:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
}

.board__swatch:active {
  transform: scale(0.94);
  transition-duration: 90ms;
}


/* The pen's hint: a scribble that writes itself and starts again, a pen's blue at half strength,
   where the answer begins; gone with the first line. */
.board__page .board__page-hint {
  display: block;
  height: 32px;
}

.board__page-hint svg {
  display: block;
  width: 176px;
  height: 32px;
  overflow: visible;
}

.board__page-hint path {
  fill: none;
  stroke: var(--primary-700);
  stroke-opacity: 0.5;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

/* The first time the pen is picked it writes itself once and fades away; after that, this visit,
   it doesn't show (the user, 2026-10-30: "first time alone draws then disappears"). */
.board__page-hint.is-on path {
  animation: board-scribble 2200ms var(--ease-standard) 300ms both;
}

.board__page-hint.is-seen {
  visibility: hidden;
}

@keyframes board-scribble {
  0% {
    stroke-dashoffset: 1;
    opacity: 1;
  }
  70% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
  100% {
    stroke-dashoffset: 0;
    opacity: 0;
  }
}

/* With reduced motion: no scribble at all. */
@media (prefers-reduced-motion: reduce) {
  .board__page-hint {
    visibility: hidden;
  }
}

.board__page--novus .board__page-hint path {
  stroke: var(--primary-100);
}

/* The sent card as the wall's own cards are: paper, corners all but square, the tag in small spaced
   capitals. A print: the picture to a thin border (the wall's 2 mm, at its scale), its tag and words
   at the foot. A card: the tag at its head, the words set large and anchored to its foot. */
.board__sent-face.board__sent-face--print,
.board__sent-face.board__sent-face--card {
  display: flex;
  flex-direction: column;
  place-items: stretch;
  padding: var(--space-2);
  gap: 0;
}

.board__sent-photo {
  flex: 1;
  min-height: 0;
  display: block;
  background: #fff;
  overflow: hidden;
}

.board__sent-photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.board__sent-tag {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-3);
}

.board__sent-face--print .board__sent-tag {
  margin: var(--space-3) var(--space-2) var(--space-1);
}

.board__sent-caption {
  margin: 0 var(--space-2) var(--space-2);
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: var(--lh-tight);
  color: var(--ink);
}

.board__sent-face.board__sent-face--card {
  justify-content: space-between;
  padding: var(--space-4);
}

.board__sent-face--card .board__sent-text {
  align-self: stretch;
  -webkit-line-clamp: 6;
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

/* A print stands a little taller than it is wide (4:5, as the wall's upright prints), so the square
   card's picture fills its width over the tag and words, with no bands beside it. */
.board__sent-card:has(.board__sent-face--print) {
  aspect-ratio: 4 / 5;
}

.board__sent-photo {
  background: transparent;
}

/* Write's card as a postcard (the user, 2026-10-29: "questions on the left and answer on the right
   and post card type"): A5 on its side, the postcard's own proportion (210 x 148 mm). The question
   on the left half, H3; a line down the middle as a postcard has, the thread's weight in the
   palest blue; on the right half the stamp at the top right (the NOVUS mark on a perforated stamp,
   in Primary 50) with EICMA's postmark over its corner, and under them the answer. design.md's
   spacing: --pad (--space-6) at the edges, --space-4 between. */
.board--write .board__page {
  --card: #fcfcfb;
  --mm: min(calc((100vw - 48px) / 210), calc((100vh - 260px) / 148), 3.6px);
  width: calc(var(--mm) * 210);
  height: calc(var(--mm) * 148);
}

.board--write .board__page--frost {
  --card: #f4f9fd;
}

.board--write .board__page--film {
  --card: #d8eeff;
}

.board--write .board__page--sky {
  --card: var(--primary-50);
}

.board--write .board__page--novus {
  --card: var(--primary-700);
}

.board__page .board__page-q {
  left: var(--pad);
  right: calc(50% + var(--pad) / 2);
  top: var(--pad);
  /* The message side holds just the question: design.md's H2 (40 px, 32 under 768). */
  font-size: var(--fs-h2);
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.board__post-rule {
  position: absolute;
  left: 50%;
  top: var(--pad);
  bottom: var(--pad);
  width: 1px;
  background: var(--primary-100);
  pointer-events: none;
}

.board__post-stamp {
  position: absolute;
  top: var(--pad);
  right: var(--pad);
  display: grid;
  place-items: center;
  width: 56px;
  height: 68px;
  /* The perforated edge: a stamp's teeth, small rounds of the card's own colour bitten out along
     its four edges. */
  --stamp: var(--primary-50);
  background:
    radial-gradient(circle, var(--card) 2px, transparent 2.4px) 0 -3px / 6px 6px repeat-x,
    radial-gradient(circle, var(--card) 2px, transparent 2.4px) 0 calc(100% + 3px) / 6px 6px repeat-x,
    radial-gradient(circle, var(--card) 2px, transparent 2.4px) -3px 0 / 6px 6px repeat-y,
    radial-gradient(circle, var(--card) 2px, transparent 2.4px) calc(100% + 3px) 0 / 6px 6px repeat-y,
    var(--stamp);
  pointer-events: none;
}

.board__post-stamp img {
  width: 28px;
  height: auto;
}

.board__post-mark {
  position: absolute;
  top: calc(var(--pad) + 34px);
  right: calc(var(--pad) + 30px);
  display: grid;
  place-content: center;
  width: 56px;
  height: 56px;
  border: 1.5px solid var(--primary-700);
  border-radius: 50%;
  color: var(--primary-700);
  font-size: 9px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: var(--tr-label);
  text-align: center;
  opacity: 0.55;
  transform: rotate(-12deg);
  pointer-events: none;
}

.board__page .board__page-a,
.board__page .board__page-hint {
  left: calc(50% + var(--pad) / 2);
  right: var(--pad);
  top: calc(var(--pad) + 68px + var(--space-4));
}

.board__page .board__page-a {
  bottom: calc(var(--pad) + 24px);
}

.board__page--sky .board__post-stamp,
.board__page--film .board__post-stamp {
  --stamp: #fff;
}

.board__page--novus .board__post-rule {
  background: rgba(255, 255, 255, 0.3);
}

.board__page--novus .board__post-mark {
  border-color: var(--primary-100);
  color: var(--primary-100);
}

/* On a phone the postcard stands up: the question above, the answer below, the line across. */
@media (max-width: 699px) {
  .board--write .board__page {
    --mm: min(calc((100vw - 32px) / 148), calc((100vh - 200px) / 210));
    width: calc(var(--mm) * 148);
    height: calc(var(--mm) * 210);
  }

  /* Clear of the stamp and its postmark beside it. */
  .board__page .board__page-q {
    right: calc(var(--pad) + 96px);
  }

  .board__post-rule {
    left: var(--pad);
    right: var(--pad);
    top: 42%;
    bottom: auto;
    width: auto;
    height: 1px;
  }

  .board__page .board__page-a,
  .board__page .board__page-hint {
    left: var(--pad);
    top: calc(42% + var(--space-4));
  }
}

/* The postcard's type and spacing follow its own width, not the screen's (the user, 2026-10-29: "fix
   typography sizes, make sure all the text is visible, adjust the padding ... based on design.md"),
   in design.md's steps: from 720 px wide, --space-6 at the edges and the question in H2; narrower,
   --space-5 and H3; under 480 px (a phone), --space-4 and H3. The answer is always Body. The stamp
   steps down with it, its postmark over its lower left corner and clear of the answer, which starts
   --space-4 under the stamp. */
.board--write .board__page {
  container: postcard / inline-size;
}

.board__page > * {
  --stamp-w: 56px;
  --stamp-h: 68px;
  --mark: 48px;
}

.board__page .board__post-stamp {
  width: var(--stamp-w);
  height: var(--stamp-h);
}

.board__page .board__post-mark {
  top: calc(var(--pad) + var(--stamp-h) - var(--mark) * 0.95);
  right: calc(var(--pad) + var(--stamp-w) - var(--mark) * 0.45);
  width: var(--mark);
  height: var(--mark);
  font-size: 9px;
}

.board__page .board__page-a,
.board__page .board__page-hint {
  top: calc(var(--pad) + var(--stamp-h) + var(--space-4));
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.board__page .board__page-q {
  right: calc(50% + var(--pad) / 2);
}

@container postcard (max-width: 719px) {
  .board__page > * {
    --pad: var(--space-5);
    --stamp-w: 48px;
    --stamp-h: 58px;
    --mark: 40px;
  }

  .board__page .board__page-q {
    font-size: var(--fs-h3);
    line-height: 1.2;
  }

  .board__page .board__post-mark {
    font-size: 8px;
  }
}

@container postcard (max-width: 479px) {
  .board__page > * {
    --pad: var(--space-4);
  }

  /* Standing up on a phone: the question across the top, clear of the stamp. */
  .board__page .board__page-q {
    right: calc(var(--pad) + var(--stamp-w) + var(--mark));
  }

  /* The line across a step (--space-5) under the stamp, the answer a step (--space-4) under it. */
  .board__page .board__post-rule {
    top: calc(var(--pad) + var(--stamp-h) + var(--space-5));
  }

  .board__page .board__page-a,
  .board__page .board__page-hint {
    top: calc(var(--pad) + var(--stamp-h) + var(--space-5) + var(--space-4));
  }
}

.board__post-stamp img {
  width: 50%;
}

/* Write, from the wall's own rules (the user, 2026-10-29: "reverse engineer the novus lab's wall and
   other screens and implement a ui for write"). Tokens only. */

/* 1. Arrival ink: each word of the question goes from grey (Greyscale 200) to its own ink, in order,
   the future of mobility last, so it lands in NOVUS blue (the product pages' grey to ink). */
.board__word {
  animation: board-ink var(--duration-slow) var(--ease-standard) both;
  animation-delay: calc(240ms + var(--i) * 90ms);
}

@keyframes board-ink {
  from {
    color: var(--grey-200);
  }
}

/* 2. The filing mark, in the card's foot at the left: Label, grey while blank, NOVUS blue once it
   is a draft; each change rises in, as the site's words do. */
.board__file-mark {
  position: absolute;
  left: var(--pad);
  bottom: var(--pad);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: 1.33;
  letter-spacing: var(--tr-label);
  color: var(--primary-700);
  pointer-events: none;
  animation: board-file 280ms var(--ease-emphasized) both;
}

.board__file-mark.is-blank {
  color: var(--ink-3);
}

@keyframes board-file {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

.board__page--novus .board__file-mark {
  color: var(--primary-100);
}

/* 3. The postmark inks in as the card fills: faint and askew on a blank card, its full strength and
   nearly square by the limit, as if the card were posted as it was written. */
.board__page .board__post-mark {
  opacity: calc(0.2 + 0.5 * var(--progress, 0));
  transform: rotate(calc(-20deg + 10deg * var(--progress, 0)));
  transition: opacity var(--duration-slow) var(--ease-standard), transform var(--duration-slow) var(--ease-emphasized);
}

/* 4. Lift: while it is written on, the card comes a little off the panel, its shadow longer and
   softer, as a wall card does under the pointer; it settles back after. */
.board--write .board__page {
  transition: background-color var(--duration-base) var(--ease-standard), translate var(--duration-slow) var(--ease-emphasized), box-shadow var(--duration-slow) var(--ease-emphasized);
}

.board--write.is-writing .board__page {
  translate: 0 -3px;
  box-shadow: var(--shadow-lift);
}

/* 5. Crop marks just outside the card's corners, as the product pages' photographs have: short
   hairline ticks, the thread's weight, in grey. */
.board__pad::before {
  content: "";
  grid-area: 1 / 1;
  margin: calc(var(--space-3) * -1);
  pointer-events: none;
  --tick: rgba(16, 42, 67, 0.28);
  background:
    linear-gradient(var(--tick), var(--tick)) top left / 10px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) top left / 1px 10px no-repeat,
    linear-gradient(var(--tick), var(--tick)) top right / 10px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) top right / 1px 10px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom left / 10px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom left / 1px 10px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom right / 10px 1px no-repeat,
    linear-gradient(var(--tick), var(--tick)) bottom right / 1px 10px no-repeat;
}

@media (prefers-reduced-motion: reduce) {
  .board__word,
  .board__file-mark {
    animation: none;
  }
}

/* The answer's scrollbar, once it runs past the card: the parts panel's slim one (a 4 px pill in NOVUS
   blue on no track). */
.board__page-a::-webkit-scrollbar {
  width: 12px;
}

.board__page-a::-webkit-scrollbar-track {
  background: transparent;
}

.board__page-a::-webkit-scrollbar-thumb {
  border: 4px solid transparent;
  border-radius: var(--radius-pill);
  background: rgba(7, 116, 184, 0.35) padding-box;
}

.board__page-a::-webkit-scrollbar-button {
  display: none;
}

@supports (-moz-appearance: none) {
  .board__page-a {
    scrollbar-width: thin;
    scrollbar-color: rgba(7, 116, 184, 0.35) transparent;
  }
}

/* One column again, square as before (the user, 2026-10-29: "remove the 2 splits, let's have it as one
   column like how we had before"): the question across the top, clear of the stamp at the top right,
   and the answer the card's full width under it (its top set in Page). The postcard's line is gone. */
/* A rectangle (the user, 2026-10-29: "rectangle"): A5 on its side, 210 x 148 mm; standing up on a
   phone, 148 x 210, so there is room to write there too. */
.board--write .board__page {
  --mm: min(calc((100vw - 48px) / 210), calc((100vh - 260px) / 148), 3.6px);
  width: calc(var(--mm) * 210);
  height: calc(var(--mm) * 148);
}

@media (max-width: 699px) {
  .board--write .board__page {
    --mm: min(calc((100vw - 32px) / 148), calc((100vh - 200px) / 210));
    width: calc(var(--mm) * 148);
    height: calc(var(--mm) * 210);
  }
}

.board__page .board__page-q {
  right: calc(var(--pad) + var(--stamp-w) + var(--mark) * 0.6 + var(--space-4));
}

.board__page .board__page-a,
.board__page .board__page-hint {
  left: var(--pad);
  right: var(--pad);
}

@container postcard (max-width: 479px) {
  .board__page .board__page-q {
    right: calc(var(--pad) + var(--stamp-w) + var(--mark));
  }
}

/* The Write card on an iPad, as the product pages' form is laid out (the user, 2026-10-29: "make it
   responsive for ipad, refer the forms"; .take--split): on its side, the landscape card as large as
   the screen gives it, a touch larger on the 12.9 in (to 4.2 px a mm); held upright (700 to 1023 px
   wide), the card across the screen, 24 px (--space-4) from its sides and at most 720 px wide,
   standing a little taller than wide, so the answer has the height the screen has. Its type and padding step
   with its own width (the postcard container queries above). */
.board--write .board__page {
  --mm: min(calc((100vw - 48px) / 210), calc((100vh - 260px) / 148), 4.2px);
}

@media (min-width: 700px) and (max-width: 1023px) and (orientation: portrait) {
  .board--write .board__page {
    --card-w: min(calc(100vw - var(--space-4) * 2), 720px);
    width: var(--card-w);
    height: min(calc(100vh - 300px), calc(var(--card-w) * 1.12));
  }
}

/* The board's words in the NOVUS components file's text styles (Figma, NOVUS components, Foundations;
   the user, 2026-10-29: "refer this design system and redesign fonts and stuff"), set in PP Neue
   Montreal, for which the file's Inter stands in:
   Button/Small 14 Medium, line 1, +0.5 px: the toolbars' words (Clear, Save, Parts, Rotate, Flip,
   Delete), in sentence case as the file's buttons are, no longer small capitals;
   Field/Input 16 Regular, 1.4: the answer and its placeholder;
   Field/Help 14 Regular, 1.4: the count;
   Tag 12 Medium, 1.33, +4%, capitals: the filing mark and the postmark. */
.board__tool.label {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.5px;
  text-transform: none;
}

.board__page .board__page-a {
  font: 400 16px / 1.4 var(--sans);
  letter-spacing: 0;
}

.board__page .board__page-hint {
  font-size: 16px;
  line-height: 1.4;
}

.board__page .board__page-count {
  font: 400 14px / 1.4 var(--sans);
  letter-spacing: 0;
  text-transform: none;
}

.board__page .board__file-mark,
.board__page .board__post-mark {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.33;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* The postmark holds the Tag's 12 px: 60 px across (52 on a smaller card). */
.board__page > * {
  --mark: 60px;
}

@container postcard (max-width: 719px) {
  .board__page > * {
    --mark: 52px;
  }
}

/* On a laptop the card had less room than the screen gave it (the user, 2026-10-29: "in laptop view this
   card looks too cluttered and it has a overflow ... increase the size of the card and fix padding
   and typography sizes"): it reserves only the nav's and the toolbar's height (200 px), and grows to
   4.6 px a mm on a large screen, so on a laptop it is past 720 px wide and takes the larger step,
   --space-6 and H2. The postmark is large enough for the Tag's 12 px inside its ring (72 px; 60 on a
   smaller card), over the stamp's corner only; the question keeps clear of both. */
@media (min-width: 1024px) and (orientation: landscape) {
  .board--write .board__page {
    --mm: min(calc((100vw - 96px) / 210), calc((100vh - 200px) / 148), 4.6px);
  }
}

.board__page > * {
  --mark: 72px;
}

@container postcard (max-width: 719px) {
  .board__page > * {
    --mark: 60px;
  }
}

.board__page .board__post-mark {
  top: calc(var(--pad) + var(--stamp-h) - var(--mark));
  right: calc(var(--pad) + var(--stamp-w) - var(--mark) * 0.4);
}

/* The glass stickers (data/stickers.json): frosted glass as the site's .glass controls are, translucent,
   what is under them softened and a touch brighter, tinted from the blue ramp; a highlight from the
   upper left, where the wall's key light is, a hairline edge, and a short soft shadow down and to the
   right. In the stamp's and the postmark's places, at their sizes (--stamp-w, --mark). */
.board__page .board__glass-sticker {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0;
  box-sizing: border-box;
  background:
    radial-gradient(120% 90% at 20% 0%, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0) 60%),
    var(--tint);
  -webkit-backdrop-filter: blur(10px) saturate(1.6);
  backdrop-filter: blur(10px) saturate(1.6);
  border: 1px solid rgba(255, 255, 255, 0.7);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 0 rgba(7, 116, 184, 0.12),
    2px 6px 14px -6px rgba(16, 42, 67, 0.3);
  color: var(--ink);
  opacity: 1;
  transform: rotate(var(--turn));
  pointer-events: none;
}

.board__glass-sticker--soft {
  border-radius: 30%;
}

.board__glass-sticker--round {
  border-radius: 50%;
}

.board__glass-sticker--pill {
  border-radius: var(--radius-pill);
}

/* The stamp's place: a soft square the stamp's width, the mark in its middle. */
.board__page .board__glass-sticker.board__post-stamp {
  width: var(--stamp-w);
  height: var(--stamp-w);
}

.board__glass-sticker img {
  width: 46%;
  height: auto;
}

/* The postmark's place: round, its words in the Tag style, over the stamp's lower left corner. */
.board__page .board__glass-sticker.board__post-mark {
  border-radius: 50%;
  opacity: 1;
  transform: rotate(var(--turn));
}

.board__page--novus .board__glass-sticker {
  border-color: rgba(255, 255, 255, 0.45);
}

.board__page--novus .board__glass-sticker.board__post-mark {
  color: var(--on-primary);
}

/* The EICMA sticker over the stamp's lower left corner only, so the NOVUS mark shows; the question
   keeps clear of both. */
.board__page .board__glass-sticker.board__post-mark {
  top: calc(var(--pad) + var(--stamp-w) * 0.45);
  right: calc(var(--pad) + var(--stamp-w) - var(--mark) * 0.2);
}

.board__page .board__page-q {
  right: calc(var(--pad) + var(--stamp-w) + var(--mark) * 0.8 + var(--space-4));
}

/* The glass stickers as stamps, stuck across the card's top right corner as tape is (data/stickers.json;
   the user, 2026-10-29: "add these like a tape in the corner, let the shape be like stamp"): a
   stamp's perforated edge, cut as a row of small rounds along each side (the mask), on the frosted
   glass above; hanging off the card's edges, askew. --sk scales them down on a smaller card. */
.board__page > * {
  --sk: 1;
}

@container postcard (max-width: 719px) {
  .board__page > * {
    --sk: 0.85;
  }
}

.board__page .board__glass-sticker {
  position: absolute;
  z-index: 3;
  gap: 2px;
  border: 0;
  border-radius: 0;
  transform: rotate(var(--turn));
  font-size: 12px;
  font-weight: 500;
  line-height: 1.33;
  letter-spacing: 0.04em;
  -webkit-mask:
    linear-gradient(#000 0 0) center / calc(100% - 8px) calc(100% - 8px) no-repeat,
    radial-gradient(circle at 50% 0, transparent 2px, #000 2.5px) top / 7px 4px repeat-x,
    radial-gradient(circle at 50% 100%, transparent 2px, #000 2.5px) bottom / 7px 4px repeat-x,
    radial-gradient(circle at 0 50%, transparent 2px, #000 2.5px) left / 4px 7px repeat-y,
    radial-gradient(circle at 100% 50%, transparent 2px, #000 2.5px) right / 4px 7px repeat-y;
  mask:
    linear-gradient(#000 0 0) center / calc(100% - 8px) calc(100% - 8px) no-repeat,
    radial-gradient(circle at 50% 0, transparent 2px, #000 2.5px) top / 7px 4px repeat-x,
    radial-gradient(circle at 50% 100%, transparent 2px, #000 2.5px) bottom / 7px 4px repeat-x,
    radial-gradient(circle at 0 50%, transparent 2px, #000 2.5px) left / 4px 7px repeat-y,
    radial-gradient(circle at 100% 50%, transparent 2px, #000 2.5px) right / 4px 7px repeat-y;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85), inset 0 -1px 0 rgba(7, 116, 184, 0.12);
  filter: drop-shadow(2px 4px 6px rgba(16, 42, 67, 0.22));
}

.board__page .board__glass-sticker img {
  width: 44%;
}

/* The stamp's highlight as bright as its JSON says (a blue stamp dimmer, so its white words read),
   and the wall's tape across the card's top left corner, its middle just off the corner so it clears
   the question. */
.board__page .board__glass-sticker {
  background:
    radial-gradient(120% 90% at 20% 0%, rgba(255, 255, 255, var(--shine, 0.75)), rgba(255, 255, 255, 0) 60%),
    var(--tint);
}

.board__page .board__tape--left {
  top: calc(var(--page-mm, 3px) * -2);
  left: calc(var(--page-mm, 3px) * -2);
}

/* No stickers on the card (the user, 2026-10-29: "no remove those stickers"): the question runs the
   card's width, to its padding. */
.board__page .board__page-q {
  right: var(--pad);
}

/* A message's action (Undo after Clear): the design system's text button, in NOVUS blue, the one thing
   in the message that takes a tap. */
.board__done-action {
  margin-left: var(--space-2);
  padding: 6px 10px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--primary-700);
  font: 500 14px / 1 var(--sans);
  letter-spacing: 0.5px;
  cursor: pointer;
  pointer-events: auto;
}

@media (hover: hover) {
  .board__done-action:hover {
    background: var(--primary-50);
  }
}

.board__done-action:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* Writing with the keyboard up, as Apple Notes does on an iPad (the user, 2026-10-29: "this is not the
   ideal way ... see how apple notes app does this"): nothing shrinks and nothing hides behind the
   keyboard. The card fills what the screen has left, from under the nav to a step (--space-3) above
   the toolbar riding on the keyboard, and is one page that scrolls: the question, then the answer as
   tall as its words (Page grows it), the line being written kept in sight; the question scrolls up
   out of the way as the answer runs on. The count rides in the toolbar meanwhile. */
.board__canvas.board--write.has-keyboard .board__page-wrap {
  inset: 72px var(--space-4) calc(var(--kb, 0px) + 24px + 48px + var(--space-3));
  grid-template-rows: minmax(0, 1fr);
  place-items: stretch center;
}

.board--write.has-keyboard .board__page {
  height: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--pad);
  box-sizing: border-box;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.board--write.has-keyboard .board__page::-webkit-scrollbar {
  display: none;
}

.board--write.has-keyboard .board__page .board__page-q,
.board--write.has-keyboard .board__page .board__page-a {
  position: static;
  flex: none;
  width: 100%;
  margin: 0;
}

.board--write.has-keyboard .board__page .board__page-a {
  min-height: calc(1.4em * 4);
  overflow: hidden;
}

.board--write.has-keyboard .board__page .board__page-count,
.board--write.has-keyboard .board__page .board__page-hint {
  display: none;
}

/* The count in the toolbar: Field/Help, grey, NOVUS blue near the limit; only while the keyboard is up. */
.board__tools-count {
  display: none;
  align-items: center;
  padding: 0 var(--space-2);
  font: 400 14px / 1.4 var(--sans);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

.board--write.has-keyboard .board__tools-count {
  display: inline-flex;
}

/* The card as one page that scrolls (Page): the question, what is typed under it (as tall as its words),
   then the sketch area under that, filling the rest and growing with what is drawn; the pen writes
   only there, so ink and typing never overlap. design.md's spacing: the card's padding round it,
   --space-4 between the three; the count stays in the card's foot, outside what scrolls. */
.board__page-body {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--pad) var(--pad) calc(var(--pad) + 28px);
  box-sizing: border-box;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.board__page-body::-webkit-scrollbar {
  display: none;
}

.board__page .board__page-body .board__page-q,
.board__page .board__page-body .board__page-a {
  position: static;
  inset: auto;
  flex: none;
  width: 100%;
  margin: 0;
}

.board__page .board__page-body .board__page-a {
  min-height: calc(1.4em * 2);
  height: auto;
  overflow: hidden;
  resize: none;
}

/* With the pen and nothing typed, the sketch area starts right under the question. */
.board__page-body.is-hand.is-empty .board__page-a {
  display: none;
}

.board__sketch {
  position: relative;
  flex: 1 0 auto;
  min-height: calc(var(--page-mm, 3px) * 36);
}

.board__sketch .board__page-ink {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.board__page .board__sketch .board__page-hint {
  position: absolute;
  left: 0;
  right: auto;
  top: 0;
}

/* The keyboard state is the same page; only its size changes (styles above), not its layout. */
.board--write.has-keyboard .board__page {
  display: block;
  padding: 0;
  overflow: visible;
}

/* Saved: the lab's photograph full bleed and the product pages' frosted sheet rising over it from below
   (SentScreen). Motion from the library, set slow on purpose: the photograph settles from 106% over
   2.4 s, the sheet comes up from below the screen over 1.4 s, both on the emphasized ease, so they
   arrive gently rather than snap; the words rise in (the site's 12 px rise, 600 ms) once the glass
   is nearly there, a beat apart. Reduced motion: it is simply there. */
.board__sent--lab {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--wall);
}

.board__sent-photo {
  position: absolute;
  inset: 0;
}

.board__sent-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 30%;
  animation: board-sent-photo 2400ms var(--ease-emphasized) both;
}

@keyframes board-sent-photo {
  from {
    transform: scale(1.06);
  }
}

/* The photograph's foot fading into the page, as a product page's banner does. */
.board__sent-fade {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(251, 252, 253, 0) 45%, rgba(251, 252, 253, 0.6) 80%, var(--wall));
  pointer-events: none;
}

.board__sent-sheet.sheet {
  position: absolute;
  left: var(--space-5);
  right: var(--space-5);
  top: 26vh;
  bottom: -28px;
  margin: 0;
  padding: clamp(48px, 8vh, 112px) max(48px, calc((100% - 1216px) / 2)) 96px;
  overflow-y: auto;
  animation: board-sent-sheet 1400ms var(--ease-emphasized) 200ms both;
}

@keyframes board-sent-sheet {
  from {
    transform: translateY(calc(74vh + 28px));
  }
}

.board__sent-rise {
  animation: take-rise 600ms var(--ease-emphasized) both;
  animation-delay: calc(1000ms + var(--d, 0) * 120ms);
}

.board__sent-again {
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--sans);
  cursor: pointer;
  align-items: center;
}

.board__sent-again .icon {
  width: 14px;
  height: 14px;
}

@media (max-width: 899px) {
  .board__sent-sheet.sheet {
    left: var(--space-3);
    right: var(--space-3);
    top: 30vh;
    padding: 40px 24px 72px;
  }

  .board__sent-sheet .sheet__headline {
    font-size: var(--fs-h2);
  }

  .board__sent-sheet .sheet__words {
    grid-column: 1 / -1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .board__sent-photo img,
  .board__sent-sheet.sheet,
  .board__sent-rise {
    animation: none;
  }
}


/* Saved: the wall in 3D, close up and straight on (ui/board/SimWall.tsx, three/Closeup.tsx), filling
   the screen; 2 s after the visitor's pin goes in, 3.4 s in, the product pages' frosted sheet (.sheet)
   rises from below over the lower part of it (1.2 s, the emphasized ease), so the landing and the
   thanks read as one motion (the user, 2026-10-30: "make the landing and pop up seamless, now it
   is too much time"), the wall showing through it, and its words rise in once it is nearly
   there. Reduced motion: it is simply there. */
.sim {
  overflow: hidden;
}

/* Waiting, ready, until Save (ui/board/Canvas.tsx, `warm`): there, but not seen or touched. Its
   motion plays only once it is shown. */
.sim:not(.is-live) {
  visibility: hidden;
  pointer-events: none;
}

.sim:not(.is-live) * {
  animation-play-state: paused !important;
}

.sim__view {
  position: absolute;
  inset: 0;
  /* The wall fades up under the board's Write or Draw as it goes, rather than appear at once. */
  animation: sim-in 500ms var(--ease-emphasized) both;
}

@keyframes sim-in {
  from {
    opacity: 0;
  }
}

.sim__sheet.sheet {
  position: absolute;
  z-index: 2;
  left: var(--space-5);
  right: var(--space-5);
  /* The lower half of the screen, the notes in view above it (the user, 2026-10-30: "reduce the
     height of the bottom pop up", then "let the pop up occupy more vertical height"). */
  top: 44vh;
  bottom: -28px;
  margin: 0;
  padding: clamp(32px, 5vh, 56px) clamp(24px, 5vw, 56px) 56px;
  overflow-y: auto;
  /* A lighter blur than the product pages' sheet: redone over the moving 3D on every frame of its
     rise, 30 px dropped frames to 50 to 200 ms. */
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  backdrop-filter: blur(16px) saturate(1.1);
  will-change: transform;
  animation: sim-sheet 1200ms var(--ease-emphasized) 3400ms both;
}

/* From wholly below the screen, by its own height: by 56vh, a sheet taller than that (with the save
   screen's questions on it) showed its top, bare, for the 3.4 s before it rose (the user, 2026-11-02:
   "the time at which the pop up shows is faulty"). */
@keyframes sim-sheet {
  from {
    transform: translateY(calc(100% + 28px));
  }
}

/* One layout on every screen (the user, 2026-10-30: monitor, iPad on its side and upright side by
   side, "find a way to make it uniform, padding fix"): one column, centred in the sheet, the
   logo, the headline, what happens next and Start again under each other, left aligned, on the
   spacing scale; the type steps down with the screen's width. */
.sim__sheet-in {
  position: relative;
  display: grid;
  justify-items: start;
  gap: 0;
  width: min(100%, 640px);
  margin: 0 auto;
}

/* Over the product pages' own setting of the headline (its 12 column grid, 72 px). */
.sim__sheet .sheet__headline.sim__title {
  grid-column: auto;
  max-width: none;
  margin: 0 0 var(--space-3);
  font-size: clamp(36px, 4.2vw, 44px);
  line-height: 1.08;
}

.sim__words {
  display: grid;
  justify-items: start;
  gap: var(--space-4);
}

.sim__words .sheet__text {
  max-width: 52ch;
  font-size: 16px;
}

/* The lab's mark at the head of the sheet, the Vision card's own (images/home/novus-labs-logo.png),
   never cropped: the file holds the mark with transparent space round it (1215 x 401 of its 1400 x
   605), so it is set by the mark, 32 px of mark (--logo-h is the file's height), and drawn back by the
   space at its top, left and foot, so the mark itself lines up with the headline's left edge and sits
   32 px over it (the user, 2026-10-30: "rethink the logo size, placing, padding"). Headline to its
   line 12 px, line to the button 24 px. */
.sim__logo {
  --logo-h: 48px;
  display: block;
  width: auto;
  height: var(--logo-h);
  margin: calc(var(--logo-h) * -0.17) 0 calc(var(--logo-h) * -0.167 + var(--space-5)) calc(var(--logo-h) * -0.149);
}

.sim__rise {
  animation: take-rise 600ms var(--ease-emphasized) both;
  animation-delay: calc(4000ms + var(--d, 0) * 140ms);
}

@media (max-width: 899px) {
  .sim__sheet.sheet {
    left: var(--space-3);
    right: var(--space-3);
    top: 42vh;
  }
}

/* Upright, the sheet is as tall as what it holds, at the foot of the screen, not 58% of it with a
   bare stretch under Start again (the user, 2026-10-30: "reduce the bottom padding in the
   portrait"); its foot runs 28 px off the screen, so that much more padding there. */
/* (On every screen now, not only upright: on a big monitor it ran 56% of the screen high with a wide
   bare stretch under Start again; the user, 2026-10-30: "in big monitors the bottom padding is too
   big".) */
.sim__sheet.sheet {
  top: auto;
  max-height: 60vh;
  padding-bottom: calc(var(--space-6) + 28px);
}

@media (prefers-reduced-motion: reduce) {
  .sim__view,
  .sim__sheet.sheet,
  .sim__rise {
    animation: none;
  }
}

/* Below 1100 px the toolbar, centred on the page, reaches under the parts panel (the user,
   2026-10-30, a screenshot at 690 px: Save hidden under it): there the panel stops above the
   toolbar and its tip, so all of them show. */
@media (max-width: 1099px) {
  .board--draw .board__library {
    bottom: 128px;
  }
}

/* On an iPad the panel as far from the screen's top as from its foot (the user, 2026-10-30: "make
   sure padding top and bottom of the parts card is the same from the margin"; it was 16 px and
   128 px): 88 px each, clear of the nav above and 16 px over the toolbar below. */
@media (min-width: 700px) and (max-width: 1099px) {
  .board--draw .board__library {
    top: 88px;
    bottom: 88px;
  }
}

/* The kinds of part as smaller pills on an iPad and an iPad mini, upright or on its side (the user,
   2026-10-30: "for mini + ipad, reduce the pill size"): 36 px, 13 px (the design system's small
   Button is 44 px; a phone's are 32). */
@media (min-width: 700px) and (max-width: 1199px) {
  .board--draw .board__groups .board__group-tab {
    --h: 36px;
    padding: 0 14px;
    font-size: 13px;
  }
}

/* On an iPad the hint over the toolbar's middle, lined up with it (the user, 2026-10-30: "see the
   hint position, fix it"; set in the middle of what the panel left, it sat off to one side); its
   words short enough to keep clear of the panel. */
@media (min-width: 700px) and (max-width: 1099px) {
  .has-library .board__tip {
    left: 50%;
  }
}

/* The collaboration wall on a phone (the user, 2026-10-30, screenshots at 375 px: "in phone fix the
   ui", "increase the size of the card, utilise the white space", "let the character limit be on a
   separate [row] so nothing overwrites it", "fix the button spacing and shape, maybe a clear icon for
   mobile alone", "center align the top nav and back button across all devices", "remove scroll from
   pop up"). */

/* The way back and the nav, their middles on one line: the nav's pill is 48 px tall 14 px down (44
   px, 10 px down on a phone); the round of glass is 48 px. */
/* (The back button is the design system's small secondary button, 44 px: its middle on the nav's,
   38 px down, 32 on a phone.) */
.board__canvas .board__bar {
  top: 16px;
}

@media (max-width: 767px) {
  .board__canvas .board__bar {
    top: 10px;
  }
}

/* Back: the arrow before the word, as a way back reads (.board__way-back: .board__back is the round
   chip of before). */
.board__way-back .icon {
  order: -1;
}

/* The count in a row of its own at the card's foot: what is typed and drawn scrolls above it, never
   under it. */
.board__page .board__page-body {
  bottom: calc(var(--pad) + 24px);
  padding-bottom: var(--space-3);
}

/* Clear: a word, and on a phone the design system's trash icon in its place, as the other tools are. */
.board__clear-icon {
  display: none;
}

/* Save likewise: a word, and on a phone its icon (below). */
.board__save-icon {
  display: none;
}

/* A phone: every tool an icon, so the toolbar fits on one row with no scroll down to 320 px (the user,
   2026-11-03: "let the mobile floating button not have scroll - make it icons and fix the spacing"; at
   360 px Draw's ran 10 px over and scrolled, Save cut in half). Eight round chips, as wide as fit, evenly
   spread; Save the primary blue still, a chip like the rest. Back is its arrow alone, so it clears the
   nav's pill (it ran 6 px under it at 360 px, 26 px at 320). */
@media (max-width: 699px) {
  .board .board__tools,
  .board .has-library .board__tools {
    overflow: visible;
    padding: 4px;
  }

  .board .board__tools .board__tool,
  .board .board__tools .board__tool.board__save {
    width: min(36px, calc((100vw - 24px - 8px - 7 * 2px) / 8));
    min-width: 0;
    padding: 0;
    flex: none;
  }

  .board .board__tool--help {
    margin-left: 0;
  }

  /* While the keyboard is up, the count just over the toolbar's right end, not a ninth chip in it
     (it ran 72 px out of the pill at 320 px). */
  .board .board--write.has-keyboard .board__tools-count {
    position: absolute;
    right: 12px;
    bottom: calc(100% + 6px);
    padding: 0;
    font-size: 12px;
  }

  .board__parts-word,
  .board__save-word {
    display: none;
  }

  .board__save-icon {
    display: block;
    width: 20px;
    height: 20px;
  }

  .board__tool--parts .icon {
    width: 20px;
    height: 20px;
  }

  /* No gap: Button wraps the hidden word in a span of its own, still a flex item, and the gap beside it
     pushed the arrow 4 px left of the circle's middle. */
  .board .board__way-back {
    width: var(--h);
    padding: 0;
    gap: 0;
  }

  .board .board__way-back .board__way-back-word {
    display: none;
  }
}

@media (max-width: 699px) {
  /* The way in: the line over three, the two ways side by side, all on the screen without a scroll. */
  .board__choose-words .board__title {
    max-width: none;
    font-size: 34px;
    line-height: 1.08;
  }

  .board__choose-in .board__ways {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: 100%;
    gap: var(--space-3);
  }

  .board__choose-in .board__way {
    min-height: 0;
  }

  /* Both ways' names on one line across: the words follow the picture, not pushed to the card's
     foot (Write's line runs to three, Draw's to two; the user: "looks uneven"). */
  .board__choose-in .board__way-art {
    width: 120px;
    height: 52px;
    margin-left: 0;
    margin-bottom: var(--space-2);
  }

  /* No crop marks round Write's card: the card runs to 16 px from the screen's sides, and they were
     cut off at its edges (the user: "those arrows are being cropped, remove it"). */
  .board__pad::before {
    display: none;
  }

  /* Write's card as large as the screen leaves it: its width less 16 px a side, its height less the
     nav and back above and the toolbar below (not while the keyboard is up, which sizes it itself). */
  .board--write:not(.has-keyboard) .board__page {
    width: calc(100vw - 32px);
    height: calc(100dvh - 168px);
  }

  /* The toolbar across the screen, its tools spread evenly, every one a 36 px round chip; Clear as
     its icon; Save the design system's primary pill, wider than a chip. */
  .board__tools,
  .has-library .board__tools {
    width: min(calc(100vw - 24px), 400px);
    justify-content: space-between;
    gap: 2px;
    box-sizing: border-box;
  }

  .board__tools .board__tool {
    padding: 0;
    width: 36px;
  }

  .board__tools .board__tool.board__save {
    width: auto;
    min-width: 64px;
    padding: 0 16px;
  }

  .board__tools .board__tool--parts {
    width: auto;
    padding: 0 12px;
  }

  .board__tools .board__tool-gap {
    display: none;
  }

  .board__clear-icon {
    display: block;
    width: 20px;
    height: 20px;
  }

  /* The parts library across the screen, 12 px from its sides as the toolbar is (it was 288 px,
     against the left, with a bare strip at its right). */
  .board--draw .board__library {
    left: 12px;
    right: 12px;
    width: auto;
    /* Docked 12 px over the toolbar (16 px up, 48 px tall), and a third of the screen high at most,
       so most of the canvas stays in view (the user, 2026-10-30: "reduce the padding between the
       parts card and the toolbar; it hides 60% of the canvas, maybe up to 30%"). */
    top: auto;
    bottom: 76px;
    height: max(220px, 32dvh);
  }

  /* The hint under the canvas is the panel's place while it is open. */
  .has-library .board__tip {
    display: none;
  }

  /* The library tighter on a phone (the user, 2026-10-30: "reduce the bottom padding in between,
     reduce the overall size of the pills and components"): the kinds as 32 px pills, 13 px; three
     parts to a row, each its picture at 44 px with 8 px round it; 4 px between rows, 16 px between
     kinds. */
  .board--draw .board__groups .board__group-tab {
    /* The design system's Button takes its height from --h (.btn--sm: 44 px). */
    --h: 32px;
    padding: 0 var(--space-3);
    font-size: 13px;
  }

  .board--draw .board__kind-parts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    row-gap: var(--space-1);
  }

  .board--draw .board__part {
    padding: var(--space-2) var(--space-1);
    gap: var(--space-1);
  }

  .board--draw .board__part-art,
  .board--draw .board__part-art svg {
    height: 44px;
  }

  .board--draw .board__part-name {
    font-size: 12px;
    line-height: 1.25;
  }

  .board--draw .board__kind + .board__kind {
    margin-top: var(--space-4) !important;
  }

  .board__clear-word {
    display: none;
  }

  /* The thanks as tall as what it holds, at the foot, its words a step smaller: nothing to scroll. */
  .sim__sheet.sheet {
    top: auto;
    max-height: none;
    overflow: hidden;
    padding: var(--space-5) var(--space-4) calc(var(--space-5) + 28px);
  }

  .sim__sheet .sheet__headline.sim__title {
    font-size: 28px;
  }

  .sim__logo {
    --logo-h: 36px;
    margin-bottom: calc(var(--logo-h) * -0.167 + var(--space-4));
  }

  .sim__words .sheet__text {
    font-size: 15px;
  }
}

/* Draw's canvas as Write's is while being written on (the user, 2026-10-30): the whole canvas, its dots
   fallen back. (A card under the drawing, Write's own, was tried and taken out: "just retain the
   canvas".) */
.board--draw .board__holes--sheet {
  opacity: 0.25;
}

/* The way in, laid out again (the user's lead, 2026-10-30: "can we try a different layout for this
   page? the heading width looks a bit off with two words in the second line"): the line breaks
   evenly everywhere, never one or two words left on the last; on a wide screen (a laptop, an iPad on
   its side) the words on the left, over three lines, "Imagine the / future of mobility / with us.",
   and the two ways beside them on the right, both on the screen's middle; upright, one column as
   before. */
.board__title {
  text-wrap: balance;
}

/* On every screen the same three phrases, the blue one on its own line: "Imagine the / future of
   mobility / with us." (left to balancing, "with" went up beside it and "us." was left alone). */
.board__choose-words .board__title {
  max-width: none;
}

.board__choose-words .board__title em {
  display: block;
  white-space: nowrap;
}

.board__choose-in .board__ways {
  margin-top: var(--space-5);
}

@media (min-width: 1000px) and (orientation: landscape) {
  .board__choose-in {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    justify-items: start;
    gap: var(--space-8);
    width: min(1120px, 100%);
    padding: 96px 48px 48px;
    text-align: left;
  }

  .board__choose-words {
    justify-items: start;
  }

  .board__choose-words .board__title {
    font-size: 56px;
    line-height: 1.05;
  }

  .board__choose-in .board__ways {
    margin-top: 0;
    grid-template-columns: repeat(2, 264px);
  }

  /* Both ways' names on one line across: the words follow the picture, not pushed to the foot. */
  .board__choose-in .board__way-art {
    margin-bottom: var(--space-2);
  }
}

/* Side by side as on any wide screen, the line still 56 px; under 1100 px, a smaller gap and slightly
   narrower ways leave its column the 330 px "future of mobility" needs (the user, 2026-11-03: it ran
   under the Write card from 1000 px; "we want the headings beside sideways only", "like before"). */
@media (min-width: 1000px) and (max-width: 1099px) and (orientation: landscape) {
  .board__choose-in {
    gap: var(--space-5);
  }

  .board__choose-in .board__ways {
    grid-template-columns: repeat(2, 228px);
  }
}

/* A save that didn't go: its icon in the error red. */
.board__done.is-error svg {
  color: var(--error);
}

/* Write and Draw's way back: the arrow alone, on the wall's round of glass (Button, glass), at
   the top left (the user, 2026-10-29: "remove the title from the top - just lets have the back
   button"). */
.board__bar {
  position: absolute;
  z-index: 3;
  top: 16px;
  left: 32px;
}

/* Pen, Eraser and Undo as icons, each a round 36 px chip, the icon at 20 px. */
.board__tools .board__tool--icon {
  width: 36px;
  padding: 0;
  font-size: 20px;
}

/* ---- Write: one page of the foot card's notebook paper, pinned to the panel in the middle of the
   screen (the user, 2026-10-29: "a single paper with larger text: Imagine the future of mobility
   with us, and the user should be able to add their answers in it itself"). Drawn as the foot card
   is (faces.ts, `ruled`): rules every 9 mm in the wall's pale blue from 26 mm down, the warm margin
   line at 30 mm, the words from 6 mm past it, all in the page's own millimetres (--mm), so it
   keeps its look at any size. The question sits on the first rules, the answer on the rules below,
   a line to a rule. */
.board__page-wrap {
  position: absolute;
  inset: 88px 24px 96px;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.board__page {
  --mm: min(calc((100vw - 48px) / 297), calc((100vh - 200px) / 210), 3.2px);
  --rule: calc(var(--mm) * 9);
  position: relative;
  width: calc(var(--mm) * 297);
  height: calc(var(--mm) * 210);
  border-radius: 2px;
  background-color: #fcfcfb;
  box-shadow: var(--shadow-2), 6px 14px 28px -12px rgba(16, 42, 67, 0.22);
  pointer-events: auto;
  animation: board-rise 520ms var(--ease) both;
}

/* The question: large, Medium, on two rules (its line-height two of them), the first words in ink
   and the future of mobility in NOVUS blue. */
.board__page-q {
  position: absolute;
  left: calc(var(--mm) * 36);
  right: calc(var(--mm) * 14);
  top: calc(var(--mm) * 17 + var(--rule) * 0.4);
  margin: 0;
  font-size: calc(var(--mm) * 14);
  line-height: calc(var(--rule) * 2);
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.board__page-q em {
  font-style: normal;
  color: var(--blue-700);
}

/* The answer, written on the rules: one line to a rule, its words sitting on the line. */
.board__page-a {
  position: absolute;
  left: calc(var(--mm) * 36);
  right: calc(var(--mm) * 14);
  top: calc(var(--mm) * 17 + var(--rule) * 4);
  bottom: calc(var(--mm) * 6);
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  resize: none;
  outline: none;
  font: 400 max(16px, calc(var(--mm) * 6.4)) / var(--rule) var(--sans);
  color: var(--ink);
  overflow-y: auto;
}

.board--write.has-keyboard .board__page-wrap {
  place-items: start center;
}

.board--write.has-keyboard .board__page-a {
  bottom: max(calc(var(--mm) * 6), var(--clip, 0px));
}

.board__page-a::placeholder {
  color: var(--ink-3);
}

@media (max-width: 699px) {
  .board__bar {
    left: 16px;
  }

  .board__page-wrap {
    inset: 80px 12px 88px;
  }

  .board__page {
    --mm: min(calc((100vw - 24px) / 210), calc((100vh - 168px) / 297));
    width: calc(var(--mm) * 210);
    height: calc(var(--mm) * 297);
  }

  .board__page-q {
    font-size: calc(var(--mm) * 12);
  }
}

@media (prefers-reduced-motion: reduce) {
  .board__canvas,
  .board__choose-in,
  .board__drift-item,
  .board__drift-art,
  .board__library,
  .board__part,
  .board__piece-bar,
  .board__choose,
  .board__way,
  .board__piece,
  .board__snap {
    animation: none !important;
  }
}

/* Tags: the dot and label once repeated in every section of the old site, made one thing. Blue,
   grey and green only (indigo, Vida and red were "dont need"). */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 10px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-label);
  line-height: 1.33;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  font-weight: 500;
  white-space: nowrap;
  background: var(--grey-50);
  color: var(--ink-2);
}

.tag::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.tag--blue {
  background: var(--primary-50);
  color: var(--primary-700);
}

.tag--success {
  background: var(--success-bg);
  color: var(--success-text);
}

.tag--success::before {
  background: var(--success);
}

.tag.tag--bare {
  padding: 0;
  background: none;
}

/* Chips: for choosing, a filter that's on or off, or one you can remove. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0;
  min-height: 44px;
  padding: 0 16px;
  border: 1.5px solid var(--blue-100);
  border-radius: var(--radius-pill);
  background: #fff;
  font-family: inherit;
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    transform 420ms var(--spring);
}

.chip .icon {
  width: 14px;
  height: 14px;
  vertical-align: 0;
}

/* The tick takes no room while the chip is off, the gap after it included, so the words sit in the
   chip's middle (with a 6 px gap that stayed, they were 6 px right of centre). */
.chip__check {
  display: inline-flex;
  width: 0;
  margin-right: 0;
  overflow: hidden;
  transition: width var(--duration-base) var(--ease-emphasized), margin-right var(--duration-base) var(--ease-emphasized);
}

@media (hover: hover) {
  .chip:hover:not(:disabled) {
    border-color: var(--blue-200);
  }
}

.chip:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

.chip:active:not(:disabled) {
  transform: scale(0.96);
  transition-duration: 90ms;
}

.chip[aria-pressed="true"] {
  background: var(--blue-50);
  border-color: var(--blue-50);
  color: var(--blue-700);
}

.chip[aria-pressed="true"] .chip__check {
  width: 14px;
  margin-right: 6px;
}

.chip:disabled {
  background: var(--disabled-bg);
  border-color: var(--disabled-bg);
  color: var(--disabled-text);
  cursor: not-allowed;
}

.chip--removable {
  gap: 6px;
  padding-right: 6px;
  cursor: default;
}

.chip__remove {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}

.chip__remove .icon {
  width: 12px;
  height: 12px;
}

@media (hover: hover) {
  .chip__remove:hover {
    background: var(--blue-50);
    color: var(--blue-700);
  }
}

.chip__remove:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ------------------------------------------------------------------------------------------ */
/* {04} Your take, on NEX 1's and NEX 2's pages (ui/YourTake.tsx; from the form lab's concept A,
   "the thread", public/lab/forms.html). Set in the page's own language (the user, 2026-10-27:
   "follow the same ui style throughout the page"): open on the page, no panels or cards; each
   step as a feature is set (.story__block), its number large in the first four columns, its name
   small in blue and the question large from the sixth; answers as the index's rows (.index__row),
   figures as its numerals, photographs as its prints. For an iPad: targets 64 px and up; spacing
   on design.md's scale; its motion (150 / 250 / 400 ms). */

.take {
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --hole: rgba(16, 42, 67, 0.1);
  --error: #ce2c31;
  --blue-800: #055282;
  --shadow-1: 0 1px 3px rgba(16, 42, 67, 0.06);
  --shadow-2: 0 4px 12px rgba(16, 42, 67, 0.08);
  scroll-margin-top: 80px;
}

.take__blue {
  color: var(--blue-700);
}

/* As the overview: the line large on the left, the paragraph lower right. */
.take__intro {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  row-gap: 24px;
  align-items: end;
}

.take__head {
  grid-column: 1 / span 7;
  margin: 0;
  font-size: 56px;
  line-height: 1.04;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.take__sub {
  grid-column: 8 / -1;
  max-width: 40ch;
  margin: 0;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-2);
}


/* As the page's blocks: the intro and the steps rise in once, the first time they come into view,
   and nothing in a step plays until then. */
.take.has-motion :is(.take__intro, .take__module) {
  transition: opacity 700ms var(--ease), transform 900ms var(--ease);
}

.take.has-motion :is(.take__intro, .take__module):not(.is-in) {
  opacity: 0;
  transform: translateY(32px);
}

.take--split.has-motion .take__intro:not(.is-in) {
  transform: none;
}

.take.has-motion .take__module:not(.is-in) * {
  animation-play-state: paused;
}

/* A question's words go from grey to ink one after another as it comes in, as a feature's words do
   as they come up the page. */
.take.has-motion .take__w {
  animation: take-ink 600ms var(--ease-standard) backwards;
  animation-delay: calc(260ms + var(--i) * 55ms);
}

@keyframes take-ink {
  from {
    color: var(--ink-3);
  }
}

/* One height for every step (the user, 2026-10-27: "when i mean the section to be fixed i meant the
   section height so that it is uniform"): the height of its tallest step (YourTake measures it,
   --take-h), so what follows never moves as the steps change. Each step keeps its own spacing
   from the top; what a shorter one leaves over is at the section's end, not inside the step (the
   user: "fix the spacing of this better"; a screen's height opened gaps inside short steps). */
.take__module {
  min-height: var(--take-h, 0px);
  margin-top: 96px;
  /* Where a step lands when it's brought into view: clear of the fixed nav (72 px). */
  scroll-margin-top: 88px;
}

/* A step: the question, then its answers right under it, then the way back. */
.take__stage {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 32px;
  align-items: start;
}

.take__words,
.take__answers,
.take__foot {
  grid-column: 1 / span 8;
  min-width: 0;
}

.take__words {
  animation: take-rise 400ms 40ms var(--ease) both;
}

.take__answers {
  margin-top: 40px;
  animation: take-rise 400ms 100ms var(--ease) both;
}

.take__stage--photo .take__answers,
.take__stage--photo .take__foot,
.take__stage--photo .take__words {
  grid-column: 1 / -1;
}

.take__q {
  max-width: 26ch;
  margin: 0;
  font-size: 44px;
  line-height: 1.1;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-wrap: pretty;
}

.take__q:focus {
  outline: none;
}

.take__hint {
  max-width: 40ch;
  margin: 16px 0 0;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-3);
}

/* The specs a version comes with, set as design.md's Metric: the figure large, its name small over
   it, side by side, no rules. Under each version's photograph and, on NEX 2's price step, under the
   question, the same three in the same order, so they read across. */
.take__given {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 40px;
  margin: 24px 0 0;
}

.take__given > :is(span, div) {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.take__dt {
  font-size: 12px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.take__dd {
  margin: 0;
  font-size: 28px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: -0.02em;
  white-space: nowrap;
  color: var(--ink);
}

/* A version's specs in its answer row, as the price step's (the user, 2026-10-29: "add it like
   this"): each name small over its figure, the three side by side; ink and grey, chosen or not. */
/* Small (the user, 2026-10-29: larger, they were "tooooo cluttered"), each as wide as it is, the
   same space either side of each rule (fixed columns left it "very uneven"). */
.take__given--opt {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 0;
  margin-top: 10px;
}

.take__given--opt > span {
  flex: none;
  gap: 5px;
}

/* A faint rule between the three (the user, 2026-10-29: "add divider lines between the three
   metrics faintly"; asked for, so the exception to no hairlines). */
.take__given--opt > span + span {
  margin-left: 20px;
  padding-left: 20px;
  border-left: 1px solid rgba(16, 42, 67, 0.12);
}

.take__given--opt .take__dt {
  font-size: 10.5px;
}

.take__given--opt .take__dd {
  font-size: 17px;
  letter-spacing: -0.01em;
}

.take__given--opt small {
  margin-left: 3px;
  font-size: 12px;
}

.take__given small {
  margin-left: 4px;
  font-size: 14px;
}

.take__foot {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 56px;
  margin-top: 40px;
  animation: take-rise 400ms 160ms var(--ease) both;
}

.take__module.is-back :is(.take__words, .take__answers) {
  animation-name: take-rise-back;
}

/* Between steps: the answered one fades up and away (200 ms), the next rises in (400 ms). */
.take__module.is-leaving .take__stage {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 200ms var(--ease-standard), transform 200ms var(--ease-standard);
}

@keyframes take-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}

@keyframes take-rise-back {
  from {
    opacity: 0;
    transform: translateY(-12px);
  }
}

/* Answers. Rows as the index's: the design system's radio, the answer large, its note in blue under
   it, no rules; chosen, its radio fills and it turns blue, and the others step back. */
.take__opts {
  display: flex;
  flex-direction: column;
}

.take__opt {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 16px;
  align-items: start;
  width: 100%;
  min-height: 72px;
  padding: 16px 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: opacity 250ms var(--ease-standard), transform 150ms var(--ease-standard);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
}

.take__opt:active {
  transform: scale(0.99);
}

.take__opt:focus-visible {
  outline: none;
}

.take__opts:has([aria-checked="true"]) .take__opt[aria-checked="false"] {
  opacity: 0.45;
}

/* The radio (.choice--radio), level with the answer's first line; its states as the design
   system's, read from the answer it marks. */
.take__radio {
  min-height: 0;
  height: 29px;
}

.take__opt[aria-checked="true"] .choice__box {
  background: var(--blue-700);
  box-shadow: none;
}

.take__opt[aria-checked="true"] .choice__box::after {
  transform: scale(1);
}

.take__opt:focus-visible .choice__box {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

@media (hover: hover) {
  .take__opt[aria-checked="false"]:hover .choice__box {
    box-shadow: inset 0 0 0 1.5px var(--primary-500);
  }
}

.take__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.take__label {
  font-size: 24px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -0.01em;
  transition: color 250ms var(--ease-standard);
}

.take__opthint {
  max-width: 40ch;
  font-size: 15px;
  line-height: 1.45;
  color: var(--blue-700);
}

.take__opt[aria-checked="true"] .take__label,
.take__opt[aria-checked="true"] .take__num {
  color: var(--blue-700);
}

/* Figures set large, as the page's numerals. */
.take__opts--metric {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 16px 56px;
}

.take__opt--metric {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  width: auto;
  min-height: 88px;
  padding: 8px 0;
}

.take__opt--metric .take__radio {
  height: auto;
}

/* The figures, each with its radio, in one row: the full width. */
.take__answers:has(.take__opts--metric) {
  grid-column: 1 / -1;
}

/* PP Neue Montreal, as the rest of the form (the user, 2026-10-29: "use pp neue montreal"; it was
   Milling, the page's numerals). */
.take__num {
  font-family: var(--sans);
  font-size: 88px;
  line-height: 0.9;
  font-weight: 500;
  letter-spacing: -0.03em;
  white-space: nowrap;
  transition: color 250ms var(--ease-standard);
}

.take__unit {
  margin-left: 8px;
  font-family: var(--sans);
  font-size: 20px;
  color: var(--ink-3);
}

/* Photographs as the page's prints: the shot with its crop marks, its words under it. */
.take__opts--photo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px;
}

.take__opt--photo {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 0;
}

.take__print {
  position: relative;
  display: block;
  transform-origin: 0 0;
  rotate: calc(var(--sway, 0) * var(--side, 1) * 1deg);
}

.take__img {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--radius);
  transition: box-shadow 250ms var(--ease-standard);
}

/* The wipe, as the page's prints: the frame comes in from the outer edge (--side: 1 from the left,
   -1 from the right) while the picture inside holds still, and the picture settles from a little
   large. Once, as the step comes in. */
.take__wipe,
.take__unwipe {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
  background: var(--blue-50);
}

.take__unwipe {
  background: none;
}

.take.has-motion .take__wipe {
  animation: take-wipe 1100ms var(--ease) backwards;
}

.take.has-motion .take__unwipe {
  animation: take-unwipe 1100ms var(--ease) backwards;
}

.take.has-motion .take__opt--photo + .take__opt--photo :is(.take__wipe, .take__unwipe) {
  animation-delay: 120ms;
}

.take.has-motion .take__img img {
  animation: take-settle 2600ms var(--ease) backwards;
}

@keyframes take-wipe {
  from {
    transform: translate3d(calc(-100% * var(--side, 1)), 0, 0);
  }
}

@keyframes take-unwipe {
  from {
    transform: translate3d(calc(100% * var(--side, 1)), 0, 0);
  }
}

@keyframes take-settle {
  from {
    scale: 1.08;
  }
}

.take__opt--photo[aria-checked="true"] .take__img {
  box-shadow: 0 0 0 2px var(--blue-700);
}

/* No "Save image" on a long press, no dragging a photograph off. */
.take__img img {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.take__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: scale 400ms var(--ease);
}

.take__opt--photo[aria-checked="true"] .take__img img {
  scale: 1.03;
}

.take__photofoot {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 24px 0 0;
}

.take__photofoot .take__body {
  flex: 1;
}

@media (hover: hover) {
  .take__opt:hover .take__label {
    color: var(--blue-700);
  }
}

.take__err {
  font-size: 14px;
  line-height: 1.4;
  color: var(--error);
}

.take__err {
  margin: 16px 0 0;
  font-size: 16px;
}

/* iPad portrait: the big screen's layout with the type a step down (the user, 2026-10-28: "the same
   look and feel for ipad devices as well"). */
@media (max-width: 1023px) {
  .take__head {
    font-size: 44px;
  }

  .take__module {
    margin-top: 64px;
  }

  .take__q {
    font-size: 36px;
  }

  .take__num {
    font-size: 72px;
  }
}

/* While asking, split as the user's reference (2026-10-29: a contact form, its line and a picture
   on the left, its questions on a white card on the right): the line, the paragraph and the
   product's photograph in the first five columns, the card from the seventh. The card is the
   page's frosted glass (as `.sheet`: its blur, the palest NOVUS blue through it, the light across
   its face), round-cornered, no shadow and no line round it (the user, 2026-10-29: "keep the panel
   frosted glass ... remove the drop shadow"); its answers are white rows with the design system's
   field edge, pale blue (the one place a line is wanted: round a control). The review and the
   thanks keep the full width. */
/* As the user's frame (2026-10-29, Figma, 1470 wide): the photograph the section's whole box at
   1422:795, 20 px corners; the line 83 px in and 105 down; the card 525 wide (37%), 82 px in from
   the top and foot and 91 from the right, white at half. */
.take--split .take__layout {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 32px;
  /* Out past the page's margins to 8 px from the screen's edges, as the lineup below it
     (.page__scroll is the container; the user, 2026-10-29: "match the lhs rhs padding"). */
  width: calc(100cqw - 16px);
  margin-left: calc(50% - 50cqw + 8px);
  /* The frame's 1422:795 as its least height, up to 880 px (a large monitor); taller when a step
     needs it. */
  min-height: min(calc((100cqw - 16px) * 795 / 1422), 880px);
  /* The line starts where the section's tag ({04} YOUR TAKE) does, the page's own margin (the user,
     2026-10-29: "align the help shape text to {04}"): the section starts 8 px from the screen. */
  padding: 82px 91px 82px max(24px, calc(50cqw - 50% - 8px));
  overflow: hidden;
  border-radius: 20px;
}

/* The product's studio shot behind it all, edge to edge, still (YourTake, `Backdrop`). Its own pale
   studio colour under it until it's drawn. */
.take__backdrop {
  position: absolute;
  inset: 0;
  z-index: -2;
  display: block;
  width: 100%;
  height: 100%;
  background: #e6edf3;
  pointer-events: none;
}

.take--split .take__intro {
  display: block;
  flex: 1;
  /* Its own height, not the section's: the photograph is placed under where it ends. */
  align-self: flex-start;
  min-width: 0;
  padding-top: 23px;
}

.take--split .take__head {
  font-size: 64px;
  line-height: 0.91;
  font-weight: 530;
  color: #000;
}

.take--split .take__head .take__blue {
  color: inherit;
}

/* The body copy under it (the user, 2026-10-29: "add the body copy under the help shape nex2"). */
.take--split .take__sub {
  max-width: 34ch;
  margin-top: 24px;
  color: var(--ink);
}

.take--split .take__sub {
  margin-top: 24px;
}

.take--split .take__module {
  position: relative;
  flex: none;
  /* 525 of the frame's 1422: a share of the whole box, its padding included. */
  width: calc((100% + 174px) * 0.369);
  min-width: 400px;
  /* On a large monitor it stops growing (at 2560 it ran 724 wide, its answers lost in it). */
  max-width: 600px;
  margin-top: 0;
  padding: 40px;
  /* The overview's glass exactly (.sheet; the user, 2026-10-29: "match the form to the sheet"):
     its fill, edge, corners and the light across it; and a soft shadow, so it sits on the
     photograph. (A clearer glass, even and saturated with a lit top edge, was tried and
     reverted the same day.) */
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 28px;
  background: linear-gradient(to bottom, rgba(247, 250, 253, 0.4), rgba(245, 249, 252, 0.56) 55%, rgba(251, 252, 253, 0.9));
  -webkit-backdrop-filter: blur(30px) saturate(1.15);
  backdrop-filter: blur(30px) saturate(1.15);
  box-shadow: 0 24px 48px -16px rgba(16, 42, 67, 0.22), 0 4px 12px rgba(16, 42, 67, 0.06);
  scroll-margin-top: 104px;
  /* Up into place with the scroll (YourTake, --rise). */
  translate: 0 var(--rise, 0px);
}

.take--split .take__module::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(112deg, rgba(255, 255, 255, 0) 24%, rgba(255, 255, 255, 0.14) 36%, rgba(255, 255, 255, 0) 48%, rgba(255, 255, 255, 0.07) 68%, rgba(255, 255, 255, 0) 80%);
  pointer-events: none;
}

.take--split .take__module > * {
  position: relative;
}

/* Every question laid out unseen in the card, to hold it at the tallest one's height (YourTake.tsx). */
.take__module > .take__ghosts,
.take--split .take__module > .take__ghosts {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: grid;
  align-items: start;
  padding: inherit;
  visibility: hidden;
  pointer-events: none;
}

.take__ghosts > * {
  grid-area: 1 / 1;
}

/* At the card's head: a bar filling as they answer. */
.take__progress {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 32px;
}

.take__bar {
  flex: 1;
  height: 4px;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.85);
}

.take__bar > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--blue-700);
  transition: width 400ms var(--ease);
}

/* In the card, one column: the question, the answers, Back. */
.take--split .take__stage {
  display: block;
}

.take--split .take__q {
  max-width: none;
  font-size: 32px;
  line-height: 1.15;
}

.take--split .take__answers {
  margin-top: 32px;
}

.take--split .take__foot {
  justify-content: space-between;
  min-height: 0;
  margin-top: 24px;
}

/* Under the last question once it's answered: the consent (the design system's checkbox), rising
   in; the button is in the foot, beside Back. */
.take__send {
  margin-top: 24px;
  animation: take-rise 400ms var(--ease) both;
}

.take__foot .btn {
  animation: take-rise 400ms 60ms var(--ease) both;
}

/* Sent: the thanks on the card, its words as a question's. */
.take__stage--thanks .take__foot {
  margin-top: 32px;
}

/* The answers as rows, each its radio and words in the field's pale blue edge; hovered, the edge
   deepens; chosen, it turns blue on the palest blue. */
.take--split .take__opts {
  gap: 12px;
}

.take--split .take__opt {
  align-items: center;
  min-height: 64px;
  padding: 16px 16px;
  /* Translucent on the glass, a soft white edge (the user, 2026-10-29: solid white was "too
     stark"). */
  border: 1px solid rgba(255, 255, 255, 0.38);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.42);
  transition: opacity 250ms var(--ease-standard), transform 150ms var(--ease-standard), border-color 150ms var(--ease-standard),
    background-color 150ms var(--ease-standard);
}

@media (hover: hover) {
  .take--split .take__opt[aria-checked="false"]:hover {
    border-color: var(--blue-200);
    background: rgba(255, 255, 255, 0.62);
  }
}

.take--split .take__opt[aria-checked="true"] {
  border-color: var(--blue-700);
  background: rgba(255, 255, 255, 0.78);
}

.take--split .take__opt:focus-visible {
  box-shadow: 0 0 0 3px rgba(6, 146, 229, 0.2);
  border-color: var(--focus);
}

.take--split .take__opt:focus-visible .choice__box {
  outline: none;
}

.take--split .take__radio {
  height: auto;
}

/* A row with specs under its line: the radio stays beside the name, at the top. */
.take--split .take__opt:has(.take__given--opt) {
  align-items: start;
}

.take--split .take__label {
  font-size: 18px;
}

/* The radio, unchosen, as quiet as its row: translucent, a soft ring (the user, 2026-10-29: "radio
   button standing out now"). Hovered, its ring deepens; chosen, the design system's blue. */
.take--split .take__opt[aria-checked="false"] .choice__box {
  background: rgba(255, 255, 255, 0.35);
  box-shadow: inset 0 0 0 1.5px rgba(16, 42, 67, 0.2);
}

@media (hover: hover) {
  .take--split .take__opt[aria-checked="false"]:hover .choice__box {
    box-shadow: inset 0 0 0 1.5px var(--primary-500);
  }
}

/* The name and its line close together. */
.take--split .take__body {
  gap: 2px;
}

.take--split .take__opthint {
  font-size: 14px;
  color: var(--ink-2);
}

/* Figures as rows, one under another like every answer (the user, 2026-10-29: "keep all options
   vertically in one column"): the radio, the figure, its unit after it. */
.take--split .take__opts--metric {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.take--split .take__opt--metric {
  display: grid;
  width: 100%;
  align-items: center;
}

.take--split .take__num {
  font-size: 32px;
  line-height: 1;
}

.take--split .take__unit {
  margin-left: 6px;
  font-size: 16px;
}

/* Photographs, two across, each in its own outlined frame. */
.take--split .take__opts--photo {
  gap: 12px;
}

.take--split .take__opt--photo {
  display: flex;
  align-items: stretch;
  padding: 12px;
}

.take--split .take__opt--photo .take__img {
  border-radius: 4px;
}

.take--split .take__opt--photo[aria-checked="true"] .take__img {
  box-shadow: none;
}

.take--split .take__photofoot {
  align-items: center;
  padding: 16px 8px 4px;
}

/* Narrower than the frame: the line a step down, the card its 400 px at least. */
@media (max-width: 1199px) {
  .take--split .take__head {
    font-size: 52px;
  }
}

/* Narrower (an iPad held upright): the card under the line, the photograph left out. */
@media (max-width: 899px) {
  /* Still 8 px from the screen's edges, the line on the tag's edge; the card under it. */
  .take--split .take__layout {
    display: block;
    min-height: 0;
    padding: 40px 24px 24px max(24px, calc(50cqw - 50% - 8px));
  }

  .take--split .take__head {
    font-size: 44px;
  }

  .take--split .take__module {
    width: auto;
    min-width: 0;
    margin-top: 48px;
  }
}

/* A small tablet (an iPad mini, 744 upright): the card no wider than it needs, on the right, over
   the open studio, not across the whole photograph (the user, 2026-10-29). */
@media (min-width: 600px) and (max-width: 899px) {
  .take--split .take__module {
    max-width: 520px;
    margin-left: auto;
  }

  /* Room round it, over the phone's tighter padding (an iPad mini is under 768). */
  .take.take--split .take__layout {
    padding-right: 24px;
    padding-bottom: 24px;
  }
}

/* A phone, as a fallback: one column, as the page goes. */
@media (max-width: 767px) {
  .take__head {
    font-size: 34px;
  }

  /* The line over the paragraph, and one version under the other, each with its specs in a row. */
  .take__head,
  .take__sub {
    grid-column: 1 / -1;
  }

  .take__opts--photo {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
  }

  /* 8 px from the screen's edges, as on a wide screen, and the line on the tag's edge. */
  /* The card's foot as far from the photograph's edge as its sides are (the user, 2026-11-02: "let
     it match the side spacing"). */
  .take--split .take__layout {
    width: calc(100cqw - 16px);
    margin-left: calc(50% - 50cqw + 8px);
    padding: 24px 8px 8px max(8px, calc(50cqw - 50% - 8px));
  }

  .take--split .take__head {
    font-size: 34px;
  }

  /* Its corners nested in the photograph's: 20 less the 8 px between them (the user, 2026-11-02:
     "let it nest properly"). */
  .take--split .take__module {
    margin-top: 24px;
    padding: 24px;
    border-radius: 12px;
  }

  .take--split .take__q {
    font-size: 26px;
  }

  .take--split .take__num {
    font-size: 28px;
  }


  .take__q {
    font-size: 28px;
  }

  .take__dd {
    font-size: 22px;
  }

  .take__stage {
    grid-template-rows: none;
  }

  .take__words {
    grid-row: 1;
  }

  .take__answers {
    grid-row: 2;
  }

  .take__foot {
    grid-row: 3;
  }

  .take__words,
  .take__answers,
  .take__foot {
    grid-column: 1 / -1;
  }

  .take__opts--photo {
    grid-column: 1 / -1;
  }

  .take__num {
    font-size: 56px;
  }
}

/* A phone: the card under the product's own band (Backdrop in YourTake.tsx sets its height), over
   its foot a little (the user, 2026-11-02: "the form can overlap with the image a little more"). */
@media (max-width: 599px) {
  .take--split .take__module {
    margin-top: max(24px, calc(var(--take-photo, 0px) - 56px));
  }

  /* A version's three specs one under another, name then figure, in two columns that line up: side
     by side they don't fit a phone's row (the third fell under the first two, its rule hanging; the
     Italian names are longer still). */
  /* The names in a column of one width, so the figures line up in both rows, a long name (the
     Italian) on two lines; the figures never wrap (at 340 px "90–110 km/h" ran out of the row). */
  .take__given--opt {
    display: grid;
    grid-template-columns: minmax(0, 68px) max-content;
    justify-content: start;
    align-items: baseline;
    gap: 6px 16px;
  }

  .take__given--opt .take__dt {
    line-height: 1.25;
  }

  .take__given--opt > span {
    display: contents;
  }

  .take__given--opt .take__dd {
    font-size: 15px;
  }

  /* The specs over the price question, the three in one row (the third fell under the first two):
     each column as wide as what's in it and the same gap between them (even columns left the gaps
     uneven: "spacing is off"), the names on one line across and the figures on the next, a long
     name (the Italian) wrapping in its own column, the names' tops level. */
  .take__given:not(.take__given--opt) {
    display: grid;
    grid-template-columns: repeat(3, auto);
    grid-template-rows: auto auto;
    grid-auto-flow: column;
    justify-content: start;
    align-items: start;
    gap: 8px 24px;
  }

  .take__given:not(.take__given--opt) > div {
    display: contents;
  }

  .take__given:not(.take__given--opt) .take__dt {
    line-height: 1.25;
  }

  .take__given:not(.take__given--opt) .take__dd {
    align-self: start;
    font-size: 22px;
  }

  .take__given:not(.take__given--opt) small {
    font-size: 13px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .take *,
  .take *::before,
  .take *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ---- Draw's first-time tour (the user, 2026-11-02: "a 3–4 step walkthrough..."; then "the tour ui is
   not good", their pick: light glass hints). No dimming: the board stays bright and usable. A blue
   beacon pulses on the tool a step is about; beside it a small frosted card, the board's own hint
   glass, with the step as the wall's tags have it ({01/04}), dots, Skip and Next. */
.board__tour {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
}

.board__tour-beacon {
  position: fixed;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border: 2px solid #fff;
  border-radius: 50%;
  background: var(--blue);
  box-shadow: 0 1px 4px rgba(9, 38, 64, 0.25);
  transition: left 360ms var(--ease), top 360ms var(--ease);
}

.board__tour-beacon::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  background: var(--blue);
  animation: board-tour-pulse 1.6s var(--ease) infinite;
}

.board__tour-card {
  position: fixed;
  width: min(280px, calc(100vw - 32px));
  padding: 14px 16px 12px;
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: 0 10px 30px rgba(9, 38, 64, 0.12), 0 1px 3px rgba(9, 38, 64, 0.08);
  color: var(--ink);
  pointer-events: auto;
  opacity: 0;
}

.board__tour-card.is-placed {
  animation: board-tour-card 320ms var(--ease) both;
}


/* The step count in the brand's light grey, not NOVUS blue (the user, 2026-11-02: "lighter grey", then
   "even more lighter"): grey 200. It is under WCAG AA at 12 px (2.7:1), the user's look; the step is
   also told by the dots and the title. */
.board__tour-count {
  margin: 0 0 6px;
  color: var(--grey-200);
}

.board__tour-title {
  margin: 0 0 4px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
}

.board__tour-text {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-2);
}

.board__tour-foot {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: 12px;
}

/* Back, at the foot's left, quiet as Skip with its arrow; Skip and Next stay at the right. */
.board__tour-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-right: auto;
  padding: 6px 4px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  color: var(--ink-3);
  cursor: pointer;
}

.board__tour-back .icon {
  width: 14px;
  height: 14px;
}

.board__tour-back:hover {
  color: var(--ink-2);
}

/* With no Back (the first step), Skip and Next keep to the right. */
.board__tour-foot {
  justify-content: flex-end;
}

.board__tour-skip {
  padding: 6px 4px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  color: var(--ink-3);
  cursor: pointer;
}

.board__tour-skip:hover {
  color: var(--ink-2);
}

@keyframes board-tour-pulse {
  from {
    opacity: 0.55;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(3.2);
  }
}

@keyframes board-tour-in {
  from {
    opacity: 0;
  }
}

@keyframes board-tour-card {
  from {
    opacity: 0;
    translate: 0 6px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .board__tour-card.is-placed {
    animation-duration: 1ms;
  }
  .board__tour-beacon::after {
    animation: none;
  }
}


/* Draw's demo (ui/board/DrawDemo.tsx): the parts in the board's blue, each sliding in from the parts
   panel's side and settling, a ring where it snaps on; the whole holds, then fades before it plays again. */
.board__demo {
  display: block;
  overflow: visible;
  color: #0774b8;
  pointer-events: none;
  animation: board-demo-life var(--all) linear both;
}

.board__demo-part {
  animation: board-demo-in 560ms var(--ease) var(--d) both;
}

.board__demo-snap {
  fill: none;
  stroke: var(--blue);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
  transform-origin: center;
  animation: board-demo-snap 600ms var(--ease) calc(var(--d) + 420ms) both;
}

@keyframes board-demo-in {
  from {
    opacity: 0;
    transform: translate(var(--from), var(--rise));
  }
  60% {
    opacity: 1;
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes board-demo-snap {
  from {
    opacity: 0;
    transform: scale(0.4);
  }
  30% {
    opacity: 1;
  }
  to {
    opacity: 0;
    transform: scale(2.4);
  }
}

@keyframes board-demo-life {
  0%,
  92% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .board__demo,
  .board__demo-part {
    animation: none;
  }
  .board__demo-snap {
    display: none;
  }
}


/* Draw's ? beside Back, for the tour again. */
.board__bar {
  display: flex;
  gap: var(--space-1);
}



/* ---- The save screen's questions (ui/board/AboutForm.tsx), step 2 of the sheet, on design.md (the user,
   2026-11-02: "very unprofessional, so uneven... doesn't follow the design system or any brand guidelines"):
   one control height, 48 px, for the chips, the fields and the buttons; field labels in Body Small, 14/500,
   sentence case (capitals are for tags); a card title in H3, Medium; gaps on the 8 · 16 · 24 · 32 scale;
   age and country as two equal columns. It comes in softly where the thanks was. */
.sim__about {
  display: grid;
  gap: var(--space-4);
  width: 100%;
  margin-top: var(--space-2);
}

/* Its questions in Body, Medium, ink: the voice of the sheet, a step under the headline. */
.sim__about .field__label {
  font-size: var(--fs-body);
  line-height: 1.4;
  color: var(--ink);
}

/* The thanks comes in where the questions were. */
.sim__step-in {
  animation: take-rise 480ms var(--ease) both;
}

.sim__step-in + .sim__step-in {
  animation-delay: 80ms;
}

.sim__about-q {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.sim__about-q > legend {
  margin-bottom: var(--space-2);
  padding: 0;
}

.sim__about-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.sim__about .chip {
  min-height: 48px;
  padding: 0 var(--space-3);
  font-size: var(--fs-body-sm);
}

.sim__about-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.sim__about .control {
  min-height: 48px;
  height: 48px;
}



.sim__about-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}

/* The sheet as tall as what it holds, up to just under the nav; past that it scrolls. */
.sim__sheet.sheet {
  max-height: calc(100dvh - 88px);
}

/* The questions step: room under its last field (the user, 2026-11-02: "increase the bottom ... for
   screen 1 of save"), so the country's list can drop down below it, the sheet scrolling up to make way. */
.sim__sheet.sheet:has(.sim__about) {
  padding-bottom: calc(var(--space-8) + 28px);
}

/* Submit and Submit without answering held at the sheet's foot while the questions scroll under them on a
   short screen, so the way on is never out of reach; a soft wash of the sheet behind them. Only when the
   sheet scrolls (AboutForm sets is-held): otherwise the wash was a pale box round them on the frosted
   sheet (the user, 2026-11-02: "theres a fill behind this"). (The sheet's own foot runs 28 px off the
   screen, hence the offset.) */
.sim__about-actions.is-held {
  position: sticky;
  z-index: 1;
  /* From the inside of the sheet's foot padding (space-8, plus 28 px off the screen): back down to the screen's own foot. */
  bottom: calc(-1 * var(--space-8));
  padding: var(--space-5) 0 var(--space-3);
  background: linear-gradient(to bottom, rgba(250, 252, 254, 0), rgba(250, 252, 254, 0.97) 45%);
}

@media (max-width: 699px) {
  .sim__about-row {
    grid-template-columns: 1fr;
  }

  .sim__sheet.sheet {
    max-height: calc(100dvh - 72px);
    overflow-y: auto;
  }

  /* Less room under the buttons on a phone, so the questions fit a phone's sheet without a scroll
     and the buttons aren't held over a wash (the user, 2026-11-03: unusual fills; at 375 x 812 the
     sheet scrolled by its foot padding alone, leaving a gap under Country and a pale band behind Submit). */
  .sim__sheet.sheet:has(.sim__about) {
    padding-bottom: calc(var(--space-5) + 28px);
  }

  .sim__about-actions .btn {
    flex: 1;
  }
}

/* The demo inside the tour's card, on a pale blue panel above the step's words. */
.board__tour-demo {
  display: grid;
  place-items: center;
  margin: 0 0 12px;
  padding: 12px 8px;
  border-radius: 12px;
  background: var(--blue-50);
}

/* ---- The tour's marks (the user, 2026-11-02: "the visibility of the dot is not great"): the tool a
   step is about outlined in NOVUS blue, a soft glow breathing out from it; a larger beacon on its
   corner. The card beside it points at it with a caret; the demo's card, in the middle, has none. */
/* Soft and translucent (the user, 2026-11-02: "soft translucent highlight"): a light NOVUS blue wash
   over the tool, a faint edge, and a glow that breathes out from it. */
.board__tour-ring {
  position: fixed;
  border: 1px solid rgba(43, 167, 255, 0.45);
  background: rgba(43, 167, 255, 0.12);
  -webkit-backdrop-filter: saturate(1.2);
  backdrop-filter: saturate(1.2);
  pointer-events: none;
  animation: board-tour-glow 2.4s var(--ease-standard) infinite;
  transition: left 360ms var(--ease), top 360ms var(--ease), width 360ms var(--ease), height 360ms var(--ease);
}

@keyframes board-tour-glow {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(43, 167, 255, 0.22);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(43, 167, 255, 0);
  }
}

.board__tour-beacon {
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border: 3px solid #fff;
  background: var(--blue-700);
  box-shadow: 0 2px 6px rgba(9, 38, 64, 0.3);
}

.board__tour-beacon::after {
  inset: -3px;
  background: var(--blue);
}

.board__tour-card::after {
  content: "";
  position: absolute;
  width: 12px;
  height: 12px;
  background: inherit;
  border-radius: 2px;
  transform: rotate(45deg);
}

.board__tour-card.is-centre::after {
  display: none;
}

.board__tour-card.is-top::after {
  left: calc(var(--caret) - 6px);
  bottom: -5px;
}

.board__tour-card.is-bottom::after {
  left: calc(var(--caret) - 6px);
  top: -5px;
}

.board__tour-card.is-left::after {
  right: -5px;
  top: calc(var(--caret) - 6px);
}

@media (prefers-reduced-motion: reduce) {
  .board__tour-ring {
    animation: none;
  }
}


/* The tour's pinch: a wheel growing and shrinking, two fingertips spreading and closing over it. */
.board__pinch {
  display: block;
  overflow: visible;
  color: #0774b8;
}

.board__pinch-part {
  transform-box: view-box;
  transform-origin: 0 0;
  animation: board-pinch-part 2.4s var(--ease-standard) infinite;
}

.board__pinch-finger {
  fill: rgba(43, 167, 255, 0.28);
  stroke: var(--blue);
  stroke-width: 2;
  animation: board-pinch-a 2.4s var(--ease-standard) infinite;
}

.board__pinch-finger.is-b {
  animation-name: board-pinch-b;
}

@keyframes board-pinch-part {
  0%, 100% { transform: scale(0.75); }
  45%, 55% { transform: scale(1.15); }
}

@keyframes board-pinch-a {
  0%, 100% { transform: translate(-40px, 30px); }
  45%, 55% { transform: translate(-110px, 70px); }
}

@keyframes board-pinch-b {
  0%, 100% { transform: translate(40px, -30px); }
  45%, 55% { transform: translate(110px, -70px); }
}

@media (prefers-reduced-motion: reduce) {
  .board__pinch-part,
  .board__pinch-finger {
    animation: none;
  }
}

/* ---- How it works, a ghost at the toolbar's end: the icon tools' own chip, its icon a little quieter
   than the tools', a hairline of space after Save. */
.board__tool--help {
  margin-left: 4px;
  color: var(--ink-2);
}

@media (hover: hover) {
  .board__tool--help:hover {
    color: var(--blue-700);
  }
}

/* ---- The parts panel (the user, 2026-11-02: "improve the user interaction for this whole build it
   from parts... typography, visual hierarchy, IA"; its title and hint taken out after). Read top to
   bottom: the filters, then the parts by kind. On design.md: kinds as tags (12 px capitals), names Body Small; 8 px steps; the parts two across, large enough to
   tap with confidence, their names on two lines at most. */
/* The filters: All, then Air, Land and Water with their icons; the one on raised white. */
/* Each segment its words' width plus an equal share of what's left, so "All" isn't squeezed against the
   edge on a wide panel nor the others clipped on a narrow one. */
.board__jump {
  display: flex;
  gap: 2px;
  margin: 0 16px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--blue-50);
}

.board__jump-to {
  flex: 1 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  min-height: 36px;
  padding: 0 6px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  font: inherit;
  font-size: var(--fs-body-sm);
  font-weight: 500;
  white-space: nowrap;
  color: var(--ink-2);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}

.board__jump-to .icon {
  flex: none;
  width: 16px;
  height: 16px;
}

@media (hover: hover) {
  .board__jump-to:hover {
    color: var(--blue-700);
  }
}

.board__jump-to[aria-checked="true"] {
  background: #fff;
  color: var(--blue-700);
  box-shadow: 0 1px 3px rgba(16, 42, 67, 0.12);
}

.board__jump-to:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* The kinds: a tag over each, 24 px between them. */
.board__library .board__kind + .board__kind {
  margin-top: var(--space-4);
}

.board__library .board__kind-name {
  margin: 0 0 var(--space-2);
  padding: 0;
  border: 0;
  color: var(--ink-2);
}

/* The parts, two across: a 64 px drawing over its name. */
.board__library .board__kind-parts {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}

.board__library .board__part {
  gap: var(--space-1);
  padding: 12px 10px 10px;
  border-radius: 12px;
}

.board__library .board__part-art,
.board__library .board__part-art svg {
  height: 64px;
}

.board__library .board__part-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: var(--fs-body-sm);
  font-weight: 500;
  line-height: 1.3;
  text-align: center;
}

/* A phone's panel is low and wide: three across there. */
@media (max-width: 699px) {
  .board__library .board__kind-parts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .board__library .board__part-art,
  .board__library .board__part-art svg {
    height: 48px;
  }
}

/* An iPad held upright: one part to a row, as the user asked (2026-10-30: "revert to one"). */
@media (min-width: 700px) and (orientation: portrait) {
  .board__library .board__kind-parts {
    grid-template-columns: 1fr;
  }
}

/* The tour's Next (and Start): a step smaller than the system's small button, in scale with the card's
   14 px words and its Skip. */
.board__tour-foot .btn {
  --h: 32px;
  gap: 6px;
  padding: 0 14px;
  font-size: var(--fs-body-sm);
}

.board__tour-foot .btn .icon {
  width: 16px;
  height: 16px;
}

/* ---- A phone on its side (short and wide): the parts panel at the right, between the nav and the
   toolbar, as on an iPad, not docked across the foot, where it covered most of the sheet and the parts
   tapped in landed under it. Two parts across; the filters' padding a step tighter to fit. */
@media (max-width: 999px) and (max-height: 500px) and (orientation: landscape) {
  .board--draw .board__library {
    top: 60px;
    bottom: 68px;
    left: auto;
    right: 12px;
    width: 300px;
    height: auto;
    max-height: none;
  }

  .board__library .board__kind-parts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .board__library .board__part-art,
  .board__library .board__part-art svg {
    height: 44px;
  }

}

/* Every filter at least a fingertip wide (44 px, design.md's touch target: "All" was 35). */
.board__jump-to {
  min-width: 44px;
}

/* An iPad held upright: the panel 288 px, as on its side (at 240 the four filters ran past its edge),
   the filters' padding a step tighter so all four fit. */
@media (min-width: 700px) and (orientation: portrait) {
  .board--draw .board__library {
    width: 288px;
  }

}

/* ---- An iPad mini held upright (744 to 799 px wide): the parts panel docked along the foot above the
   toolbar, as on a phone (the user, 2026-11-02: "for mini we can have it in the bottom, like the phone,
   so it never overlaps"), not down the right side, where its column met the hint and the sheet's middle.
   Four parts across in its width; the hint is the panel's place while it is open. Other iPads keep the
   side panel. */
@media (min-width: 700px) and (max-width: 799px) and (orientation: portrait) {
  .board--draw .board__library {
    inset: auto 16px 80px;
    width: auto;
    height: 34dvh;
    max-height: none;
  }

  .board__library .board__kind-parts {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .board__library .board__part-art,
  .board__library .board__part-art svg {
    height: 52px;
  }

  .has-library .board__tip {
    display: none;
  }
}

/* No tool in hand (the pen or eraser tapped off): the sheet is for picking and moving parts, so the
   ordinary pointer over it, and a hand over a part. */
.board--draw.is-pointing .board__surface {
  cursor: default;
}

.board--draw.is-pointing .board__piece {
  cursor: grab;
}
