/*
 * Tokos Health one-pager: immersive and mobile-first, over the Jade Tide (site/tide.js), in light and dark.
 *
 * Colour. The page uses only the brand's site tokens (--site-*: brand/tokens.js, written into tokens.css by the build),
 * as rgb(var(--site-token)) or rgb(var(--site-token) / alpha), never a literal colour (masks use black as alpha only).
 * The app's own tokens (--background, --primary, …) belong to the live phones (phone.css, story.css); nothing here
 * reads them. One set of rules serves both themes: html[data-theme] swaps the tokens (site/theme.js sets it before first
 * paint; without script tokens.css follows the system), and the few page values that differ by more than a token are
 * set once, under "themes". Roles: teal for links, the active section, icons, and focus rings; coral only for the one
 * italic word per headline (display sizes), the live dots, and tiny highlights; deep green solid buttons in light, a
 * near-white pill in dark. Every text pair is WCAG 2.2 AA in both themes (ratios are noted in brand/tokens.js).
 *
 * Type is the app's: Instrument Serif for display, Manrope for everything else. Layout is mobile-first; sections follow
 * GetLayers compositions (recorded in getlayers.json): artist-hero, artist-process (mirrored, for the story),
 * marcus-vane-story + an artist-about ledger, artist-cta, artist-footer.
 *
 * Motion animates transform and opacity, plus the one-shot reveals (blur, and a mask sweep on titles) and the loader's
 * stroke draw. A theme switch is a 250 ms View Transition crossfade (main.js marks it with html.theme-switching).
 * prefers-reduced-motion turns every entrance into a plain fade and stills everything else; html.motion-paused (the
 * pause switch) stills the loops. main.js sets the state classes (see its header); the hooks styled here: html.intro /
 * is-open / is-settled / reveal-ready / story-live / motion-paused / menu-open / tide-on / tide-off,
 * [data-header].is-scrolled, [data-reveal].is-in / .is-done, .story-step.is-active, .seg.is-active, .live-dot.is-idle,
 * [data-menu-button][aria-expanded], [data-motion-toggle][aria-pressed], and .nav-link[aria-current="true"]; and the
 * story's --stick, --tail, and --card-h. The story's live phone styles itself (site/story, published as story.css).
 */

/* ---------- foundation ---------- */

:root {
  --gutter: 20px;
  --content: 1200px;
  --bar-h: 56px;
  /* Launched from the home screen, the bar keeps a little air under the status bar. */
  --bar-top: max(10px, calc(env(safe-area-inset-top) + 6px));
  /* Where the fixed header bar ends; pinned things, anchor jumps, and focused elements clear it. */
  --header-space: calc(var(--bar-top) + var(--bar-h));
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

@media (min-width: 600px) {
  :root {
    --gutter: 32px;
  }
}

@media (min-width: 900px) {
  :root {
    --bar-h: 64px;
  }
}

@media (min-width: 960px) {
  :root {
    --gutter: 48px;
  }
}

/* ---------- themes ---------- */

/*
 * Page values built from the site tokens. Hairlines and tints are the ink at low alpha, so they read the same over the
 * moving scene in either theme. The logo's four parts take --logo-* (a context may override one, as the footer's
 * wordmark does). Dark is the default; light is html[data-theme="light"], or the system's choice without script.
 */
:root {
  --hairline: rgb(var(--site-ink) / 0.12);
  --tint: rgb(var(--site-ink) / 0.06);
  --logo-ring: rgb(var(--site-logo-ring));
  --logo-dot: rgb(var(--site-logo-dot));
  --logo-word: rgb(var(--site-logo-word));
  --logo-sub: rgb(var(--site-logo-sub));
  /* The form panel's top: a raised sheen in dark, plain white in light. */
  --panel-top: var(--site-surface-2);
  /* The still of the water (before the tide draws, or html.tide-off): deep green in dark, teal mist in light. */
  --still-top: var(--site-hero);
  --still-low: rgb(var(--site-hero) / 0.85);
}

:root[data-theme="light"] {
  --panel-top: var(--site-surface);
  --still-top: var(--site-surface-2);
  --still-low: rgb(var(--site-primary) / 0.12);
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --panel-top: var(--site-surface);
    --still-top: var(--site-surface-2);
    --still-low: rgb(var(--site-primary) / 0.12);
  }
}

/* ---------- base ---------- */

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

[hidden] {
  display: none !important;
}

/*
 * color-scheme (scrollbars, form controls) comes with each theme's tokens in tokens.css.
 * overflow-x on <html> keeps <body>'s own clip from being handed to the viewport (where it would stop clipping): the
 * hero's scrim and the titles' reveal room reach past the screen's edge, and a page wider than the screen makes mobile
 * browsers lay out fixed elements (the header) against the wider page. clip, not hidden, on <body>: it makes no scroll
 * container, so the story's sticky phone still pins to the viewport.
 */
html {
  overflow-x: hidden;
  overflow-x: clip;
  background-color: rgb(var(--site-bg));
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Anchor jumps and keyboard focus land below the fixed header (WCAG 2.4.11). */
  scroll-padding-top: calc(var(--header-space) + 12px);
  /* The loader holds the scroll briefly; reserving the scrollbar's gutter keeps the page from shifting when it lets go. */
  scrollbar-gutter: stable;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

body {
  margin: 0;
  min-height: 100vh;
  overflow-x: clip;
  color: rgb(var(--site-ink));
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.55;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

h1,
h2,
h3,
p,
ol,
ul,
dl,
dd,
figure {
  margin: 0;
}

ol,
ul {
  padding: 0;
  list-style: none;
}

a,
button,
input {
  color: inherit;
}

button,
input {
  font: inherit;
}

strong {
  font-weight: 700;
}

svg {
  flex: none;
}

img {
  max-width: 100%;
}

::selection {
  background: rgb(var(--site-primary) / 0.3);
  color: rgb(var(--site-ink));
}

/* Teal, 2px, offset: 5.3:1 on the light ground and 7.7:1 on the dark one, and as much on every surface here. */
:focus-visible {
  outline: 2px solid rgb(var(--site-primary-strong));
  outline-offset: 3px;
}

/* Script moves focus to non-controls so Tab and screen readers carry on from there: a section's heading (or <main>) after
   a same-page jump, the form's success title. They take focus without a ring (a heading's box is padded for its reveal,
   so a ring would float far from its text); after a keyboard jump a heading shows a soft teal underline instead, and
   <main> shows nothing. Interactive controls always keep their ring. */
[tabindex="-1"]:not(a, button, input, select, textarea, summary):focus {
  outline: none;
}

:is(h1, h2, h3)[tabindex="-1"]:focus-visible,
:is(h1, h2, h3)[tabindex="-1"]:focus-visible em {
  text-decoration: underline 2px rgb(var(--site-primary-strong) / 0.7);
  text-underline-offset: 0.16em;
}

.icon {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

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

.container {
  width: 100%;
  max-width: calc(var(--content) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right));
}

.skip-link {
  position: fixed;
  top: calc(var(--bar-top) + 6px);
  left: 16px;
  z-index: 200;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgb(var(--site-solid));
  color: rgb(var(--site-on-solid));
  font-weight: 700;
  text-decoration: none;
  transform: translateY(calc(-100% - 40px));
}

.skip-link:focus {
  transform: none;
}

/* ---------- the logo (partials/logo*.html: one inline SVG each) ---------- */

/* Sized by height wherever it's used (width follows its viewBox); coloured per theme through --logo-*. It has no
   intrinsic width, so a crowded flex row must never shrink it (flex: none). */
.tk-logo {
  display: block;
  flex: none;
  width: auto;
  height: 32px;
}

.tk-logo__ring,
.tk-logo__ring * {
  stroke: var(--logo-ring);
}

.tk-logo__dot,
.tk-logo__dot * {
  fill: var(--logo-dot);
}

.tk-logo__word,
.tk-logo__word * {
  fill: var(--logo-word);
}

.tk-logo__sub,
.tk-logo__sub * {
  fill: var(--logo-sub);
}

/* ---------- the backdrop: the tide, its still, and the veil ---------- */

#tide,
body::before,
.tide-veil {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  /* The large viewport: Safari's toolbar coming and going never resizes the scene. */
  height: 100vh;
  height: 100lvh;
  pointer-events: none;
}

#tide {
  display: block;
}

.tide-off #tide {
  display: none;
}

