/* =========================================================
   Components and sections. Mobile first; a component's own
   wider-screen rules sit directly underneath it, so it is
   read in one place. What is left in responsive.css is the
   page frame rather than any single component.

   Breakpoints: 40em (large phone), 48em (tablet),
   52em (header unfolds), 64em (laptop), 80em (desktop).
   ========================================================= */

/* ═══════════════════════════ PRIMITIVES ═══════════════════════════ */

/* The gutter is a floor, not a fixed value: with viewport-fit=cover the page
   runs under the notch in landscape, and the safe-area insets take over
   whenever they are the larger of the two. They are 0 everywhere else, so this
   reads as plain --gutter on every other screen. */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}

.container--narrow {
  max-width: var(--container-narrow);
}

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

/* Clipped away rather than parked off-screen. Hiding it by position leaves a
   real box somewhere that elastic overscroll can drag into view, which is what
   made it flash in when the page was pulled down past the top. Collapsed to a
   clipped 1px it has nowhere to be revealed from, in any browser. */
.skip-link {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  background: var(--ink);
  color: var(--porcelain);
  font-weight: 700;
  text-decoration: none;
}

.skip-link:focus-visible {
  width: auto;
  height: auto;
  padding: 0.75rem 1.25rem;
  clip-path: none;
  outline-color: var(--accent);
  outline-offset: -4px;
}

/* ---------- The mark ---------- */

.mark {
  flex: none;
  overflow: visible;
}

.mark__face {
  fill: var(--mark-face, var(--porcelain));
  stroke: var(--mark-ink, var(--ink));
}

.mark__eye {
  fill: var(--mark-ink, var(--ink));
}

/* ---------- Icons ---------- */

.icon,
.arrow {
  flex: none;
  width: 1em;
  height: 1em;
  transition: transform 0.3s var(--ease);
}

/* ---------- Label ----------
   The technical label above a heading: index box, mono name, trailing rule. */

.label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.label::after {
  content: "";
  flex: 1 1 auto;
  max-width: 4rem;
  height: 1px;
  background: currentColor;
  opacity: 0.4;
}

.label__index {
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--rule-mid);
  color: var(--accent-ink);
  letter-spacing: 0.06em;
}

/* ---------- Buttons ----------
   A printed offset rather than a blur: the button sits on the page like a
   stamped label and presses into it on click. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 3rem;
  padding: 0.75rem 1.25rem;
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 700;
  line-height: 1.1;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform 0.2s var(--ease),
    box-shadow 0.2s var(--ease),
    background-color 0.2s var(--ease),
    color 0.2s var(--ease);
}

.btn:hover .icon--arrow,
.btn:hover .arrow {
  transform: translateX(3px);
}

.btn--primary {
  background: var(--ink);
  color: var(--porcelain);
  box-shadow: 3px 3px 0 var(--accent);
}

.btn--primary:hover {
  transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 var(--accent);
}

.btn--secondary {
  background: var(--porcelain);
  color: var(--ink);
  box-shadow: var(--offset);
}

.btn--secondary:hover {
  transform: translate(-1px, -1px);
  box-shadow: var(--offset-hover);
}

/* On a night surface the ink offset disappears into the ground, so the accent
   becomes the button and the light tone becomes its shadow. */
.btn--night {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--night-deep);
  box-shadow: 3px 3px 0 var(--on-night);
}

.btn--night:hover {
  transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 var(--on-night);
}

.btn:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 transparent;
}

.btn--small {
  min-height: 2.5rem;
  padding: 0.5rem 0.9rem;
  font-size: var(--step--1);
}

/* ---------- Links ---------- */

.more {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.75rem;
  color: var(--accent-ink);
  font-weight: 700;
  text-decoration: none;
}

.more:hover {
  text-decoration: underline;
}

.more:hover .icon,
.more:hover .arrow {
  transform: translateX(3px);
}

.body-link,
.prose a,
.contact-address__link {
  color: var(--accent-ink);
  text-decoration-color: var(--accent);
  text-decoration-thickness: 1.5px;
}

/* Marker pass. The one italic display face on a page that is otherwise body and
   mono, over a wash a single step off the surface. Named .marker, not .mark —
   .mark is already the skull glyph. */
.marker {
  padding: 0.06em 0.3em;
  margin: 0 -0.06em;
  background-color: var(--accent-tint-soft);
  box-shadow: 0 1px 0 var(--accent);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.12em;
  font-style: italic;
  font-weight: 500;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* ---------- Tags ---------- */

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.tag {
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--rule-mid);
  border-radius: var(--radius);
  background: var(--porcelain);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.5;
}

.tag--future {
  border-style: dashed;
  background: transparent;
}

.tag--accent {
  border-color: var(--accent);
  color: var(--accent-ink);
}

.tags--large .tag {
  padding: 0.4rem 0.75rem;
  font-size: var(--step--1);
}

/* ---------- Check list ---------- */

.checks {
  display: grid;
  gap: 0.55rem;
}

.checks li {
  position: relative;
  padding-left: 1.75rem;
  color: var(--text-2);
}

.checks li::before {
  content: "";
  position: absolute;
  top: 0.42em;
  left: 0.2rem;
  width: 0.8rem;
  height: 0.45rem;
  border-bottom: 2px solid var(--accent-ink);
  border-left: 2px solid var(--accent-ink);
  transform: rotate(-45deg);
}

.checks--compact {
  gap: 0.3rem;
  margin-block: 0.75rem;
  font-size: var(--step--1);
}

/* ---------- Status ----------
   A dot and a word. The word is what carries it: on a site whose figures are
   mostly "this was reachable and should not have been", colour alone would be
   the one place the page lets a reader down. */

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.status__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px rgb(63 122 90 / 0.15);
}

.status--warn .status__dot {
  background: var(--warn);
  box-shadow: 0 0 0 3px rgb(168 112 29 / 0.18);
}

.status--bad .status__dot {
  background: var(--bad);
  box-shadow: 0 0 0 3px rgb(181 72 61 / 0.18);
}

.status--info .status__dot {
  background: var(--accent);
  box-shadow: 0 0 0 3px rgb(189 148 195 / 0.24);
}

/* ---------- Pull-quote ---------- */