/* Until tide.js draws — and whenever it can't (html.tide-off) — a still of the same water, per theme. */
body::before {
  content: "";
  background:
    radial-gradient(70% 45% at 88% 6%, rgb(var(--site-accent) / 0.08), transparent 70%),
    radial-gradient(90% 60% at 8% 0%, rgb(var(--site-primary) / 0.16), transparent 70%),
    radial-gradient(120% 70% at 30% 100%, var(--still-low), transparent 75%),
    linear-gradient(180deg, rgb(var(--still-top)) 0%, rgb(var(--site-bg)) 80%);
}

.tide-on body::before {
  display: none;
}

/*
 * Calms the tide under everything past the hero, so text keeps its contrast; main.js scrubs its opacity with scroll.
 * A flat colour shaped by a mask (not a gradient of colours), so a theme switch can crossfade it.
 */
.tide-veil {
  opacity: 0;
  background-color: rgb(var(--site-bg) / 0.84);
  -webkit-mask-image: radial-gradient(140% 100% at 50% 35%, rgb(0 0 0 / 0.6), #000);
  mask-image: radial-gradient(140% 100% at 50% 35%, rgb(0 0 0 / 0.6), #000);
}

main,
.site-footer {
  position: relative;
  z-index: 1;
}

/* ---------- type ---------- */

.display,
.title {
  font-family: var(--font-serif);
  font-weight: 400;
  text-wrap: balance;
}

.display {
  line-height: 0.98;
  letter-spacing: -0.02em;
}

.title {
  font-size: clamp(40px, 3.4vw + 26px, 76px);
  line-height: 1.02;
  letter-spacing: -0.015em;
}

/* The one italic phrase per headline: Instrument Serif Italic in coral, at display sizes only. An inline block keeps the
   phrase on one line wherever it fits (as nowrap would), yet lets it wrap inside itself where it can't, as under a
   reader's text-spacing override (WCAG 1.4.12) on a 320px screen, instead of running off the edge. */
.display em,
.title em {
  display: inline-block;
  font-style: italic;
  color: rgb(var(--site-accent));
}

/* Small caps behind a short lead rule, in teal. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: rgb(var(--site-primary-strong));
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.eyebrow::before {
  content: "";
  width: 28px;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
}

.lead {
  max-width: 44ch;
  color: rgb(var(--site-ink-soft));
  font-size: clamp(17px, 0.35vw + 15.6px, 20px);
  line-height: 1.55;
  text-wrap: pretty;
}

/* ---------- buttons ---------- */

.btn {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 54px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  font-size: 16px;
  line-height: 20px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 0.25s var(--ease-out);
}

/* Hover is a veil of the control's own ink, faded in: no colour transitions, no layout. */
.btn::before,
.pill-link::before,
.tool::before,
.menu-button::before,
.nav-link::before,
.motion-toggle-text::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  transition: opacity 0.25s var(--ease-out);
}

.btn .icon {
  width: 18px;
  height: 18px;
  stroke-width: 2;
  transition: transform 0.3s var(--ease-out);
}

/* Deep green with white text in light (12.3:1); a near-white pill with deep green text in dark (11.0:1). */
.btn-solid {
  background: rgb(var(--site-solid));
  color: rgb(var(--site-on-solid));
  box-shadow: var(--site-shadow-solid);
}

.btn-ghost {
  background: rgb(var(--site-bg) / 0.35);
  box-shadow: inset 0 0 0 1px rgb(var(--site-ink) / 0.26);
  color: rgb(var(--site-ink));
}

.btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: progress;
}

@media (hover: hover) {
  .btn:hover::before {
    opacity: 0.08;
  }
}

/* ---------- header: a compact glass bar (GetLayers stride-nav) ---------- */

.site-header {
  position: fixed;
  top: var(--bar-top);
  right: max(10px, env(safe-area-inset-right));
  left: max(10px, env(safe-area-inset-left));
  z-index: 50;
  display: flex;
  justify-content: center;
  pointer-events: none;
}

/* Its edges sit 10px outside the content, so the logo lines up with the page's left edge at every width. */
.header-bar {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  max-width: calc(var(--content) + 2 * (var(--gutter) - 10px));
  height: var(--bar-h);
  padding: 0 6px 0 calc(var(--gutter) - 10px);
  border-radius: 999px;
  pointer-events: auto;
}

/* Glass: the page's one backdrop blur, and it never animates. */
.header-bar::before,
.header-bar::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}

.header-bar::before {
  background-color: rgb(var(--site-bg) / var(--site-glass));
  box-shadow: inset 0 0 0 1px rgb(var(--site-ink) / 0.09);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
}

/* Firmer once the page has scrolled (main.js: .is-scrolled), and while the menu is open. */
.header-bar::after {
  background-color: rgb(var(--site-bg) / var(--site-glass-scrolled));
  box-shadow: var(--site-shadow-bar);
  opacity: 0;
  transition: opacity 0.45s var(--ease-out);
}

.is-scrolled .header-bar::after,
.menu-open .header-bar::after {
  opacity: 1;
}

.brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  border-radius: 10px;
  text-decoration: none;
}

.site-header .brand {
  margin-right: auto;
}

.site-header .brand .tk-logo {
  height: 34px;
}

/* The early-access pill: the header's one solid control. Like the menu button, it never shrinks below its target size. */
.pill-link {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  flex: none;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  border-radius: 999px;
  background: rgb(var(--site-solid));
  color: rgb(var(--site-on-solid));
  font-size: 14px;
  line-height: 18px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

/* Icon tools (theme, motion) and the menu button: 44px rounds in ink, a veil on hover. */
.tool,
.menu-button {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: rgb(var(--site-ink-soft));
  cursor: pointer;
}

.menu-button {
  flex: none;
  color: rgb(var(--site-ink));
}

.tool .icon {
  width: 20px;
  height: 20px;
}

/* The theme switch shows where it goes: the sun (and "Light mode") in dark, the moon (and "Dark mode") in light. */
.theme-toggle .icon-moon,
.theme-toggle .for-light {
  display: none;
}

:root[data-theme="light"] .theme-toggle .icon-sun,
:root[data-theme="light"] .theme-toggle .for-dark {
  display: none;
}

:root[data-theme="light"] .theme-toggle .icon-moon {
  display: block;
}

:root[data-theme="light"] .theme-toggle .for-light {
  display: inline;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .theme-toggle .icon-sun,
  :root:not([data-theme]) .theme-toggle .for-dark {
    display: none;
  }

  :root:not([data-theme]) .theme-toggle .icon-moon {
    display: block;
  }

  :root:not([data-theme]) .theme-toggle .for-light {
    display: inline;
  }
}

/* The pause switch (here and in the footer): pause icon until pressed, then play, in teal. */
.motion-toggle .icon-play,
.motion-toggle[aria-pressed="true"] .icon-pause {
  display: none;
}

.motion-toggle[aria-pressed="true"] .icon-play {
  display: block;
}

.tool.motion-toggle[aria-pressed="true"] {
  color: rgb(var(--site-primary-strong));
}

.tool.motion-toggle[aria-pressed="true"]::before {
  background: rgb(var(--site-primary));
  opacity: 0.14;
}

.motion-toggle .icon {
  stroke-width: 2.2;
}

/* Two bars that cross into an X while the menu is open (transform only). */
.menu-icon {
  position: relative;
  display: block;
  width: 18px;
  height: 12px;
}

.menu-icon > span {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1.75px;
  margin-top: -0.875px;
  border-radius: 2px;
  background: currentColor;
  transform: translate3d(0, -3.5px, 0);
  transition: transform 0.35s var(--ease-out);
}

.menu-icon > span:last-child {
  transform: translate3d(0, 3.5px, 0);
}

[aria-expanded="true"] > .menu-icon > span:first-child {
  transform: rotate(45deg);
}

[aria-expanded="true"] > .menu-icon > span:last-child {
  transform: rotate(-45deg);
}

.nav-link {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  text-decoration: none;
  white-space: nowrap;
}

/* The section in view (main.js: aria-current). The indicator grows in; its colour carries the state too. */
.nav-link::after {
  content: "";
  flex: none;
  background: rgb(var(--site-primary-strong));
  transform: scale(0);
  transition: transform 0.35s var(--ease-out);
}

.nav-link[aria-current="true"] {
  color: rgb(var(--site-primary-strong));
}

.nav-link[aria-current="true"]::after {
  transform: none;
}

@media (hover: hover) {
  .pill-link:hover::before,
  .menu-button:hover::before,
  .tool:hover::before {
    opacity: 0.1;
  }

  .tool:hover {
    color: rgb(var(--site-ink));
  }

  .nav-link:hover::before {
    opacity: 0.07;
  }
}

/* Phones and tablets: logo, pill, and the menu button in the bar; the links and the switches in a panel beneath it.
   The button comes right before its panel in the markup (so Tab and VoiceOver go from the button into the menu) and
   sits last in the bar by flex order. */
@media (max-width: 899.98px) {
  .menu-button {
    order: 1;
  }

  /* A scrim over the page while the menu is open (no blur: the bar's is the page's only one). */
  .site-header::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background-color: rgb(var(--site-bg) / 0.55);
    opacity: 0;
    visibility: hidden;
    pointer-events: auto;
    transition:
      opacity 0.3s var(--ease-out),
      visibility 0s linear 0.3s;
  }

  .menu-open .site-header::before {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.3s var(--ease-out);
  }

  /* Closed, it is hidden from everyone (visibility), so its links never take keyboard focus. */
  .header-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    left: 0;
    display: grid;
    gap: 6px;
    max-height: calc(100vh - var(--header-space) - 24px);
    max-height: calc(100dvh - var(--header-space) - 24px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 8px;
    border-radius: 26px;
    background-color: rgb(var(--site-surface));
    box-shadow:
      inset 0 0 0 1px rgb(var(--site-ink) / 0.08),
      var(--site-shadow-panel);
    opacity: 0;
    visibility: hidden;
    transform: translate3d(0, -10px, 0) scale(0.98);
    transform-origin: 50% 0;
    transition:
      opacity 0.2s var(--ease-out),
      transform 0.3s var(--ease-out),
      visibility 0s linear 0.3s;
  }

  .menu-open .header-menu {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition:
      opacity 0.24s var(--ease-out),
      transform 0.5s var(--ease-expo);
  }

  .nav-list {
    display: grid;
  }

  .nav-link {
    justify-content: space-between;
    gap: 12px;
    min-height: 58px;
    padding: 0 18px;
    border-radius: 18px;
    color: rgb(var(--site-ink));
    font-family: var(--font-serif);
    font-size: 28px;
    line-height: 1.1;
    letter-spacing: -0.01em;
  }

  .nav-link:active::before {
    opacity: 0.07;
  }

  .nav-link::after {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    transition-timing-function: var(--spring);
  }

  /* Side by side where both labels fit on one line (from 375px: "Pause motion" needs 156px), stacked rows below. */
  .header-tools {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(156px, 1fr));
    gap: 8px;
    margin: 2px 6px 6px;
    padding-top: 14px;
    border-top: 1px solid var(--hairline);
  }

  .tool {
    width: auto;
    height: 52px;
    padding: 0 14px;
    border-radius: 16px;
    background-color: var(--tint);
    color: rgb(var(--site-ink));
    font-size: 15px;
    line-height: 20px;
    font-weight: 600;
    white-space: nowrap;
  }

  .tool:active::before {
    opacity: 0.08;
  }

  /* The rows follow the panel in, a beat apart. */
  .header-menu .nav-list > li,
  .header-menu .tool {
    opacity: 0;
    transform: translate3d(0, 8px, 0);
    transition:
      opacity 0.2s var(--ease-out),
      transform 0.2s var(--ease-out);
  }

  .menu-open .header-menu .nav-list > li,
  .menu-open .header-menu .tool {
    opacity: 1;
    transform: none;
    transition:
      opacity 0.4s var(--ease-out) var(--i, 0s),
      transform 0.6s var(--ease-expo) var(--i, 0s);
  }

  .nav-list > li:nth-child(2) {
    --i: 0.04s;
  }

  .nav-list > li:nth-child(3) {
    --i: 0.08s;
  }

  .nav-list > li:nth-child(4) {
    --i: 0.1s;
  }

  .header-tools .tool {
    --i: 0.12s;
  }

  .header-tools .tool + .tool {
    --i: 0.15s;
  }
}

/* The menu's own "Early access" row, for screens too narrow for the pill (below). */
.nav-item-ea {
  display: none;
}

/* Under 350px (the iPhone SE 1, and any phone with Display Zoom) the logo, the pill, and the menu button no longer fit
   with the logo's clear space, so the pill moves into the menu; the hero's own button is on screen at the top anyway. */
@media (max-width: 349.98px) {
  .site-header .pill-link {
    display: none;
  }

  .nav-item-ea {
    display: block;
  }
}

/* Tablets: a card under the menu button rather than a sheet across the bar. */
@media (min-width: 600px) and (max-width: 899.98px) {
  .header-menu {
    left: auto;
    width: min(100%, 400px);
    transform-origin: 100% 0;
  }
}

/* Wide screens: logo, the links centred, the two switches (icons; their names stay for screen readers), the pill. */
@media (min-width: 900px) {
  .header-bar {
    padding-right: 10px;
  }

  .site-header .brand {
    margin-right: 12px;
  }

  .site-header .brand .tk-logo {
    height: 40px;
  }

  .header-menu {
    display: flex;
    flex: 1;
    align-items: center;
    min-width: 0;
  }

  .site-nav {
    margin-inline: auto;
  }

  .nav-list {
    display: flex;
    align-items: center;
    gap: 2px;
  }

  .nav-link {
    justify-content: center;
    min-height: 44px;
    padding: 0 15px;
    border-radius: 999px;
    color: rgb(var(--site-ink-soft));
    font-size: 14.5px;
    line-height: 18px;
    font-weight: 600;
  }

  /* A short bar under the label. */
  .nav-link::after {
    position: absolute;
    bottom: 6px;
    left: 50%;
    width: 16px;
    height: 2px;
    margin-left: -8px;
    border-radius: 2px;
    transform: scaleX(0);
  }

  .nav-link[aria-current="true"]::after {
    transform: none;
  }

  .header-tools {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: 8px;
  }

  /* The switches show only their icons here; their names (still their accessible text) appear as a small tooltip on
     hover and keyboard focus. */
  .tool-label {
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    padding: 6px 10px;
    border-radius: 9px;
    background-color: rgb(var(--site-surface));
    box-shadow:
      inset 0 0 0 1px rgb(var(--site-ink) / 0.1),
      var(--site-shadow-card);
    color: rgb(var(--site-ink));
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transform: translate3d(-50%, -4px, 0);
    transition:
      opacity 0.18s var(--ease-out),
      transform 0.25s var(--ease-out);
  }

  .tool:focus-visible .tool-label {
    opacity: 1;
    transform: translate3d(-50%, 0, 0);
  }

  .pill-link {
    margin-left: 8px;
  }

  .menu-button {
    display: none;
  }
}

@media (min-width: 900px) and (hover: hover) {
  .tool:hover .tool-label {
    opacity: 1;
    transform: translate3d(-50%, 0, 0);
    transition-delay: 0.35s;
  }

  .nav-link:hover {
    color: rgb(var(--site-ink));
  }

  .nav-link[aria-current="true"]:hover {
    color: rgb(var(--site-primary-strong));
  }
}