.pullquote {
  max-width: 44rem;
  margin-block: clamp(2.5rem, 6vw, 4rem);
  text-align: center;
}

.pullquote::before {
  content: "\201C";
  display: block;
  margin-bottom: 0.4rem;
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 5rem;
  line-height: 0.6;
}

.pullquote--soft::before {
  content: "";
  width: 32px;
  height: 2px;
  margin: 0 auto 1.6rem;
  background: var(--accent);
}

.pullquote p {
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-style: italic;
  font-weight: 500;
  line-height: 1.2;
  text-wrap: balance;
}

/* ---------- Divider ---------- */

.divider {
  --mark-face: var(--on-night);
  --mark-ink: var(--night-deep);
  display: flex;
  align-items: center;
  gap: 1.25rem;
}

.divider__rule {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    var(--rule-night) 22%,
    var(--rule-night) 78%,
    transparent
  );
}

/* ---------- Disclosure ---------- */

.disclosure {
  margin-top: 0.75rem;
}

.disclosure__summary {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.25rem;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  list-style: none;
}

.disclosure__summary::-webkit-details-marker {
  display: none;
}

.disclosure__summary:hover {
  color: var(--accent-ink);
}

.disclosure__icon {
  position: relative;
  width: 0.9rem;
  height: 0.9rem;
  border: 1px solid currentColor;
}

.disclosure__icon::before,
.disclosure__icon::after {
  content: "";
  position: absolute;
  inset: 50% 20% auto;
  height: 1px;
  background: currentColor;
  transition: transform 0.25s var(--ease);
}

.disclosure__icon::after {
  transform: rotate(90deg);
}

.disclosure[open] .disclosure__icon::after {
  transform: rotate(0deg);
}

.disclosure__body {
  padding: 0.75rem 0 0.25rem;
}

.disclosure__body > :first-child {
  border-top: 0;
}

/* ---------- The assistant hand-off line ---------- */

.ask {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-top: 2rem;
  color: var(--text-2);
}

.ask[hidden] {
  display: none;
}

.ask__button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.5rem;
  padding: 0.4rem 0.9rem;
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: var(--porcelain);
  color: var(--ink);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.ask__button:hover {
  box-shadow: 3px 3px 0 var(--ink);
}

.ask__button:hover .arrow {
  transform: translateX(3px);
}

/* ---------- Skull illustrations ---------- */

.skull {
  margin: 0;
}

.skull__img,
.skull__svg {
  width: 100%;
  max-width: 100%;
  height: auto;
}

.skull__caption {
  margin-top: 0.4rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  text-align: center;
}

@keyframes skull-wiggle {
  0%,
  100% {
    transform: rotate(0);
  }
  30% {
    transform: rotate(-5deg);
  }
  65% {
    transform: rotate(4deg);
  }
}

@keyframes skull-drift {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-7px);
  }
}

/* Two frames of the eye closing. The mascot's eyes are pitch black on this
   brand, so a blink is the only movement it has — the parent's glint does half
   this work over there and there is nothing to catch the light here. */
@keyframes skull-blink {
  0%,
  93%,
  100% {
    transform: scaleY(1);
  }
  95% {
    transform: scaleY(0.08);
  }
}

@keyframes skull-rise {
  from {
    opacity: 0;
    transform: translateY(18px) rotate(-3deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .skull__img {
    transform-origin: 50% 85%;
  }

  .card:hover .skull__img,
  .stage:hover .skull__img,
  .tier:hover .skull__img,
  .split__skull:hover .skull__img,
  .family-strip__item:hover .skull__img {
    animation: skull-wiggle 0.6s var(--ease);
  }

  .system__skull .sk-eye {
    transform-box: fill-box;
    transform-origin: center;
    animation: skull-blink 6.5s infinite;
  }

  .system__skull .sk-eye:nth-of-type(2) {
    animation-delay: 0.04s;
  }

  .system__hub .skull {
    animation: skull-drift 5s ease-in-out infinite;
  }

  /* Illustrations arrive as they scroll in, where the browser supports tying an
     animation to scroll position. Everywhere else they are simply there. */
  @supports (animation-timeline: view()) {
    .split__skull,
    .card__art .skull,
    .stage__art .skull,
    .tier__art .skull {
      animation: skull-rise linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 55%;
    }
  }
}

/* ═══════════════════════════ HEADER ═══════════════════════════ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  padding-top: env(safe-area-inset-top);
  background: rgb(242 239 235 / 0.94);
  border-bottom: 1px solid var(--rule);
  backdrop-filter: saturate(1.2) blur(10px);
  -webkit-backdrop-filter: saturate(1.2) blur(10px);
}

/* iOS Safari in portrait is the case the inset above does not cover: the
   viewport already begins below the status bar, so the inset reports 0, and the
   page is drawn behind the translucent status strip regardless. This extends
   the bar's own surface past its top edge to fill that band. */
.site-header::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 100%;
  left: 0;
  height: 6rem;
  background: var(--paper);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 4rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--ink);
  text-decoration: none;
}

/* One word set as two: the weight change separates them, so there is no space
   to close up. Cormorant rather than the tracked-out sans it used to be — the
   wordmark is the one place the house display face has to be doing the talking,
   because it is the only thing on the page a visitor arriving from the parent
   site will compare directly. */
.brand__word {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.005em;
  white-space: nowrap;
}

.brand__word b {
  font-weight: 700;
}

a.brand:hover .mark {
  animation: skull-wiggle 0.6s var(--ease);
}

/* ---------- Menu (below 52em) ---------- */

.menu {
  flex: none;
}

.menu__button {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.75rem;
  padding-inline: 0.9rem;
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: var(--porcelain);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  list-style: none;
}

.menu__button::-webkit-details-marker {
  display: none;
}

.menu__bars {
  position: relative;
  width: 1rem;
  height: 0.625rem;
}

.menu__bars::before,
.menu__bars::after {
  content: "";
  position: absolute;
  right: 0;
  left: 0;
  /* A whole pixel, not a hairline: on Android the device pixel ratios are often
     fractional, and a 1.5px box landing on a fractional offset can snap away to
     nothing when it is painted. */
  height: 2px;
  background: currentColor;
  transition: transform 0.3s var(--ease);
}

.menu__bars::before {
  top: 0;
}

.menu__bars::after {
  bottom: 0;
}