/* Without script the switches can't work and the menu can't open; the pill and the page's own scroll remain. (The
   doubled class outranks the footer switch's own display, which comes later in this file.) */
@media (scripting: none) {
  .header-tools,
  .motion-toggle.motion-toggle,
  .menu-button {
    display: none;
  }
}

/* ---------- loader (GetLayers forma-loader, made honest: the mark draws itself on — no counter, no bar) ---------- */

.loader {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  place-content: center;
  background-color: rgb(var(--site-bg));
  background-image:
    radial-gradient(80% 55% at 12% 0%, rgb(var(--site-primary) / 0.16), transparent 70%),
    radial-gradient(70% 50% at 92% 4%, rgb(var(--site-accent) / 0.07), transparent 70%),
    radial-gradient(120% 60% at 50% 100%, rgb(var(--site-primary) / 0.08), transparent 70%);
}

/*
 * Shown from first paint wherever script runs; it takes itself down at 4.6 s should main.js never arrive. Once fading it
 * lets taps through (pointer-events animates discretely, flipping early in the fade), and at 5.2 s it is hidden on a
 * track of its own: the eased fade stops a hair short of its end value in some engines, so visibility, which only
 * changes at the very end, would never flip there and WebKit would keep hit-testing an invisible curtain.
 */
@media (scripting: enabled) {
  .loader {
    display: grid;
    animation:
      loader-failsafe 0.6s var(--ease-out) 4.6s forwards,
      loader-gone 1ms linear 5.2s forwards;
  }

  .intro:not(.is-open) {
    overflow: hidden;
  }
}

.loader-inner {
  display: grid;
  justify-items: center;
}

.loader .tk-logo {
  height: 88px;
}

/* The exit: the curtain fades as the mark lifts away, and the hero plays in through it (main.js flips .is-open). */
.is-open .loader {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.85s var(--ease-in-out);
}

.is-open .loader-inner {
  opacity: 0;
  transform: translate3d(0, -12px, 0) scale(1.04);
  transition:
    opacity 0.45s var(--ease-out),
    transform 0.85s var(--ease-out);
}

@keyframes loader-failsafe {
  to {
    opacity: 0;
    pointer-events: none;
  }
}

@keyframes loader-gone {
  to {
    visibility: hidden;
    pointer-events: none;
  }
}

/* ---------- sections ---------- */

/* Sections are spaced by their top margins, so an anchor jump puts a section's first line just under the header. */
.section-head {
  max-width: 800px;
}

/* Titles carry no margins of their own (their reveal pads them), so stacks space themselves with gap. */
.stack {
  display: grid;
  justify-items: start;
  gap: 18px;
}

/* ---------- hero (GetLayers artist-hero) ---------- */

.hero {
  position: relative;
  padding-top: calc(var(--header-space) + 34px);
}

.hero-grid {
  display: grid;
  gap: 26px;
}

/* A size container, so the display type is sized to the copy column itself (100vw would count a scrollbar). */
.hero-copy {
  position: relative;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/*
 * A soft scrim of the page ground behind the copy, so every line reads at AA over any part of the tide: --site-scrim at
 * the centre, --site-scrim-mid two-thirds out, per theme. A flat colour shaped by a mask, so it crossfades on a switch.
 */
.hero-copy::before {
  content: "";
  position: absolute;
  inset: -16% -40% -10% -30%;
  z-index: -1;
  background-color: rgb(var(--site-bg) / var(--site-scrim));
  -webkit-mask-image: radial-gradient(closest-side, #000, rgb(0 0 0 / calc(var(--site-scrim-mid) / var(--site-scrim))) 58%, transparent);
  mask-image: radial-gradient(closest-side, #000, rgb(0 0 0 / calc(var(--site-scrim-mid) / var(--site-scrim))) 58%, transparent);
  pointer-events: none;
}

.hero-title {
  margin-top: 20px;
  /* Phones and tablets: two lines, "The business behind" (6.55em at this tracking) filling the measure. */
  font-size: min(calc((100vw - 2 * var(--gutter)) / 6.8), 104px);
  font-size: min(calc(100cqi / 6.8), 104px);
}

.hero-line {
  display: inline-block;
}

.hero-line-3 {
  display: block;
}

.hero-lead {
  max-width: 34ch;
  margin-top: 18px;
}

.hero-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  width: 100%;
  margin-top: 28px;
}

/* On phones the secondary action is a quiet link under the full-width primary. */
.hero-actions .btn-ghost {
  min-height: 48px;
  background: none;
  box-shadow: none;
  color: rgb(var(--site-ink-soft));
  font-size: 15px;
}

.hero-actions .btn-ghost::before {
  display: none;
}

.ledger {
  display: none;
}

.hero-media {
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  gap: 18px;
  margin-top: 6px;
}

/* A small chip with its own scrim, so the caption keeps AA wherever the tide runs under it. */
.media-caption {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px 7px 12px;
  border-radius: 999px;
  background-color: rgb(var(--site-bg) / 0.62);
  box-shadow: inset 0 0 0 1px var(--hairline);
  color: rgb(var(--site-ink-muted));
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgb(var(--site-accent));
  box-shadow: 0 0 0 3px rgb(var(--site-accent) / 0.22);
}

/* The live phone (partials/phone.html) fills this box's width; phones lean it a little and let the fold crop it. */
.hero-device {
  width: min(80vw, 340px);
  --tk-phone-width: 100%;
}

.hero-tilt {
  transform: rotate(-4deg);
  transform-origin: 50% 30%;
}

@media (min-width: 600px) {
  .hero-actions {
    flex-direction: row;
    align-items: center;
    width: auto;
    gap: 12px;
    margin-top: 34px;
  }

  .hero-actions .btn-ghost {
    min-height: 54px;
    background: rgb(var(--site-bg) / 0.35);
    box-shadow: inset 0 0 0 1px rgb(var(--site-ink) / 0.26);
    color: rgb(var(--site-ink));
    font-size: 16px;
  }

  .hero-actions .btn-ghost::before {
    display: block;
  }

  /* The fact ledger: label/value pairs under a hairline, not numbers. */
  .ledger {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0 24px;
    width: 100%;
    max-width: 580px;
    margin-top: 44px;
    padding-top: 20px;
    border-top: 1px solid var(--hairline);
  }

  .ledger dt {
    color: rgb(var(--site-ink-muted));
    font-size: 11px;
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .ledger dd {
    margin-top: 7px;
    color: rgb(var(--site-ink-soft));
    font-size: 15px;
    line-height: 1.35;
    text-wrap: balance;
  }

  .hero-device {
    width: min(60vw, 360px);
  }

  .hero-tilt {
    transform: rotate(-3deg);
  }
}

@media (min-width: 960px) {
  .hero {
    display: grid;
    align-items: center;
    min-height: 100svh;
    padding-block: calc(var(--header-space) + 32px) 56px;
  }

  .hero-grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    align-items: center;
    column-gap: clamp(32px, 5vw, 88px);
  }

  /* Three short lines, the composition's ~14-character measure ("The business" is 4.1em), and short enough for the
     copy column to fit a laptop's first screen (14.5svh: 95px at 1366 × 657, the full 116px from 800px tall). */
  .hero-title {
    margin-top: 24px;
    font-size: clamp(64px, min(calc((100vw - 2 * var(--gutter)) * 0.085), 14.5vh), 116px);
    font-size: clamp(64px, min(18.5cqi, 14.5svh), 116px);
  }

  .hero-line {
    display: block;
  }

  .hero-lead {
    margin-top: 24px;
  }

  .hero-actions {
    margin-top: 38px;
  }

  .hero-media {
    flex-direction: column;
    gap: 22px;
    margin: 0;
  }

  /* Tall enough to be the plate, short enough to sit inside the first screen; phone.js tilts it toward the pointer. */
  .hero-device {
    width: min(360px, 27vw, calc((100svh - 210px) * 433 / 905));
  }

  .hero-tilt {
    transform: none;
  }
}

/* Laptop screens (a 13-inch MacBook's browser is ~790px tall, a common Windows laptop's ~660px): tighter spacing keeps
   the buttons and the ledger above the fold; under 700px the ledger, whose facts the page repeats below, steps aside. */
@media (min-width: 960px) and (max-height: 860px) {
  .hero {
    padding-block: calc(var(--header-space) + 20px) 32px;
  }

  .hero-title {
    margin-top: 18px;
  }

  .hero-lead {
    margin-top: 18px;
  }

  .hero-actions {
    margin-top: 28px;
  }

  .ledger {
    margin-top: 28px;
    padding-top: 16px;
  }
}

@media (min-width: 960px) and (max-height: 699.98px) {
  .hero-ledger {
    display: none;
  }
}

/* ---------- story (GetLayers artist-process, mirrored) ---------- */

.story {
  margin-top: 112px;
}

.story-body {
  /* Phones: as tall as the screen allows once the tallest step card fits beneath it, 12px clear above and below, so the
     phone and a held card never overlap (main.js measures --card-h; the fallback is about the tallest at 375px wide).
     That holds down to screens ~500px tall, such as a small iPhone with Safari's bars showing; below a 200px stage the
     phone would be a stamp, so a card rides up under its lower edge instead. Up to 760px on tablets, where the phone
     stays in proportion with the card beneath it. svh, not dvh: the phone keeps its size as the browser's bars come
     and go. */
  --stage-h: clamp(200px, calc(100svh - var(--stage-top) - var(--card-h, 250px) - 24px), 760px);
  --stage-top: calc(var(--header-space) + 10px);
  position: relative;
  display: flex;
  flex-direction: column;
  margin-top: 36px;
  padding-bottom: var(--tail, 0px);
}

/* Phones: the phone pins under the header, as large as the room over the tallest card allows, and the steps scroll
   beneath it. */
.story-stage {
  --device-h: calc(var(--stage-h) - 15px);
  position: sticky;
  top: var(--stage-top);
  z-index: 2;
  order: -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  height: var(--stage-h);
}

.story-progress {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 5px;
  width: calc(var(--device-h) * 433 / 905);
  flex: none;
}

.seg {
  display: grid;
  gap: 10px;
}

.seg-track {
  position: relative;
  height: 3px;
  overflow: hidden;
  border-radius: 3px;
  background-color: rgb(var(--site-ink) / 0.16);
}

.seg-fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-color: rgb(var(--site-primary-strong));
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.seg-label,
.stage-caption {
  display: none;
}

/* The story's live phone (partials/story-phone.html, styled by story.css) fills this box: the device's 433:905. */
.story-device {
  flex: none;
  width: calc(var(--device-h) * 433 / 905);
  height: var(--device-h);
  --tk-phone-width: 100%;
}

.story-steps {
  position: relative;
  z-index: 1;
  /* --tail (main.js, phones): the phone lets go as the last card does, instead of lingering alone. The steps run that
     far past the end of the phone's sticky range, and the same space comes back as padding, so nothing below moves. */
  margin-bottom: calc(-1 * var(--tail, 0px));
}

/* Each step's card holds just under the pinned phone while its step scrolls by, then the next one pushes it out. The
   cards never dim: the pinned screen, the progress bar, and the card's place already say which step is live, and faded
   text would drop below AA. */
.story-step {
  min-height: 62svh;
  padding-top: 20px;
}

.step-index {
  display: none;
}

/* Phones: each step is a glass card in the theme's surface (no backdrop blur: the tide moves under it every frame). */
/* main.js sets --stick so a tall card on a short screen still fits; the fallback is just under the phone. */
.step-card {
  position: sticky;
  top: var(--stick, calc(var(--stage-top) + var(--stage-h) + 12px));
  padding: 18px 18px 20px;
  border-radius: 22px;
  background-color: rgb(var(--site-surface) / 0.9);
  box-shadow:
    inset 0 0 0 1px rgb(var(--site-ink) / 0.08),
    var(--site-shadow-card);
}

.step-label {
  color: rgb(var(--site-primary-strong));
  font-size: 11px;
  line-height: 14px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.step-title {
  margin-top: 8px;
  font-family: var(--font-serif);
  font-size: 25px;
  line-height: 1.08;
  font-weight: 400;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.step-body {
  margin-top: 10px;
  color: rgb(var(--site-ink-soft));
  font-size: 16px;
  line-height: 1.55;
  text-wrap: pretty;
}

/* Tablets: the card is centred under the phone at a readable measure, not stretched across the column. */
@media (min-width: 600px) and (max-width: 959.98px) {
  .step-card {
    max-width: 34rem;
    margin-inline: auto;
  }
}

/* Phones, and short screens under 960px wide (a phone on its side, a small tablet window): the card sets a little
   tighter and the progress bar gives its row to the phone (the live tab bar already says which step is on), so the
   phone takes the room they free. Safari's bars leave a 6.3" iPhone 714px of its 874. */
@media (max-width: 599.98px), (max-width: 959.98px) and (max-height: 800px) {
  .story-stage {
    --device-h: var(--stage-h);
  }

  .story-progress {
    display: none;
  }

  .step-card {
    padding: 14px 16px 16px;
  }

  .step-title {
    margin-top: 6px;
    font-size: 22px;
  }

  .step-body {
    margin-top: 8px;
    font-size: 15px;
    line-height: 1.45;
  }
}

/* Without script nothing moves the story (main.js follows the steps with the phone, fills the bar, and fades each card
   as the next one pushes it under the phone), so it reads as a plain sequence: the phone shows its first screen, still,
   the bar goes, and on phones the phone and the cards simply flow instead of pinning. */
@media (scripting: none) {
  .story-progress {
    display: none;
  }
}

@media (scripting: none) and (max-width: 959.98px) {
  .story-stage {
    position: relative;
    top: auto;
  }

  .story-step {
    min-height: 0;
  }

  .step-card {
    position: static;
  }
}

/* Wide screens only: on phones the live phone above the card already shows the stages and the payers. */
.trail {
  display: none;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
}

@media (min-width: 600px) {
  .trail {
    display: flex;
  }
}

.trail li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background-color: var(--tint);
  box-shadow: inset 0 0 0 1px rgb(var(--site-ink) / 0.1);
  color: rgb(var(--site-ink-soft));
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
}

/* Ordered stages read left to right with a chevron between them. */
ol.trail li:not(:last-child)::after {
  content: "";
  width: 5px;
  height: 5px;
  margin: 0 -2px 0 4px;
  border-top: 1.5px solid rgb(var(--site-ink) / 0.5);
  border-right: 1.5px solid rgb(var(--site-ink) / 0.5);
  transform: rotate(45deg);
}

@media (min-width: 960px) {
  .story {
    margin-top: 168px;
  }

  .story-body {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: start;
    column-gap: clamp(40px, 6vw, 112px);
    margin-top: 32px;
  }

  .story-steps {
    grid-row: 1;
    grid-column: 1;
  }

  /* Wide screens: the phone pins on the right, centred in the space under the header. */
  .story-body {
    --stage-h: min(80svh, 800px);
    --stage-top: calc(var(--header-space) + (100svh - var(--header-space) - var(--stage-h)) / 2);
  }

  .story-stage {
    --device-h: calc(var(--stage-h) - 92px);
    grid-row: 1;
    grid-column: 2;
    order: 0;
    gap: 22px;
  }

  .story-progress {
    order: 2;
    width: min(100%, 340px);
    gap: 8px;
  }

  .seg-label {
    display: block;
    color: rgb(var(--site-ink-muted));
    font-size: 11px;
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  /* The step in focus (main.js: .seg.is-active). */
  .seg.is-active .seg-label {
    color: rgb(var(--site-ink));
  }

  /* The hero's caption chip (.media-caption), under the progress bar. */
  .stage-caption {
    order: 3;
    display: inline-flex;
    margin-top: -6px;
  }

  /* Ruled rows: a hairline on top, the oversized faint numeral, the title hung beside it. */
  .story-step {
    display: grid;
    grid-template-columns: 7.5rem minmax(0, 1fr);
    align-content: center;
    min-height: 72svh;
    padding: 56px 0;
    border-top: 1px solid var(--hairline);
  }

  /* The last step runs long enough for the phone to stay pinned while it is centred: its box must reach the stage's
     bottom when its middle is mid-screen, so its height is at least 2 × (stage top + stage height) − the viewport. */
  .story-step:last-child {
    min-height: max(72svh, calc(2 * (var(--stage-top) + var(--stage-h)) - 100svh));
    border-bottom: 1px solid var(--hairline);
  }

  /* The steps out of focus recede in colour, not opacity: muted ink still reads at AA in both themes (5.8:1 and more),
     where a fade would not. */
  .story-live .story-step:not(.is-active) :is(.step-label, .step-title, .step-body, .trail li) {
    color: rgb(var(--site-ink-muted));
  }

  .step-index {
    display: block;
    color: rgb(var(--site-ink) / 0.14);
    font-family: var(--font-serif);
    font-size: 104px;
    line-height: 0.8;
    letter-spacing: -0.04em;
  }

  .step-card {
    position: static;
    padding: 14px 0 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
  }

  .step-title {
    margin-top: 14px;
    font-size: clamp(34px, 1.4vw + 18px, 46px);
  }

  .step-body {
    max-width: 46ch;
    margin-top: 16px;
    font-size: 17px;
    line-height: 1.6;
  }

  .trail {
    margin-top: 20px;
  }

  .trail li {
    padding: 5px 12px;
    font-size: 13px;
  }
}

/*
 * Phones on their side (and other short, wide windows under 960px): stacked, the phone would shrink to a stamp above
 * the card, so it pins beside the steps instead, as on wide screens, at the height of the screen under the header.
 * main.js sees the stage beside the steps and runs the story as it does there.
 */
@media (orientation: landscape) and (max-height: 520px) and (min-width: 560px) and (max-width: 959.98px) {
  .story-body {
    --stage-h: calc(100svh - var(--header-space) - 20px);
    --stage-top: calc(var(--header-space) + 10px);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    column-gap: clamp(24px, 5vw, 48px);
    margin-top: 28px;
  }

  .story-steps {
    grid-row: 1;
    grid-column: 1;
  }

  .story-stage {
    grid-row: 1;
    grid-column: 2;
    order: 0;
  }

  .story-step {
    display: grid;
    align-content: center;
    min-height: calc(100svh - var(--header-space));
    padding: 16px 0;
  }

  .step-card {
    position: static;
    max-width: none;
    margin-inline: 0;
  }
}

/* ---------- built for (GetLayers marcus-vane-story), closed by the features ledger (artist-about) ---------- */

.built {
  margin-top: 136px;
}

.built-grid {
  display: grid;
  gap: 40px;
}

@media (min-width: 960px) {
  .built-list {
    border-bottom: 1px solid var(--hairline);
  }
}

.built-row {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr);
  padding: 26px 0 28px;
  border-top: 1px solid var(--hairline);
}

/* Numerals at title size in the brand teal: decorative (aria-hidden), and still 3:1 or more on the light ground. */
.row-index {
  color: rgb(var(--site-primary));
  font-family: var(--font-serif);
  font-size: 24px;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
}

.row-title {
  font-family: var(--font-serif);
  font-size: 30px;
  line-height: 1.1;
  font-weight: 400;
  letter-spacing: -0.01em;
}

.row-body {
  max-width: 46ch;
  margin-top: 10px;
  color: rgb(var(--site-ink-soft));
  font-size: 16px;
  line-height: 1.6;
  text-wrap: pretty;
}

/* "Also in Tokos" — the nav's Features. */
.features {
  margin-top: 64px;
}

.caps {
  display: grid;
  margin-top: 20px;
  border-top: 1px solid var(--hairline);
}

.cap {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: start;
  column-gap: 16px;
  padding: 22px 0;
  border-bottom: 1px solid var(--hairline);
}

.cap-icon {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 13px;
  background-color: rgb(var(--site-primary) / 0.12);
  box-shadow: inset 0 0 0 1px rgb(var(--site-primary) / 0.16);
  color: rgb(var(--site-primary-strong));
}

.cap-title {
  font-size: 16px;
  line-height: 22px;
  font-weight: 700;
}

.cap-body {
  max-width: 46ch;
  margin-top: 4px;
  color: rgb(var(--site-ink-soft));
  font-size: 16px;
  line-height: 1.55;
  text-wrap: pretty;
}

@media (min-width: 960px) {
  .built {
    margin-top: 200px;
  }

  .built-grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    align-items: start;
    column-gap: clamp(48px, 8vw, 140px);
  }

  .built-row {
    grid-template-columns: 4.5rem minmax(0, 1fr);
    padding: 36px 0 40px;
  }

  .row-index {
    font-size: 30px;
  }

  .row-title {
    font-size: 40px;
  }

  .row-body {
    margin-top: 14px;
    font-size: 17px;
  }

  .features {
    margin-top: 112px;
  }

  .caps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin-top: 24px;
  }

  .cap {
    grid-template-columns: minmax(0, 1fr);
    padding: 32px 32px 8px 0;
    border-bottom: 0;
  }

  .cap + .cap {
    padding-left: 32px;
    border-left: 1px solid var(--hairline);
  }

  .cap-icon {
    grid-row: auto;
    margin-bottom: 18px;
  }
}

/* ---------- early access (GetLayers artist-cta: the plate is the form) ---------- */

.join {
  margin-top: 136px;
}

.join-grid {
  display: grid;
  gap: 32px;
}

/* A raised panel in the theme's surface (no backdrop blur: the tide moves under it every frame). */
.join-panel {
  position: relative;
  isolation: isolate;
  padding: 26px 20px 22px;
  border-radius: 28px;
  background-color: rgb(var(--site-surface));
  box-shadow:
    inset 0 1px 0 rgb(var(--site-ink) / 0.06),
    0 0 0 1px rgb(var(--site-ink) / 0.08),
    var(--site-shadow-panel);
}

/* A sheen down from the top edge (dark), and a faint teal dawn across it. */
.join-panel::before,
.join-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}