.menu[open] .menu__bars::before {
  transform: translateY(0.25rem) rotate(45deg);
}

.menu[open] .menu__bars::after {
  transform: translateY(-0.25rem) rotate(-45deg);
}

/* Dropped over the page rather than pushed into it, so opening the menu never
   moves what is being read underneath. */
.menu__panel {
  position: absolute;
  top: 100%;
  right: 0;
  left: 0;
  max-height: calc(100dvh - 100%);
  overflow-y: auto;
  padding: 0.5rem max(var(--gutter), env(safe-area-inset-right))
    calc(1.5rem + env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
  background: var(--paper);
  border-bottom: 1.5px solid var(--ink);
  box-shadow: 0 24px 40px -30px rgb(23 20 28 / 0.5);
  animation: menu-drop 0.24s var(--ease) both;
}

@keyframes menu-drop {
  from {
    opacity: 0;
    transform: translateY(-0.5rem);
  }
}

.nav__list {
  display: flex;
  flex-direction: column;
}

.nav__list > li + li {
  border-top: 1px solid var(--rule);
}

.nav__link {
  display: block;
  padding-block: 0.9rem;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.625rem;
  font-weight: 600;
  text-decoration: none;
}

.nav__link.is-current {
  color: var(--accent-ink);
}

.nav__link.is-current::after {
  content: " ·";
}

@media (max-width: 22em) {
  .menu__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .brand__word {
    font-size: 1.3rem;
  }
}

/* ═══════════════════════════ SECTIONS ═══════════════════════════ */

.section {
  position: relative;
  padding-block: var(--section-space);
}

/* For a run of sections whose whole content is a heading, a line and a folded
   list. At the full section height five of them in sequence are mostly empty
   band, and the page scrolls like a long one while saying very little. */
.section--compact {
  padding-block: clamp(2.5rem, 5.5vw, 3.75rem);
}

.section--paper {
  background: var(--paper);
}

.section--porcelain {
  background: var(--porcelain);
  border-block: 1px solid var(--rule);
}

.section--grid {
  background-color: var(--paper);
  background-image: var(--grid-dot);
  background-size: var(--grid-size);
  border-block: 1px solid var(--rule);
}

.section--plum {
  background:
    radial-gradient(120% 90% at 100% 0%, rgb(251 249 247 / 0.9) 0%, transparent 55%),
    var(--accent-wash);
}

/* The one band where this brand is the one speaking rather than describing
   itself, so it takes the mascot's own ground. */
.section--night {
  --mark-face: var(--on-night);
  --mark-ink: var(--night-deep);
  background:
    radial-gradient(60% 70% at 85% 30%, rgb(189 148 195 / 0.14) 0%, transparent 70%),
    var(--night);
  color: var(--on-night);
}

.section--night h2,
.section--night h3 {
  color: var(--on-night);
}

.section--night .label {
  color: var(--on-night-2);
}

.section--night .label__index {
  border-color: var(--rule-night);
  color: var(--accent-on-night);
}

.section--night .section__lead,
.section--night .section__note {
  color: var(--on-night-2);
}

.section--night a:not(.btn) {
  color: var(--accent-on-night);
}

.section--night .skull__caption {
  color: var(--on-night-2);
}

/* The mascot's teeth, rising from a dark band into whatever sits above it.
   Drawn in the band's own colour, so it never needs to know its neighbour. */
.teeth {
  position: absolute;
  right: 0;
  bottom: 100%;
  left: 0;
  height: 30px;
  background-color: var(--night);
  -webkit-mask: var(--teeth) repeat-x center bottom / 98px 30px;
  mask: var(--teeth) repeat-x center bottom / 98px 30px;
  transform: scaleY(-1);
  pointer-events: none;
}

.section__head {
  margin-bottom: clamp(2rem, 5vw, 3.25rem);
}

/* The head is full width so that content passing under it while pinned is
   covered edge to edge; the heading text keeps the measure instead. */
.section__head h2 {
  max-width: 44rem;
  font-size: var(--step-4);
}

.section__head h3 {
  font-size: var(--step-3);
}

/* When a lead follows, the head hands the section's bottom spacing over to it
   rather than both of them contributing a gap. */
.section__head:has(+ .section__lead) {
  margin-bottom: 1.25rem;
}

.section__lead {
  margin-block: 0 clamp(2rem, 5vw, 3.25rem);
  max-width: 42rem;
  color: var(--text-2);
  font-size: var(--step-1);
  line-height: 1.55;
}

.section--compact .section__lead {
  margin-bottom: 0;
}

/* An illustration set beside the section's heading. It is a sibling of the head
   rather than a child, because the head pins on a wide screen and a drawing
   pinned along with it would travel down the page. */
.section__intro {
  display: grid;
  gap: 1.5rem;
}

.section__art .skull {
  width: min(100%, 13rem);
  margin-inline: auto;
}

.section__action {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: clamp(2rem, 4vw, 2.75rem);
}

/* A second heading inside one band, where a section carries two related blocks. */
.section__subhead {
  margin-top: clamp(2.75rem, 6vw, 4rem);
  margin-bottom: clamp(1.25rem, 3vw, 1.75rem);
  font-size: var(--step-2);
}

/* A closing aside under a section's main content — secondary to it, and carrying
   the gap off whatever grid or list it follows, since the grids have no bottom
   margin of their own. */
.section__note {
  margin-top: clamp(2.25rem, 5vw, 3rem);
  max-width: 44rem;
  color: var(--text-2);
  font-size: var(--step--1);
}

/* A note that introduces the grid instead of following it. It reads as the last
   line of the lead, so it sits close under it and owes only the gap above the
   grid. */
.section__note--intro {
  margin-top: 0;
  margin-bottom: clamp(1.5rem, 3.5vw, 2rem);
}

.section__lead:has(+ .section__note--intro) {
  margin-bottom: 0.75rem;
}

@media (min-width: 64em) {
  .section__intro {
    grid-template-columns: minmax(0, 1fr) 14rem;
    gap: 3rem;
    align-items: start;
  }

  .section__intro .section__head,
  .section__intro .section__lead {
    grid-column: 1;
  }

  .section__art {
    grid-row: 1 / 3;
    grid-column: 2;
  }

  .section__art .skull {
    width: 100%;
    margin-inline: 0;
  }
}

/* ---------- Prose ---------- */

.prose {
  max-width: 40rem;
  display: grid;
  gap: 1rem;
  color: var(--text-2);
  font-size: var(--step-1);
  line-height: 1.65;
}

/* The opening paragraph of a block carries its argument, so it is set at full
   contrast on a shorter measure — the entry point a skimmer needs before
   deciding whether to read the rest. */
.prose > p:first-child {
  max-width: 34rem;
  color: var(--ink);
}

.section--night .prose {
  color: var(--on-night-2);
}

.section--night .prose > p:first-child {
  color: var(--on-night);
}

/* .prose carries no margin of its own, which is right where it is the only
   thing in a section body and wrong where it follows one of the bordered
   blocks. The step matches .section__action, so everything that trails a block
   in a section body is set off from it by the same distance. */
:is(.card-grid, .people, .stages, .detail-list) + .prose {
  margin-top: 2.5rem;
}

.prose-split {
  display: grid;
  gap: 1rem 4rem;
}

@media (min-width: 64em) {
  .prose-split {
    grid-template-columns: 5fr 7fr;
  }
}

/* ═══════════════════════════ SPLIT LAYOUTS ═══════════════════════════ */

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
}

.split__skull {
  width: min(100%, 15rem);
  margin-inline: auto;
}

.split__label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

@media (min-width: 64em) {
  .split {
    grid-template-columns: 5fr 7fr;
    align-items: start;
  }

  .split--wide-first {
    grid-template-columns: 7fr 5fr;
  }

  .split__skull {
    margin-inline: 0;
  }

  .split--wide-first .split__skull {
    margin-inline: auto 0;
  }
}

/* ═══════════════════════════ HERO ═══════════════════════════ */

.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(2.5rem, 6vw, 5rem) clamp(3.5rem, 8vw, 6.5rem);
  background:
    radial-gradient(70% 70% at 78% 40%, var(--porcelain) 0%, rgb(251 249 247 / 0) 70%),
    var(--paper);
  border-bottom: 1px solid var(--rule);
}

/* Engineering paper behind the figure, fading out towards the copy. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grid-dot);
  background-size: var(--grid-size);
  -webkit-mask-image: radial-gradient(60% 70% at 75% 45%, #000 0%, transparent 75%);
  mask-image: radial-gradient(60% 70% at 75% 45%, #000 0%, transparent 75%);
  pointer-events: none;
}

/* The mark, set into the hero surface rather than laid over it. It is the logo
   repeated, so it is a background rather than an element in the accessibility
   tree. On a phone it sits in the corner above the copy, because the figure
   takes the room it would otherwise have. */
.hero__mark {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--ink);
  opacity: 0.05;
  -webkit-mask-image: var(--skull-glyph);
  mask-image: var(--skull-glyph);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: right -3rem top 4%;
  mask-position: right -3rem top 4%;
  -webkit-mask-size: auto 26%;
  mask-size: auto 26%;
}

.hero__inner {
  position: relative;
  display: grid;
  gap: clamp(2.5rem, 6vw, 3rem);
  align-items: center;
}

.hero__title {
  font-size: var(--step-5);
  line-height: 0.95;
  letter-spacing: -0.02em;
}

/* The verb is the whole proposition on this page, so it takes the accent and
   the italic rather than the weight jump it used to get. */
.hero__title b,
.hero__title em {
  color: var(--accent-ink);
  font-style: italic;
  font-weight: 500;
}

.hero__tagline {
  margin-top: 1.5rem;
  padding-top: 1.125rem;
  border-top: 1px solid var(--rule);
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.hero__statement {
  margin-top: 0.875rem;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-style: italic;
  font-weight: 500;
  line-height: 1.1;
}

.hero__body {
  margin-top: 1.25rem;
  max-width: 36rem;
  color: var(--text-2);
  font-size: var(--step-1);
  line-height: 1.55;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 2rem;
}

/* Stacked on small screens, both buttons take the full width so they do not end
   up as two mismatched blocks. */
.hero__actions .btn {
  flex: 1 1 100%;
}

.hero__figure {
  position: relative;
}

@media (min-width: 40em) {
  .hero__actions .btn {
    flex: 0 0 auto;
  }
}

@media (min-width: 64em) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  }

  /* The figure fills the right of the band from here, so the watermark goes
     back behind the copy where there is room for it. */
  .hero__mark {
    -webkit-mask-position: left -4rem bottom -10%;
    mask-position: left -4rem bottom -10%;
    -webkit-mask-size: auto 56%;
    mask-size: auto 56%;
    opacity: 0.04;
  }
}

/* ---------- The hero figure: the attack surface, drawn ---------- */

.system {
  position: relative;
  width: 100%;
  max-width: 38rem;
  margin-inline: auto;
  aspect-ratio: 600 / 520;
}

.system__lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.system__ring {
  fill: none;
  stroke: var(--rule-mid);
  stroke-width: 1;
  stroke-dasharray: 3 5;
  vector-effect: non-scaling-stroke;
}

.system__ring--inner {
  stroke: var(--rule);
  stroke-dasharray: none;
}

.system__wire {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1;
  stroke-dasharray: 5 4;
  vector-effect: non-scaling-stroke;
  opacity: 0.55;
}

.system__joint {
  fill: var(--porcelain);
  stroke: var(--ink);
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
}

.system__hub {
  position: absolute;
  top: 57.69%;
  left: 50%;
  width: 54%;
  transform: translate(-50%, -52%);
}

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

.system__node {
  position: absolute;
  display: grid;
  gap: 0.1rem;
  padding: 0.35rem 0.55rem;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: var(--porcelain);
  box-shadow: 2px 2px 0 var(--ink);
  transform: translate(-50%, -50%);
  white-space: nowrap;
}

/* A node that found something sits on the accent rather than on porcelain, so
   the figure's argument survives being glanced at rather than read. */
.system__node:has(.status--bad) {
  background: var(--accent-tint-soft);
}

.system__name {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.04em;
}

.system__node .status {
  font-size: 0.625rem;
}