.join-panel::before {
  background-color: rgb(var(--panel-top));
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 55%);
  mask-image: linear-gradient(180deg, #000, transparent 55%);
}

.join-panel::after {
  background-color: rgb(var(--site-primary) / 0.1);
  -webkit-mask-image: radial-gradient(70% 45% at 50% 0%, #000, transparent 70%);
  mask-image: radial-gradient(70% 45% at 50% 0%, #000, transparent 70%);
}

@media (max-width: 599.98px) {
  .join-panel {
    margin-inline: calc(8px - var(--gutter));
  }
}

@media (min-width: 600px) {
  .join-panel {
    max-width: 520px;
    padding: 36px 36px 30px;
  }
}

@media (min-width: 960px) {
  .join {
    margin-top: 168px;
  }

  .join-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 480px);
    align-items: center;
    column-gap: clamp(48px, 9vw, 160px);
  }
}

.signup-form {
  display: grid;
  gap: 18px;
}

.field {
  display: grid;
  gap: 8px;
}

.field label {
  color: rgb(var(--site-ink));
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
}

/*
 * The outline needs 3:1 against the panel (WCAG 1.4.11): --site-field is 3.4:1 on the light surface, 4.0:1 on the dark.
 * 17px text keeps iOS Safari from zooming into the field on focus.
 */