/* Positions match heroNodes in src/components/diagrams.mjs (x/600, y/520). */
.system__node--1 { left: 15.33%; top: 18.46%; }
.system__node--2 { left: 50%; top: 7.69%; }
.system__node--3 { left: 85.33%; top: 18.46%; }
.system__node--4 { left: 9.33%; top: 57.69%; }
.system__node--5 { left: 91.33%; top: 57.69%; }
.system__node--6 { left: 17.33%; top: 91.92%; }
.system__node--7 { left: 82.67%; top: 91.92%; }

.system__caption {
  position: absolute;
  right: 0;
  bottom: -2.75rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  text-align: right;
}

@media (max-width: 29.99em) {
  .system__node--minor,
  .system__wire--minor {
    display: none;
  }

  .system__node {
    padding: 0.25rem 0.4rem;
  }

  .system__hub {
    width: 52%;
  }
}

@media (min-width: 48em) {
  .system__name {
    font-size: 0.75rem;
  }

  .system__node .status {
    font-size: 0.6875rem;
  }

  .system__caption {
    bottom: -2.25rem;
  }
}

/* ═══════════════════════════ FACTS ROW ═══════════════════════════ */

/* Three short claims under the hero. Stacked on a phone and a single row from
   48em, so the first thing under the headline is three lines a reader takes in
   without deciding to. */
.facts {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border-block: 1px solid var(--rule);
}

.facts li {
  position: relative;
  padding: 0.875rem 0 0.875rem 1.75rem;
  background: var(--paper);
  color: var(--text-2);
  font-size: var(--step--1);
}

/* Centred on the first line rather than on the box: the third claim wraps to
   two lines at most widths, and a marker centred on the cell drifts down it. */
.facts li::before {
  content: "";
  position: absolute;
  top: calc(0.875rem + 0.72em);
  left: 0;
  width: 0.75rem;
  height: 2px;
  background: var(--accent);
}

@media (min-width: 48em) {
  .facts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .facts li {
    padding-inline: 1.75rem 1.25rem;
  }

  .facts li::before {
    left: 0.75rem;
  }
}

/* ═══════════════════════════ CARD GRIDS ═══════════════════════════ */

/* A 1px gap over a rule-coloured background draws the dividers, so no cell
   needs a border of its own. */
.stages,
.card-grid,
.people {
  position: relative;
  display: grid;
  gap: 1px;
  background: var(--rule-mid);
  border: 1.5px solid var(--ink);
}

.stage,
.card,
.person {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--porcelain);
}

.section--porcelain .stage,
.section--porcelain .card,
.section--porcelain .person,
.section--plum .stage,
.section--plum .card,
.section--plum .person {
  background: var(--paper);
}

.stage__text,
.card__text,
.person {
  padding: clamp(1.25rem, 3.5vw, 1.75rem);
}

/* The art plate: engineering paper behind the mascot, with the card's copy on
   plain stock below it. It is the parent site's capability card, which is the
   one component both sites needed and neither could share as code. */
.card__art,
.stage__art {
  display: grid;
  place-items: center;
  min-height: 8.5rem;
  padding: 1rem;
  border-bottom: 1px solid var(--rule-mid);
  background-color: var(--paper);
  background-image: var(--grid-dot);
  background-size: var(--grid-size);
}

.section--porcelain .card__art,
.section--porcelain .stage__art {
  background-color: var(--porcelain);
}

.card__art .skull,
.stage__art .skull {
  width: 7.5rem;
}

.card:hover {
  background: var(--accent-tint-soft);
}

.card:focus-within {
  background: var(--accent-tint-soft);
}

.card__index,
.stage__index,
.detail__index,
.tier__index {
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
}

.card__title,
.stage__title {
  margin-top: 0.35rem;
  font-size: var(--step-2);
}

.card__link {
  text-decoration: none;
}

/* The whole card is the hit area; the link keeps the accessible name. */
.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

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

.card__link:focus-visible::after {
  outline: 2px solid var(--ink);
  outline-offset: -6px;
}

.card__summary,
.stage__lead {
  margin-top: 0.6rem;
  color: var(--text-2);
}

.stage__lead {
  color: var(--ink);
  font-weight: 500;
}

.stage__body {
  margin-top: 0.5rem;
  color: var(--text-2);
  font-size: var(--step--1);
}

.card__more {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: auto;
  padding-top: 1rem;
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.card:hover .arrow,
.card:hover .icon--arrow {
  transform: translateX(4px);
}

@media (min-width: 40em) {
  .stages,
  .card-grid,
  .people {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Two columns, odd number of cards: the last one takes the empty cell with
     it, so the grid's rule-coloured background is never left showing. */
  .card-grid--flush > .card:last-child:nth-child(odd) {
    grid-column: span 2;
  }

  .card-grid--flush > .card:last-child:nth-child(odd) .card__art .skull {
    width: 9rem;
  }
}

@media (min-width: 64em) {
  .card-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .card__art,
  .stage__art {
    min-height: 10rem;
  }

  .card__art .skull,
  .stage__art .skull {
    width: 8.5rem;
  }

  .card-grid--flush > .card:last-child:nth-child(3n) {
    grid-column: auto;
  }

  .card-grid--flush > .card:last-child:nth-child(3n + 1) {
    grid-column: span 3;
  }

  .card-grid--flush > .card:last-child:nth-child(3n + 2) {
    grid-column: span 2;
  }
}

/* ---------- Founders ---------- */

.person__name {
  font-size: var(--step-3);
}

.person__role {
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The part a reader is actually weighing. Set at body size rather than as a
   caption, because with no case studies yet this is the evidence. */
.person__background {
  margin-top: 0.75rem;
  color: var(--text-2);
}

.person__site {
  margin-top: auto;
  padding-top: 1rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
}

.person__site a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding-block: 0.25rem;
  color: var(--text-2);
  text-decoration-color: var(--rule-mid);
}

.person__site a:hover {
  color: var(--accent-ink);
  text-decoration-color: var(--accent);
}

.person__site a:hover .icon {
  transform: translate(2px, -2px);
}

/* ---------- The family strip ----------
   Two panels of the same character, on the about page. The accent bar down the
   left of each is the brand's own, which is the whole device: one drawing, two
   colours, and the reader works out the rest without a paragraph. */

.family-strip {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule-mid);
}

.family-strip__label {
  margin-bottom: 1rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.family-strip__list {
  display: grid;
  gap: 1rem;
}

.family-strip__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--accent);
  background: var(--porcelain);
}

.section--grid .family-strip__item,
.section--porcelain .family-strip__item {
  background: var(--paper);
}

.family-strip__item--solutions {
  border-left-color: var(--sol);
}

.family-strip__item .skull {
  width: 3.25rem;
  flex: none;
}

.family-strip__item p {
  display: grid;
  line-height: 1.35;
}

.family-strip__item strong {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 600;
}

.family-strip__item strong a {
  text-decoration: none;
}

.family-strip__item strong a:hover {
  text-decoration: underline;
}

.family-strip__item span {
  color: var(--text-2);
  font-size: var(--step--1);
}

.family-strip__note {
  position: absolute;
  top: 0.5rem;
  right: 0.75rem;
  color: var(--accent-ink) !important;
  font-family: var(--font-mono);
  font-size: var(--step--2) !important;
}

@media (min-width: 48em) {
  .family-strip__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ═══════════════════════════ DETAIL LISTS ═══════════════════════════ */

/* The specification sheet: term on the left, description on the right. */
.detail-list {
  display: grid;
  border-top: 1.5px solid var(--ink);
}

.detail {
  display: grid;
  gap: 0.35rem 2.5rem;
  padding-block: 1.4rem;
  border-bottom: 1px solid var(--rule-mid);
}

.detail__index {
  margin-bottom: 0.25rem;
}

.detail__title {
  font-size: var(--step-2);
}

.detail__title a {
  text-decoration-color: var(--rule-mid);
}

.detail__title a:hover {
  text-decoration-color: var(--accent);
}

.detail__body {
  max-width: 44rem;
  color: var(--text-2);
}

.section--night .detail-list {
  border-top-color: var(--rule-night);
}

.section--night .detail {
  border-bottom-color: var(--rule-night);
}

.section--night .detail__body {
  color: var(--on-night-2);
}

@media (min-width: 48em) {
  .detail {
    grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
    padding-block: 1.6rem;
  }

  .detail-list--numbered .detail {
    grid-template-columns: 3rem minmax(0, 14rem) minmax(0, 1fr);
    align-items: baseline;
  }

  .detail__index {
    margin-bottom: 0;
  }
}

/* ═══════════════════════════ DIAGRAMS ═══════════════════════════ */

.diagram {
  padding: clamp(1rem, 3vw, 1.75rem);
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: var(--porcelain);
}

/* The bordered blocks carry no bottom margin of their own, so anything that
   follows one has to take the gap. Without this a figure landing under a card
   grid reads as the last cell of it: two 1.5px borders a hairline apart, which
   the eye joins into one box. The step matches .section__action, so everything
   that trails a block in a section body is set off by the same distance. */
:is(.card-grid, .stages, .people, .detail-list, .tiers, .diagram, .finding)
  + :is(.diagram, .finding, .split, .card-grid, .stages, .detail-list, .pullquote) {
  margin-top: clamp(2rem, 4vw, 2.75rem);
}

.section--porcelain .diagram {
  background: var(--paper);
}

.diagram__caption {
  margin-bottom: 1.25rem;
  color: var(--text-2);
  font-size: var(--step--1);
}

.diagram__fig {
  margin-right: 0.5rem;
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--rule-mid);
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
}

/* ---------- The chain: a column on phones, a row from tablet up ---------- */

.chain {
  display: grid;
  gap: 1.5rem;
}

.chain__step {
  position: relative;
}

/* The wire between steps. */
.chain__step + .chain__step::before {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 1.25rem;
  width: 2px;
  height: 1.5rem;
  background: repeating-linear-gradient(to bottom, var(--ink) 0 4px, transparent 4px 7px);
}

.chain__box {
  position: relative;
  display: grid;
  gap: 0.2rem;
  height: 100%;
  padding: 0.75rem 0.85rem;
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: var(--paper);
}

.section--porcelain .chain__box {
  background: var(--porcelain);
}

/* The last step is the one that is not like the others, so it is the one that
   takes the offset and the accent. */
.chain__step:last-child .chain__box {
  background: var(--accent-wash);
  box-shadow: 3px 3px 0 var(--ink);
}

.chain__index {
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
}

.chain__title {
  font-family: var(--font-body);
  font-weight: 700;
  line-height: 1.25;
}

.chain__detail {
  color: var(--text-2);
  font-size: var(--step--2);
  line-height: 1.45;
}

.chain__box .status {
  margin-top: 0.35rem;
}

.chain__note {
  margin-top: 1.25rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--accent);
  color: var(--text-2);
  font-size: var(--step--1);
}

@media (min-width: 48em) {
  .chain {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.25rem;
    align-items: stretch;
  }

  .chain__step + .chain__step::before {
    top: 2.2rem;
    right: 100%;
    bottom: auto;
    left: auto;
    width: 1.25rem;
    height: 2px;
    background: repeating-linear-gradient(to right, var(--ink) 0 4px, transparent 4px 7px);
  }
}

/* ---------- The finding: a printout on porcelain ---------- */

.finding {
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: var(--porcelain);
  box-shadow: 8px 8px 0 rgb(23 20 28 / 0.9);
}

.finding__head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  padding: 0.9rem 1.1rem;
  border-bottom: 1.5px dashed var(--ink);
}

.finding__title {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 600;
}