.field input {
  width: 100%;
  height: 54px;
  padding: 0 16px;
  border: 1px solid rgb(var(--site-field));
  border-radius: 14px;
  background-color: rgb(var(--site-bg) / 0.6);
  color: rgb(var(--site-ink));
  caret-color: rgb(var(--site-primary-strong));
  font-size: 17px;
  line-height: 24px;
  -webkit-appearance: none;
  appearance: none;
}

.field input:hover {
  border-color: rgb(var(--site-ink-muted));
}

.field input:focus-visible {
  border-color: rgb(var(--site-primary-strong));
  outline: 2px solid rgb(var(--site-primary-strong));
  outline-offset: 2px;
}

.field input[aria-invalid="true"] {
  border-color: rgb(var(--site-danger));
}

.field input[aria-invalid="true"]:focus-visible {
  outline-color: rgb(var(--site-danger));
}

.field input:-webkit-autofill {
  -webkit-text-fill-color: rgb(var(--site-ink));
  box-shadow: inset 0 0 0 100px rgb(var(--site-surface-2));
  caret-color: rgb(var(--site-ink));
}

.field-error {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  color: rgb(var(--site-danger));
  font-size: 14px;
  line-height: 20px;
  font-weight: 700;
}

.field-error .icon {
  width: 16px;
  height: 16px;
  margin-top: 2px;
  stroke-width: 2;
}

/* The honeypot: off-screen for people, still in the form for bots. */
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Without JavaScript the form can't send (each request carries a hash of its body), so show only the <noscript> note. */
@media (scripting: none) {
  .signup-form > :not(noscript) {
    display: none;
  }
}

.signup-submit {
  width: 100%;
  margin-top: 6px;
}

.form-note {
  color: rgb(var(--site-ink-muted));
  font-size: 13px;
  line-height: 18px;
  text-align: center;
  text-wrap: balance;
}

.form-status {
  font-size: 14px;
  line-height: 20px;
  font-weight: 700;
  text-align: center;
}

.form-status:not(:empty) {
  margin-top: 16px;
}

.form-status[data-tone="error"] {
  color: rgb(var(--site-danger));
}

.signup-success {
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: 24px 4px 18px;
  text-align: center;
}

.success-mark {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background-color: rgb(var(--site-primary) / 0.14);
  box-shadow: inset 0 0 0 1px rgb(var(--site-primary) / 0.35);
  color: rgb(var(--site-primary-strong));
}

.success-mark .icon {
  width: 26px;
  height: 26px;
  stroke-width: 2.4;
}

.success-title {
  margin-top: 8px;
  font-family: var(--font-serif);
  font-size: 36px;
  line-height: 42px;
  font-weight: 400;
}

.success-body {
  max-width: 34ch;
  color: rgb(var(--site-ink-soft));
  font-size: 16px;
  line-height: 24px;
  text-wrap: balance;
}

.success-body strong {
  color: rgb(var(--site-ink));
  overflow-wrap: anywhere;
}

/* ---------- footer (GetLayers artist-footer) ---------- */

.site-footer {
  margin-top: 128px;
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
}

.footer-top {
  display: grid;
  gap: 32px;
  padding-top: 48px;
  border-top: 1px solid var(--hairline);
}

.footer-brand {
  display: grid;
  justify-items: start;
  gap: 14px;
}

.footer-logo .tk-logo {
  height: 44px;
}

.footer-tagline {
  color: rgb(var(--site-ink-soft));
  font-family: var(--font-serif);
  font-size: 24px;
  line-height: 1.2;
  font-style: italic;
}

.footer-heading {
  font-size: 14px;
  line-height: 20px;
  font-weight: 700;
}

.footer-text {
  max-width: 62ch;
  margin-top: 8px;
  color: rgb(var(--site-ink-soft));
  font-size: 14px;
  line-height: 1.65;
}

/* The brand word at the width of the page, nearly invisible: a texture, not a heading (aria-hidden). */
.footer-wordmark {
  --logo-word: rgb(var(--site-ink) / 0.065);
  margin-top: 56px;
  user-select: none;
  -webkit-user-select: none;
}

.footer-wordmark .tk-logo {
  width: 100%;
  height: auto;
}

.footer-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
}

.footer-legal {
  color: rgb(var(--site-ink-muted));
  font-size: 13px;
  line-height: 18px;
}

.motion-toggle-text {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 18px 0 14px;
  border: 0;
  border-radius: 999px;
  background-color: var(--tint);
  box-shadow: inset 0 0 0 1px rgb(var(--site-ink) / 0.16);
  color: rgb(var(--site-ink-soft));
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  cursor: pointer;
}

.motion-toggle-text[aria-pressed="true"] {
  background-color: rgb(var(--site-primary) / 0.14);
  box-shadow: inset 0 0 0 1px rgb(var(--site-primary) / 0.42);
  color: rgb(var(--site-primary-strong));
}

@media (hover: hover) {
  .motion-toggle-text:hover::before {
    opacity: 0.08;
  }
}

@media (min-width: 960px) {
  .site-footer {
    margin-top: 168px;
  }

  .footer-top {
    grid-template-columns: minmax(0, 1fr) minmax(0, 540px);
    column-gap: 64px;
    padding-top: 64px;
  }

  .footer-logo .tk-logo {
    height: 52px;
  }

  .footer-tagline {
    font-size: 28px;
  }
}

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

.not-found {
  display: grid;
  align-items: center;
  min-height: 88svh;
  padding-block: calc(var(--header-space) + 40px) 24px;
}

.not-found-inner {
  position: relative;
  display: grid;
  justify-items: start;
  gap: 22px;
}