.finding__meta {
  align-self: center;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finding__severity {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-bottom: 1px solid var(--rule-mid);
}

.finding__severity li {
  padding: 0.5rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  text-align: center;
}

.finding__severity li + li {
  border-left: 1px solid var(--rule);
}

.finding__severity .is-now {
  background: var(--ink);
  color: var(--porcelain);
}

.finding__row {
  display: grid;
  gap: 0.15rem 1.5rem;
  padding: 0.8rem 1.1rem;
}

.finding__row + .finding__row {
  border-top: 1px solid var(--rule);
}

.finding__field {
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.finding__value {
  color: var(--text-2);
  font-size: var(--step--1);
  overflow-wrap: anywhere;
}

.finding__foot {
  padding: 0.8rem 1.1rem;
  border-top: 1.5px dashed var(--ink);
}

@media (min-width: 40em) {
  .finding__row {
    grid-template-columns: 9.5rem minmax(0, 1fr);
    align-items: baseline;
  }
}

@media (min-width: 64em) {
  .finding {
    transform: rotate(-0.5deg);
  }
}

/* ═══════════════════════════ ASSESSMENT TIERS ═══════════════════════════ */

/* The ladder on /pricing. Four cells side by side would read as packages set up
   to be compared against each other, which is the one thing this page is not:
   they are five points on a single scale of how complex the application is. So
   they run down the page on the specification grid instead. */
.tiers {
  display: grid;
  border-top: 1.5px solid var(--ink);
}

.tier {
  display: grid;
  gap: 1rem 2.5rem;
  padding-block: clamp(2rem, 4.5vw, 2.75rem);
  border-bottom: 1px solid var(--rule-mid);
}

.tier__head {
  display: grid;
  gap: 0.75rem;
  align-content: start;
}

.tier__art .skull {
  width: 9rem;
}

.tier__name {
  font-size: var(--step-3);
}

/* The line a reader is scanning for: whether this one is them. Full contrast,
   so it is found before the paragraph under it is read. */
.tier__for {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-style: italic;
  font-weight: 500;
  line-height: 1.2;
}

.tier__lead {
  margin-top: 0.75rem;
  color: var(--text-2);
}

.tier__scope {
  margin-top: 0.25rem;
}

/* What this tier does not stretch to. It is set at the note size rather than
   hidden further down the page, because a limit found after the price is a
   limit the reader thinks was being kept from them. */
.tier__note {
  margin-top: 1rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--accent);
  color: var(--text-2);
  font-size: var(--step--1);
}

/* Effort, quote and action. The effort and the quote are one unit, and the
   button starts the line below them on a phone, so every rung of the ladder has
   the same shape whether or not it has a day count to show. */
.tier__action {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
}

.tier__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
}

/* Days carry the prominence a price would, because days are the number this
   page can actually stand behind. */
.tier__effort {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 600;
  line-height: 1.1;
}

.tier__quote {
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.04em;
}

@media (min-width: 40em) {
  .tier__meta {
    flex-direction: row;
    align-items: baseline;
    gap: 1rem;
  }

  .tier__action {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    width: 100%;
  }
}

@media (min-width: 48em) {
  .tier {
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  }
}

/* ═══════════════════════════ PAGE HEAD ═══════════════════════════ */

.page-head {
  position: relative;
  overflow: hidden;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  background:
    radial-gradient(60% 80% at 85% 50%, var(--porcelain) 0%, rgb(251 249 247 / 0) 70%),
    var(--paper);
  border-bottom: 1px solid var(--rule);
}

.page-head::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grid-dot);
  background-size: var(--grid-size);
  -webkit-mask-image: radial-gradient(50% 80% at 85% 50%, #000 0%, transparent 75%);
  mask-image: radial-gradient(50% 80% at 85% 50%, #000 0%, transparent 75%);
  pointer-events: none;
}

.page-head__inner {
  position: relative;
  display: grid;
  gap: 2rem;
  align-items: center;
}

.page-head h1 {
  font-size: var(--step-5);
  line-height: 0.98;
}

.page-head h1 em {
  color: var(--accent-ink);
}

.page-head__lead {
  max-width: 40rem;
  margin-top: 1.25rem;
  color: var(--text-2);
  font-size: var(--step-1);
  line-height: 1.55;
}

.page-head__meta {
  margin-top: 1rem;
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.page-head__art .skull {
  width: min(60vw, 15rem);
  margin-inline: auto;
}

.page-head--center {
  text-align: center;
}

.page-head--center .label,
.page-head--center .page-toc ul {
  justify-content: center;
}

.page-head--center .page-head__lead {
  margin-inline: auto;
}

.page-head--center .page-head__art .skull {
  width: min(70vw, 17rem);
  margin: 0 auto 1.5rem;
}

@media (min-width: 64em) {
  .page-head__inner {
    grid-template-columns: minmax(0, 1fr) 17rem;
  }

  .page-head--center .page-head__inner {
    grid-template-columns: minmax(0, 1fr);
  }
}

.page-toc ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  margin-top: 2rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
}

.page-toc a {
  display: inline-block;
  padding-block: 0.3125rem;
  color: var(--text-2);
  text-decoration-color: var(--rule-mid);
}

.page-toc a:hover {
  color: var(--accent-ink);
  text-decoration-color: var(--accent);
}

/* ═══════════════════════════ CONTACT ═══════════════════════════ */

.contact-address {
  margin-top: 1.5rem;
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 600;
  overflow-wrap: anywhere;
}

.enquiry {
  max-width: 44rem;
  padding: clamp(1.25rem, 3vw, 2rem);
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: var(--porcelain);
}

.section--porcelain .enquiry {
  background: var(--paper);
}

/* The action leads the block rather than closing it: the next step is the point
   of the page, and a reader should not have to get past a list of things to
   mention before they find the way to send the email. */
.enquiry__action {
  margin: 0;
}

.enquiry__action .btn {
  display: flex;
}

.enquiry__prompt {
  margin-top: 1.75rem;
  font-weight: 700;
}

.enquiry__points {
  margin-top: 0.9rem;
  border-top: 1.5px solid var(--ink);
}

.enquiry__points li {
  position: relative;
  padding: 0.7rem 0 0.7rem 1.75rem;
  border-bottom: 1px solid var(--rule);
  color: var(--text-2);
}

.enquiry__points li::before {
  content: "";
  position: absolute;
  top: 1.35em;
  left: 0;
  width: 0.75rem;
  height: 2px;
  background: var(--accent);
}

.enquiry__note {
  margin-top: 1.25rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--accent);
  color: var(--text-2);
  font-size: var(--step--1);
}

@media (min-width: 40em) {
  .enquiry__action .btn {
    display: inline-flex;
  }
}

/* ═══════════════════════════ CLOSING CALL TO ACTION ═══════════════════════════ */

.cta {
  --mark-face: var(--on-night);
  --mark-ink: var(--night-deep);
  position: relative;
  padding-block: calc(clamp(3.5rem, 9vw, 5.5rem) + 1rem) clamp(3.5rem, 9vw, 5.5rem);
  background:
    radial-gradient(60% 80% at 82% 20%, rgb(189 148 195 / 0.16) 0%, transparent 70%),
    var(--night);
  color: var(--on-night);
}

.cta__inner {
  position: relative;
  display: grid;
  gap: 2rem;
}

.cta__prompt {
  margin-bottom: 1rem;
  color: var(--on-night-2);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  overflow-wrap: anywhere;
}

.cta__prompt span {
  color: var(--accent);
}

.cta__prompt::after {
  content: "▋";
  margin-left: 0.2rem;
  color: var(--accent);
}

@media (prefers-reduced-motion: no-preference) {
  .cta__prompt::after {
    animation: caret 1.1s steps(1) infinite;
  }
}

@keyframes caret {
  50% {
    opacity: 0;
  }
}

.cta h2 {
  color: var(--on-night);
  font-size: var(--step-4);
}

.cta h2 em {
  color: var(--accent-on-night);
}

.cta__text p {
  margin-top: 1rem;
  max-width: 34rem;
  color: var(--on-night-2);
  font-size: var(--step-1);
}

.cta__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
}

.cta__actions .btn {
  align-self: stretch;
}

.cta__email {
  color: var(--on-night-2);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  overflow-wrap: anywhere;
  text-decoration-color: rgb(239 233 239 / 0.35);
}

.cta__email:hover {
  color: var(--on-night);
  text-decoration-color: var(--accent);
}

.cta__art {
  display: grid;
  justify-items: center;
}

.cta__art .skull {
  width: min(100%, 13rem);
}

/* The mascot's ink contour is very nearly the night's own value, so on this
   band the drawing's outline all but disappears and only the face reads. The
   same faint lift the sleeping footer skull takes puts the silhouette back. */
.cta__art .skull__img {
  filter: drop-shadow(0 0 20px rgb(189 148 195 / 0.28));
}

.cta .skull__caption {
  color: var(--on-night-2);
}

.cta :focus-visible {
  outline-color: var(--on-night);
}

@media (min-width: 40em) {
  .cta__actions {
    flex-direction: row;
    align-items: center;
    gap: 1.5rem;
  }

  .cta__actions .btn {
    align-self: center;
  }
}

@media (min-width: 64em) {
  .cta__inner {
    grid-template-columns: minmax(0, 1fr) 13rem;
    column-gap: 3rem;
    align-items: center;
  }

  .cta__art {
    grid-row: 1 / 3;
    grid-column: 2;
  }
}

/* ═══════════════════════════ FOOTER ═══════════════════════════ */

.site-footer {
  --mark-face: var(--on-night);
  --mark-ink: var(--night-deep);
  position: relative;
  margin-top: 30px;
  padding-top: clamp(3rem, 6vw, 4.5rem);
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--night);
  color: var(--on-night-2);
}

/* The teeth again, so the footer and the closing slab are recognisably the same
   mouth rather than two dark bands that happen to be adjacent. */
.site-footer::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 100%;
  left: 0;
  height: 30px;
  background-color: var(--night);
  -webkit-mask: var(--teeth) repeat-x center bottom / 98px 30px;
  mask: var(--teeth) repeat-x center bottom / 98px 30px;
  transform: scaleY(-1);
  pointer-events: none;
}

/* The closing call to action already ends on the night, so a second set of teeth
   between the two would be a mouth inside a mouth — and the 30px margin the
   teeth hang in would show a strip of paper between two dark bands.

   Matched through <main> rather than as a sibling of the slab: the call to
   action is the last thing inside the document's main landmark, and the footer
   is a sibling of that landmark, so .cta + .site-footer never matches anything.
   Only /contact and /404 end without one, and those are the two pages that
   still want the edge. */
main:has(> .cta:last-child) + .site-footer {
  margin-top: 0;
}

main:has(> .cta:last-child) + .site-footer::before {
  content: none;
}

.site-footer a {
  color: var(--on-night);
  text-decoration-color: rgb(239 233 239 / 0.35);
}

.site-footer a:hover {
  text-decoration-color: var(--accent);
}

.site-footer__inner {
  position: relative;
  display: grid;
  gap: 2.5rem;
  padding-bottom: 2.5rem;
}

.brand--footer {
  display: flex;
  color: var(--on-night);
}

.site-footer__tagline {
  margin-top: 1rem;
  color: var(--on-night);
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-style: italic;
}

.site-footer__statement {
  max-width: 26rem;
  margin-top: 0.5rem;
  font-size: var(--step--1);
}

.site-footer__parent {
  margin-top: 0.9rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--sol);
  font-size: var(--step--1);
}

.site-footer__nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem 1.5rem;
}

/* Two narrow columns cannot hold the email address on one line, so it takes the
   full row until there is room for three columns. */
.site-footer__group--contact {
  grid-column: 1 / -1;
}

.site-footer__heading {
  margin-bottom: 0.9rem;
  color: var(--on-night-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.site-footer__nav ul {
  display: grid;
  gap: 0.45rem;
  font-size: var(--step--1);
}

.site-footer__nav a {
  display: inline-block;
  padding-block: 0.1875rem;
  text-decoration: none;
  /* The email address is one long unbreakable token — let it wrap rather than
     push the footer grid wider than the viewport. */
  overflow-wrap: anywhere;
}

.site-footer__nav a:hover {
  text-decoration: underline;
}

.site-footer__skull {
  width: 9rem;
  justify-self: end;
  opacity: 0.95;
}

/* The footer skull sleeps on the dark ground, so it gets a faint lift to stay
   readable against the night. */
.site-footer__skull .skull__img {
  filter: drop-shadow(0 0 18px rgb(189 148 195 / 0.22));
}

.site-footer .divider {
  margin-top: clamp(2rem, 5vw, 3rem);
}

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  padding-block: 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
  font-family: var(--font-mono);
  font-size: var(--step--2);
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
}

.site-footer__base a {
  color: inherit;
}

@media (min-width: 48em) {
  /* The two link columns size to their content, but the contact column gets a
     floor first, so the email address always has room to sit on one line. */
  .site-footer__nav {
    grid-template-columns: auto auto minmax(13rem, 1fr);
    gap: 2rem 2.5rem;
  }

  .site-footer__group--contact {
    grid-column: auto;
  }
}

@media (min-width: 64em) {
  .site-footer__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    gap: 3rem;
    padding-right: 10rem;
  }

  .site-footer__skull {
    position: absolute;
    right: 0;
    bottom: 0;
  }
}