.not-found-inner::before {
  content: "";
  position: absolute;
  inset: -20% -30%;
  z-index: -1;
  background-color: rgb(var(--site-bg) / var(--site-scrim));
  -webkit-mask-image: radial-gradient(closest-side, #000, transparent);
  mask-image: radial-gradient(closest-side, #000, transparent);
  pointer-events: none;
}

.not-found-title {
  font-size: clamp(56px, 7vw + 24px, 128px);
}

.not-found-inner .btn {
  margin-top: 10px;
}

/* ---------- motion ---------- */

/*
 * The loader: the mark's ring draws itself on from its open end (pathLength 1: a dash as long as the ring, offset just
 * past it, so not even a round cap shows before it starts), then the coral dot drops into its cradle and settles.
 * Under the 900 ms the loader stays up at least. Reduced motion: the whole mark fades in.
 */
@media (prefers-reduced-motion: no-preference) {
  .loader .tk-logo__ring {
    stroke-dasharray: 1 2;
    stroke-dashoffset: 1.01;
    animation:
      ring-draw 0.74s var(--ease-in-out) 0.08s forwards,
      pen-down 1ms linear 0.08s backwards;
  }

  .loader .tk-logo__dot {
    transform-box: fill-box;
    transform-origin: 50% 100%;
    animation: dot-settle 0.6s var(--spring) 0.62s both;
  }

  html {
    scroll-behavior: smooth;
  }

  .btn:active,
  .pill-link:active,
  .tool:active,
  .menu-button:active,
  .motion-toggle-text:active {
    transform: scale(0.97);
  }

  .live-dot {
    animation: breathe 2.6s var(--ease-in-out) infinite;
  }

  .signup-success {
    animation: rise-in 0.6s var(--ease-out) both;
  }

  .success-mark {
    animation: pop 0.5s var(--spring) 0.1s both;
  }
}

@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .btn:hover .icon {
    transform: translateX(3px);
  }

  .btn:hover .icon-down {
    transform: translateY(3px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .loader-inner {
    animation: fade-in 0.5s ease both;
  }

  /* The menu appears and leaves in place. */
  .site-header::before,
  .menu-open .site-header::before,
  .header-menu,
  .menu-open .header-menu,
  .header-menu .nav-list > li,
  .menu-open .header-menu .nav-list > li,
  .header-menu .tool,
  .menu-open .header-menu .tool,
  .menu-icon > span,
  .nav-link::after {
    transition: none;
  }

  .header-menu,
  .header-menu .nav-list > li,
  .header-menu .tool {
    transform: none;
  }

  .header-menu .nav-list > li,
  .header-menu .tool {
    opacity: 1;
  }
}

/* The switches' tooltips fade in place. */
@media (prefers-reduced-motion: reduce) and (min-width: 900px) {
  .tool .tool-label {
    transform: translate3d(-50%, 0, 0);
  }
}

@keyframes ring-draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes pen-down {
  from {
    opacity: 0;
  }
}

@keyframes dot-settle {
  from {
    opacity: 0;
    transform: translate3d(0, -70%, 0) scale(0.55);
  }

  45% {
    opacity: 1;
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes pop {
  from {
    transform: scale(0);
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

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

@keyframes breathe {
  50% {
    opacity: 0.35;
  }
}

/*
 * The hero intro. html.intro (main.js, only while the loader is up) holds each piece at its from-state under the curtain;
 * html.is-open, flipped as the curtain starts to leave, plays them in: each display line out of a blur as it rises
 * (110–120 ms apart, opacity landing early in the curve), then the lead, the actions, the ledger, and the phone.
 * The lines are never clipped, so the blur has room.
 */
.site-header {
  --d: 0.05s;
}

.hero-eyebrow {
  --d: 0.04s;
}

.hero-line-1 {
  --d: 0.1s;
}

.hero-line-2 {
  --d: 0.22s;
}

.hero-line-3 {
  --d: 0.34s;
}

.hero-device {
  --d: 0.18s;
}

.hero-lead {
  --d: 0.5s;
}

.hero-actions {
  --d: 0.6s;
}

.hero-ledger {
  --d: 0.72s;
}

.media-caption {
  --d: 0.95s;
}

@media (prefers-reduced-motion: no-preference) {
  .intro [data-intro] {
    opacity: 0;
    transform: translate3d(0, 16px, 0);
  }

  .intro [data-intro-line] {
    opacity: 0;
    transform: translate3d(0, 0.32em, 0);
    filter: blur(14px);
  }

  .intro .hero-device {
    opacity: 0;
    transform: translate3d(0, 64px, 0);
  }

  .intro .site-header {
    opacity: 0;
    transform: translate3d(0, -12px, 0);
  }

  .intro:not(.is-settled) :is([data-intro], [data-intro-line], .hero-device) {
    will-change: transform, opacity;
  }

  .intro.is-open :is([data-intro], [data-intro-line], .hero-device),
  .intro.is-open .site-header {
    opacity: 1;
    transform: none;
    filter: none;
    transition:
      opacity 0.6s var(--ease-out) var(--d, 0s),
      transform 1.2s var(--ease-expo) var(--d, 0s),
      filter 0.9s var(--ease-out) var(--d, 0s);
  }
}

@media (prefers-reduced-motion: reduce) {
  .intro :is([data-intro], [data-intro-line], .hero-device),
  .intro .site-header {
    opacity: 0;
  }

  .intro.is-open :is([data-intro], [data-intro-line], .hero-device),
  .intro.is-open .site-header {
    opacity: 1;
    transition: opacity 0.6s ease var(--d, 0s);
  }

  .is-open .loader-inner {
    transform: none;
  }
}

/*
 * Below the fold, plain viewport-entry reveals, once (main.js adds .reveal-ready, then .is-in at ~45% visible). Titles
 * come out of a blur behind a soft mask sweeping left to right; they are padded so the mask never cuts the blur's edge.
 * Screens only: printing lays the page out again without scrolling, and nothing must stay hidden there.
 */
.section-head [data-reveal]:nth-child(2),
.built-intro [data-reveal]:nth-child(2),
.join-copy [data-reveal]:nth-child(2),
.built-row:nth-child(2),
.cap:nth-child(2) {
  --rd: 0.08s;
}

.cap:nth-child(3) {
  --rd: 0.16s;
}

/* A section's lead follows its title in, so the order reads eyebrow, title, lead. */
.section-head [data-reveal]:nth-child(3),
.built-intro [data-reveal]:nth-child(3),
.join-copy [data-reveal]:nth-child(3) {
  --rd: 0.22s;
}

@media screen and (prefers-reduced-motion: no-preference) {
  .reveal-ready [data-reveal] {
    transition:
      opacity 0.8s var(--ease-out) var(--rd, 0s),
      transform 1.1s var(--ease-expo) var(--rd, 0s);
  }

  .reveal-ready [data-reveal]:not(.is-in) {
    opacity: 0;
    transform: translate3d(0, 28px, 0);
  }

  .reveal-ready [data-reveal="title"] {
    margin: calc(-1 * max(0.4em, 26px));
    padding: max(0.4em, 26px);
    -webkit-mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
    mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
    -webkit-mask-size: 250% 100%;
    mask-size: 250% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: 0 0;
    mask-position: 0 0;
    /* The sweep starts briskly (ease-out), so a title is under way before the lead beneath it arrives. */
    transition:
      opacity 0.7s var(--ease-out) var(--rd, 0s),
      filter 1s var(--ease-out) var(--rd, 0s),
      -webkit-mask-position 1.1s var(--ease-out) var(--rd, 0s),
      mask-position 1.1s var(--ease-out) var(--rd, 0s);
  }

  .reveal-ready [data-reveal="title"]:not(.is-in) {
    opacity: 0;
    transform: none;
    filter: blur(12px);
    -webkit-mask-position: 100% 0;
    mask-position: 100% 0;
  }

  .reveal-ready [data-reveal="title"].is-done {
    -webkit-mask-image: none;
    mask-image: none;
    filter: none;
  }
}

@media screen and (prefers-reduced-motion: reduce) {
  .reveal-ready [data-reveal] {
    transition: opacity 0.6s ease var(--rd, 0s);
  }

  .reveal-ready [data-reveal]:not(.is-in) {
    opacity: 0;
  }
}

/*
 * A theme switch. main.js swaps html[data-theme] inside a View Transition (html.theme-switching marks it), so the
 * browser crossfades two finished frames, old over new, in 250 ms: opacity only, every element and the tide in step,
 * in every engine. (Per-element colour transitions couldn't: text that inherits its colour restarts the fade at each
 * level of nesting in WebKit, so headlines lagged a quarter second behind their ground and all but vanished.) The
 * curve is steep in the middle, so the moment where both frames show is brief. Where View Transitions aren't
 * available, with reduced motion, or with motion paused, the swap is instant.
 */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 250ms;
    animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
  }
}

/* The pause switch stills the page's own loop (the tide and the phone stop themselves on tokos:motion). One-shot
   entrances are left alone: pausing them would freeze them at their first frame, invisible. */
.motion-paused .live-dot {
  animation: none;
}

/* Off screen (main.js: .is-idle) a live dot holds still: an animation nobody sees still restyles the page every frame. */
.live-dot.is-idle {
  animation-play-state: paused;
}

.motion-paused {
  scroll-behavior: auto;
}

/* ---------- forced colours (Windows contrast themes) ---------- */

/* Backgrounds drop out there, so controls get an outline and the logo the system's text colour. */
@media (forced-colors: active) {
  .btn,
  .pill-link,
  .tool,
  .menu-button,
  .motion-toggle-text {
    border: 1px solid;
  }

  .tk-logo__ring,
  .tk-logo__ring * {
    stroke: CanvasText;
  }

  .tk-logo__dot,
  .tk-logo__dot *,
  .tk-logo__word,
  .tk-logo__word *,
  .tk-logo__sub,
  .tk-logo__sub * {
    fill: CanvasText;
  }

  .header-menu {
    border: 1px solid;
  }
}

/* ---------- print ---------- */

@media print {
  #tide,
  body::before,
  .tide-veil,
  .loader,
  .site-header,
  .story-stage,
  .footer-wordmark,
  .motion-toggle {
    display: none !important;
  }

  .story-step,
  .step-card,
  [data-handoff-inner] {
    opacity: 1 !important;
    transform: none !important;
  }

  .story-step {
    min-height: 0;
  }
}
