/* dotpano.com
   ==========================================================================
   One stylesheet, no framework. Every value here comes from a token declared
   once at the top; nothing below invents a colour or a duration.

   The site runs two visual modes on one page: a dark ground that is the
   default, and bright sections used as deliberate reversals. Both are the same
   token set with the roles swapped inside `.bright`, rather than a second
   palette, so a component dropped into either one is already correct.

   There is no appearance toggle. This is a marketing site with an argument to
   make, and the mode is part of the argument.
   ========================================================================== */

/* ------------------------------------------------------------- tokens --- */

:root {
  /* The palette, exactly as the kit states it. The app, the back office and the
     studio pages ship these same values, so the site cannot drift from the
     product. Nothing below invents a colour: every other value on this page is
     one of these, or one of these mixed with another. */
  --lime: #d4ff3b;      /* Pano Lime — the accent, and one surface per view */
  --ink: #14180c;       /* Ink */
  --charcoal: #1a1a1a;  /* Charcoal — raised surfaces on the dark ground */
  --highlight: #d7d3ff; /* Highlight — a pill, never a surface */
  --paper: #ffffff;     /* Paper */
  --fog: #f3f3f1;       /* Fog */
  --stone: #8a8a8a;     /* Stone — secondary text */

  /* Two the kit names beside the seven: lime has to darken to be read as text,
     and an error needs a colour of its own. Warning has no value in the kit, so
     this one was chosen to sit beside lime without competing with it. */
  --lime-ink: #4a5a10;
  --danger: #c0392b;
  --warn: #8a5c00;

  /* Stone is 5.2:1 on ink and 5.0:1 on charcoal, so it is used as given on the
     dark ground. On fog it is 3.1:1, which is below AA at the size this site
     sets body text, so the bright sections take the same neutral darkened until
     it passes — 4.8:1 on fog. The hue is unchanged; only the value moves. */
  --stone-dark: #6b6b6b;

  /* The dark ground and its surfaces are the reference the panel and the phone
     now follow: a cool blue-black page, a charcoal panel a step above it, a
     card a step above that, and the reference's own quiet grey for secondary
     text. Cool on purpose — these are that reference's tones, and the warm ink
     keeps its real job: type, the mark, and the text on lime and on highlight.
     The site, app.dotpano.com and the phone share these exact values. */
  --ground-dark: #0e1014;
  --panel: #171a20;
  --panel-2: #1e2229;
  --panel-3: #262b33;
  --mist: #8e939c;

  /* Danger and warning as they have to read on the dark ground. Declared twice
     so a browser without `color-mix` still gets a colour rather than dropping
     the declaration and inheriting whatever was underneath. */
  --danger-lit: #d4786f;
  --danger-lit: color-mix(in srgb, var(--danger) 68%, var(--paper));
  --warn-lit: #aba51b;
  --warn-lit: color-mix(in srgb, var(--warn) 55%, var(--lime));

  /* The dark ground is lit rather than flat: one soft circle, high and
     centred, exactly as the reference lights its own page. It is what stops a
     panel sitting on the ground from reading as a slightly different grey.

     Three things about it are deliberate. It is held to the viewport rather
     than to the document, so it neither repeats at every section boundary nor
     travels with the content — the light is in the room and the page moves
     through it. Its only colour is `--panel-3` at an opacity, so the palette
     is unchanged. And its peak lands at rgb(21, 24, 29), which is below
     `--panel` at rgb(23, 26, 32): the brightest the ground ever gets is still
     darker than the darkest thing standing on it, so depth never inverts. */
  --halo: radial-gradient(circle min(115vw, 1020px) at 50% 0%,
      rgba(38, 43, 51, 0.28),
      rgba(38, 43, 51, 0.15) 42%,
      rgba(38, 43, 51, 0) 74%);

  /* Hairlines, never a solid grey border. */
  --hair-d: rgba(255, 255, 255, 0.08);
  --hair-l: rgba(20, 24, 12, 0.08);

  /* Roles. `.bright` redefines these four and nothing else has to know. */
  --ground: var(--ground-dark);
  --surface: var(--panel);
  --surface-2: var(--panel-2);
  --text: var(--paper);
  --text-2: var(--mist);
  --hair: var(--hair-d);

  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --dur: 720ms;
  --dur-fast: 220ms;

  --r-shell: 32px;
  --r-core: 24px;
  --r-tile: 18px;
  --r-pill: 999px;

  --gutter: clamp(18px, 2.2vw, 28px);
  --wrap: 1200px;
  --pad: clamp(16px, 5vw, 40px);
  --section: clamp(96px, 12vw, 160px);
}

.bright {
  --ground: var(--fog);
  --surface: var(--paper);
  --surface-2: var(--fog);
  --text: var(--ink);
  --text-2: var(--stone-dark);
  --hair: var(--hair-l);
}

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

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: #101010;
  background: var(--ground-dark);
  background-image: var(--halo);
  background-attachment: fixed;
  color: var(--paper);
  font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a { color: inherit; text-decoration: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

input {
  font: inherit;
  color: inherit;
}

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

::selection {
  background: var(--lime);
  color: var(--ink);
}

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

/* ------------------------------------------------------------ layout --- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.section {
  position: relative;
  background: transparent;
  color: var(--text);
  padding-block: var(--section);
}

/* Only the reversals paint. A dark section leaves the page's own lit ground
   showing through, which is the whole point of putting the circle on the body:
   paint it here and every section boundary would start the gradient again. */
.section.bright { background: var(--fog); }

.section-head { max-width: 62ch; }
.section-head .h2 { margin-top: 16px; }
.section-head .lede { margin-top: 18px; }

/* Never a symmetrical three-up with a default gap: each grid below states its
   own rhythm, and the asymmetric ones collapse to one column on a phone. */
.grid { display: grid; gap: var(--gutter); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 900px) {
  .g3, .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .g2, .g3, .g4 { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------------- typography --- */

/* Tracking depends on the size band, which is the kit's own rule: -0.03em is a
   display setting and closes headings up if it is used on them. */
.display {
  margin: 0;
  font-size: clamp(2.75rem, 7vw, 6rem);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.display .quiet {
  display: block;
  margin-top: 0.24em;
  font-size: 0.46em;
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--text-2);
}

.h2 {
  margin: 0;
  font-size: clamp(2rem, 4.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.h3 {
  margin: 0;
  font-size: clamp(1.15rem, 1.6vw, 1.4rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.h4 {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.lede {
  margin: 0;
  font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  line-height: 1.5;
  color: var(--text-2);
  text-wrap: pretty;
}

.body {
  margin: 0;
  color: var(--text-2);
  text-wrap: pretty;
}

.tabular { font-variant-numeric: tabular-nums; }

/* Who said the thing above it. The name takes the strong role and the rest the
   quiet one, so it reads on a bright section and a dark one without knowing
   which it is standing in. */
.quote-by {
  margin: 20px 0 0;
  font-size: 14px;
  color: var(--text-2);
}
.quote-by b { color: var(--text); font-weight: 600; }

/* The eyebrow pill that stands above every H1 and H2. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 7px 14px 7px 10px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-2);
}

.eyebrow .sweep-mini { flex: none; }

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 13px 13px 13px 26px;
  border: 1.5px solid transparent;
  border-radius: var(--r-pill);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}

.btn:active { transform: scale(0.98); }

/* The arrow lives in its own circle and moves on hover; the pill itself does
   not, which keeps a row of buttons from jittering. */
.btn .arrow {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--lime);
  color: var(--ink);
  transition: transform var(--dur-fast) var(--ease);
}

.btn:hover .arrow { transform: translate(2px, -2px); }
.btn .arrow svg { width: 15px; height: 15px; }

.btn-primary { background: var(--lime); color: var(--ink); }
.btn-primary .arrow { background: var(--ink); color: var(--lime); }
.btn-primary:hover { background: #e2ff70; background: color-mix(in srgb, var(--lime) 84%, var(--paper)); }

.btn-solid { background: var(--paper); color: var(--ink); }
.bright .btn-solid { background: var(--ink); color: var(--paper); }

.btn-line {
  padding: 13px 26px;
  border-color: var(--hair);
  color: var(--text);
}
.btn-line:hover { border-color: var(--text); }

.btn-quiet {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 0;
  font-weight: 600;
  color: var(--text);
}
.btn-quiet .chev { transition: transform var(--dur-fast) var(--ease); }
.btn-quiet:hover .chev { transform: translateY(3px); }

.btn-sm { padding: 9px 9px 9px 18px; font-size: 14px; }
.btn-sm .arrow { width: 27px; height: 27px; }
.btn-sm .arrow svg { width: 12px; height: 12px; }

/* --------------------------------------------------- the double bezel --- */

/* Every major panel is a shell around a core: the shell is barely-there and
   carries the hairline, the core is the real surface with its own top
   highlight. The radii are concentric — the core's is the shell's less the
   shell's padding — so the two curves are parallel rather than merely similar. */
.bezel {
  padding: 6px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--hair);
  border-radius: var(--r-shell);
}

.bright .bezel { background: rgba(20, 24, 12, 0.03); }

.bezel > .core {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border-radius: var(--r-core);
}

.bright .bezel > .core { background: var(--paper); }

/* The inner highlight: one hairline of light along the top edge of the core. */
.bezel > .core::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.18), transparent);
}

.bright .bezel > .core::before { background: linear-gradient(90deg, transparent, var(--hair-l), transparent); }

.core-pad { padding: clamp(20px, 2.4vw, 30px); }

/* ------------------------------------------------------------- reveals --- */

/* Entry is per element and happens once. Nothing on this site listens to the
   scroll event; an IntersectionObserver sets `is-in` and the transition here
   does the rest. */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  filter: blur(6px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
    filter var(--dur) var(--ease);
}

.reveal.is-in {
  opacity: 1;
  transform: none;
  filter: none;
}

/* Stagger inside a group, capped so a long list never crawls. */
.reveal[data-i='1'] { transition-delay: 70ms; }
.reveal[data-i='2'] { transition-delay: 140ms; }
.reveal[data-i='3'] { transition-delay: 210ms; }
.reveal[data-i='4'] { transition-delay: 280ms; }
.reveal[data-i='5'] { transition-delay: 350ms; }

/* A page whose script never ran must still be readable, so the hidden state is
   applied by the script rather than assumed here. */
.no-js .reveal { opacity: 1; transform: none; filter: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal,
  .reveal.is-in {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ================================================================== nav === */

/* A floating pill, detached from the top edge. It gets its glass only once the
   page has moved, so the hero meets it as a shape rather than a bar. */
.nav {
  position: fixed;
  z-index: 40;
  top: 14px;
  left: 0;
  right: 0;
  pointer-events: none;
}

.nav-in {
  display: flex;
  align-items: center;
  gap: clamp(14px, 3vw, 34px);
  max-width: calc(var(--wrap) - 40px);
  margin-inline: auto;
  padding: 9px 9px 9px 22px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  pointer-events: auto;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}

.nav.is-stuck .nav-in {
  background: rgba(14, 16, 20, 0.72);
  border-color: var(--hair-d);
  backdrop-filter: blur(16px) saturate(1.4);
}

/* The lockup is drawn inline rather than loaded, so the intro can move its
   parts: the letters take the current colour, the mark is lime, the eyes ink.
   It is 417.32 x 137.7, so the width is the height times 3.03, and the pair of
   numbers has to move together or the mark distorts. */
.logo {
  display: block;
  width: 121px;
  height: 40px;
  color: var(--paper);
}

.logo .lockup { display: block; width: 100%; height: 100%; overflow: visible; }
.logo .body { fill: var(--lime); }
.logo .eye { fill: var(--ink); }

/* The footer's is larger again — there is room, and it is the last thing on the
   page rather than something competing with a nav full of links. */
.foot .logo { width: 158px; height: 52px; }

.bright .logo,
.logo.on-light { color: var(--ink); }

/* The links are the panel's tab strip: a pill holding pills, the current page
   lime. The same strip sits across the top of app.dotpano.com. */
.nav-links {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: auto;
  padding: 4px;
  border-radius: var(--r-pill);
  background: var(--panel);
  border: 1px solid var(--hair-d);
}

.nav-links a {
  display: flex;
  align-items: center;
  height: 34px;
  padding: 0 15px;
  border-radius: var(--r-pill);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--mist);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}

.nav-links a:hover { color: var(--paper); }
.nav-links a[aria-current='page'] { background: var(--lime); color: var(--ink); }

.nav-cta {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-left: auto;
}

.nav-signin { font-size: 14px; font-weight: 600; color: var(--mist); }
.nav-signin:hover { color: var(--paper); }

.nav-burger {
  display: none;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-left: auto;
  border: 1px solid var(--hair-d);
  border-radius: 50%;
}

.nav-burger svg { width: 17px; height: 17px; }

@media (max-width: 900px) {
  .nav-links,
  .nav-cta { display: none; }
  .nav-burger { display: grid; }
  .nav-in { padding-left: 18px; }
  .logo { width: 100px; height: 33px; }
}

/* The mobile sheet: a full overlay whose rows arrive one after another. */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  align-content: center;
  gap: 6px;
  padding: var(--pad);
  background: rgba(16, 16, 16, 0.95);
  backdrop-filter: blur(20px);
  opacity: 0;
  visibility: hidden;
  /* Visibility is stepped, not faded. Transitioning it alongside opacity leaves
     the sheet computing as hidden for the first frame, which is the frame the
     close button is focused in — so the keyboard would be left behind on a menu
     that had visually opened. Opening flips it at once; closing waits for the
     fade to finish. */
  transition: opacity var(--dur-fast) var(--ease), visibility 0s var(--dur-fast);
}

.sheet.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--dur-fast) var(--ease), visibility 0s;
}

.sheet a {
  font-size: clamp(2rem, 9vw, 3rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.18;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 420ms var(--ease), transform 420ms var(--ease);
}

.sheet.is-open a { opacity: 1; transform: none; }
.sheet.is-open a:nth-child(1) { transition-delay: 60ms; }
.sheet.is-open a:nth-child(2) { transition-delay: 110ms; }
.sheet.is-open a:nth-child(3) { transition-delay: 160ms; }
.sheet.is-open a:nth-child(4) { transition-delay: 210ms; }
.sheet.is-open a:nth-child(5) { transition-delay: 260ms; }
.sheet.is-open a:nth-child(6) { transition-delay: 310ms; }

.sheet-close {
  position: absolute;
  top: 22px;
  right: var(--pad);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--hair-d);
  border-radius: 50%;
}

.sheet-close svg { width: 17px; height: 17px; }

/* ================================================================ hero === */

.hero {
  position: relative;
  min-height: min(100dvh, 900px);
  display: flex;
  align-items: center;
  padding-block: clamp(130px, 16vh, 190px) var(--section);
  overflow: hidden;
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: clamp(36px, 5vw, 72px);
  align-items: center;
}

@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero { min-height: 0; }
}

.hero .display { margin-top: 22px; }
.hero .lede { margin-top: 24px; max-width: 54ch; }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
  margin-top: 38px;
}

.hero-note {
  margin-top: 22px;
  font-size: 14px;
  color: var(--stone);
}

.hero-grid { position: relative; z-index: 1; }

/* ============================================================== sweep === */

/* The motif. A dotted ring with one lime dot on it: read as a panorama it is
   the camera going round, read as a clock it is a hosting term running out. */
.sweep { display: block; }
.sweep .track { fill: none; stroke: currentColor; opacity: 0.38; stroke-dasharray: 1.6 8; stroke-linecap: round; }
.sweep .track.small { stroke-dasharray: 4 13; opacity: 0.55; }
.sweep .lit { fill: var(--lime); }
.sweep .trail { fill: var(--lime); }

.sweep.spin .rotor {
  transform-origin: 50% 50%;
  animation: sweep-turn 9s linear infinite;
}

@keyframes sweep-turn { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .sweep.spin .rotor { animation: none; }
}

.sweep-mini { width: 13px; height: 13px; color: var(--text-2); }
.sweep .num { fill: currentColor; font-size: 30px; font-weight: 700; letter-spacing: -0.03em; }

/* ========================================================== platforms === */

.marquee {
  position: relative;
  margin-top: 34px;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.marquee-row {
  display: flex;
  gap: 12px;
  width: max-content;
  animation: marquee 42s linear infinite;
}

.marquee:hover .marquee-row { animation-play-state: paused; }

@keyframes marquee { to { transform: translateX(-50%); } }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 18px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text-2);
}

.chip.lit {
  border-color: rgba(212, 255, 59, 0.4);
  background: rgba(212, 255, 59, 0.08);
  color: var(--lime);
}

/* On a phone the marquee is a wrapped grid: motion for its own sake in a strip
   nobody can pause is not worth the battery. */
@media (max-width: 767px) {
  .marquee { mask-image: none; overflow: visible; }
  .marquee-row {
    flex-wrap: wrap;
    width: auto;
    animation: none;
  }
  .marquee-row .dup { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .marquee-row { animation: none; }
}

/* =========================================================== work-card === */
/* The product as it actually looks, built from the same parts as the panel:
   a white card holding a strip of pill tabs, a list of pill rows with the
   chosen one dark, and a charcoal detail panel. Always paper and always
   charcoal, whatever section it sits in — it is a picture of the product and
   the product does not change with the page. */
.work {
  border-radius: 26px;
  background: var(--paper);
  color: var(--ink);
  padding: 18px 18px 18px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
  min-width: 0;
}

.work > * { min-width: 0; }

.work-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 0 4px;
}

.work-title { font-size: 14.5px; font-weight: 700; letter-spacing: -0.01em; }

.segs {
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  border-radius: var(--r-pill);
  background: var(--fog);
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

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

.segs span {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 13px;
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 700;
  color: var(--stone-dark);
  white-space: nowrap;
}

.segs span.on { background: var(--lime); color: var(--ink); }

.segs i {
  font-style: normal;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--paper);
  font-size: 10.5px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.segs span.on i { color: var(--lime); }

.pills { display: grid; gap: 4px; }

.pill-row {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto auto;
  gap: 11px;
  align-items: center;
  padding: 6px 13px 6px 6px;
  border-radius: var(--r-pill);
  color: var(--ink);
}

.pill-row.on { background: var(--ink); color: var(--paper); }

.pill-row .face {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--fog);
  color: var(--ink);
  font-size: 10.5px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.pill-row.on .face { background: rgba(255, 255, 255, 0.14); color: var(--paper); }
.pill-row .who { min-width: 0; display: flex; flex-direction: column; }
.pill-row .ref { font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pill-row .when { font-size: 11.5px; color: var(--stone-dark); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pill-row.on .when { color: rgba(255, 255, 255, 0.62); }
.pill-row .amt { font-size: 13.5px; font-weight: 700; min-width: 56px; text-align: right; font-variant-numeric: tabular-nums; }

.status {
  height: 23px;
  padding: 0 9px;
  border-radius: var(--r-pill);
  font-size: 10.5px;
  font-weight: 700;
  background: var(--fog);
  color: var(--stone-dark);
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.status.due { background: rgba(212, 255, 59, 0.5); color: var(--ink); }
.status.over { background: rgba(192, 57, 43, 0.12); color: var(--danger); }
.status.warn { background: rgba(138, 92, 0, 0.12); color: var(--warn); }
.pill-row.on .status { background: rgba(255, 255, 255, 0.14); color: var(--paper); }

.detail {
  border-radius: 20px;
  background: var(--panel);
  color: var(--paper);
  padding: 16px 18px;
  display: grid;
  gap: 14px;
}

.detail-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.detail-head .lbl { font-size: 11.5px; color: var(--mist); }
.detail-ref { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.detail-ref .id { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.detail-ref .hash { color: var(--mist); font-weight: 500; margin-right: 3px; }
.detail .status { background: var(--panel-3); color: var(--mist); }
.detail .status.due { background: rgba(212, 255, 59, 0.18); color: var(--lime); }
.detail .person { display: flex; align-items: center; gap: 9px; margin-top: 4px; }
.detail .person .face { width: 30px; height: 30px; border-radius: 50%; background: var(--panel-3); color: var(--paper); font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.detail .person .face.lime { background: var(--lime); color: var(--ink); }
.detail .person .name { font-size: 13px; font-weight: 600; }
.detail .person .role { font-size: 11px; color: var(--mist); }

.lines { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.line { padding: 11px 12px 10px; border-radius: 12px; background: var(--panel-2); border: 1px solid var(--hair-d); min-width: 0; }
.line .v { font-size: 15.5px; font-weight: 700; letter-spacing: -0.01em; white-space: nowrap; }
.line .v .cur { font-size: 10.5px; color: var(--mist); font-weight: 500; margin-right: 2px; vertical-align: 0.45em; }
.line .k { font-size: 11px; color: var(--mist); margin-top: 6px; }
.line .k.warn { color: var(--warn-lit); }

.detail-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.detail-foot .net { font-size: 12px; color: var(--mist); }
.detail-foot .net b { color: var(--lime); font-weight: 700; font-size: 14px; }
.go {
  height: 36px;
  padding: 0 15px;
  border-radius: var(--r-pill);
  background: var(--lime);
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

@media (max-width: 620px) {
  .lines { grid-template-columns: minmax(0, 1fr); }
  .pill-row { grid-template-columns: 36px minmax(0, 1fr) auto; }
  .pill-row .status { display: none; }
}

/* ======================================================= renewal panel === */

.panel-cap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--hair);
}

.panel-cap .h4 { letter-spacing: 0.02em; }
.panel-cap .meta { font-size: 13px; color: var(--text-2); }

.rows { display: grid; }

.row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px 16px;
  align-items: center;
  padding: 14px 20px;
}

.row + .row { border-top: 1px solid var(--hair); }

.row .name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.row .sub {
  grid-column: 1;
  font-size: 12.5px;
  color: var(--text-2);
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.row .sub .dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.5;
  flex: none;
}

.row .right {
  grid-row: 1 / span 2;
  grid-column: 2;
  text-align: right;
}

.days {
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
}

.days small { font-size: 11px; font-weight: 600; color: var(--text-2); }

.tag {
  display: inline-block;
  margin-top: 6px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.tag.due { background: rgba(212, 255, 59, 0.14); color: var(--lime); }
.tag.soon { background: rgba(214, 158, 46, 0.16); color: var(--warn-lit); }
.tag.over { background: rgba(192, 57, 43, 0.16); color: var(--danger-lit); }
.tag.sent { background: rgba(255, 255, 255, 0.08); color: var(--text-2); }

.bright .tag.due { background: rgba(74, 90, 16, 0.12); color: var(--lime-ink); }
.bright .tag.soon { background: rgba(138, 92, 0, 0.12); color: var(--warn); }
.bright .tag.over { background: rgba(192, 57, 43, 0.1); color: var(--danger); }
.bright .tag.sent { background: rgba(20, 24, 12, 0.06); color: var(--stone); }

/* Truncating a tour's name is right in a dense dashboard and wrong on a page
   someone is reading, so on a narrow screen the row gives up a line instead. */
@media (max-width: 620px) {
  .row .name { white-space: normal; overflow: visible; }
  .row { grid-template-columns: minmax(0, 1fr) auto; }
}

.panel-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 20px;
  border-top: 1px solid var(--hair);
  font-size: 13px;
  color: var(--text-2);
}

.total { font-size: 15px; font-weight: 700; color: var(--text); }

/* A small figure card that sits under the panel. */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: var(--gutter);
}

.stat { font-size: clamp(1.7rem, 2.6vw, 2.2rem); font-weight: 700; line-height: 1; letter-spacing: -0.02em; }
.stat-cap { margin-top: 8px; font-size: 13px; color: var(--text-2); }

/* ========================================================== the clock === */

/* One tour's life on a line, then the fork at expiry. The line fills as the
   section is scrolled, which is the only scroll-linked thing on the site. */
.timeline { margin-top: 54px; }

.track-line {
  position: relative;
  height: 2px;
  background: var(--hair);
  border-radius: 2px;
}

.track-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--p, 0%);
  background: var(--lime);
  border-radius: 2px;
}

.track-marks {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-top: 18px;
}

.mark .h4 { font-size: 14px; }
.mark .body { margin-top: 5px; font-size: 13px; }

.mark .pip {
  width: 9px;
  height: 9px;
  margin-bottom: 12px;
  border-radius: 50%;
  background: var(--hair);
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.mark.on .pip {
  background: var(--lime);
  box-shadow: 0 0 0 5px rgba(212, 255, 59, 0.14);
}

.fork {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: 46px;
}

@media (max-width: 767px) {
  .track-marks { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .fork { grid-template-columns: minmax(0, 1fr); }
}

.fork .core-pad { display: grid; gap: 10px; }
.fork .good { border-color: rgba(212, 255, 59, 0.28); }
.fork .bad .h3 { color: var(--danger-lit); }

/* ========================================================= portfolio === */

.page-mock .core { background: var(--paper); }

.mock-cover {
  height: 96px;
  background: linear-gradient(120deg, var(--charcoal), #2b3117 60%, #3b4420);
  background: linear-gradient(120deg, var(--charcoal),
    color-mix(in srgb, var(--ink) 82%, var(--lime)) 60%,
    color-mix(in srgb, var(--ink) 68%, var(--lime)));
}

.mock-head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px 20px 16px;
}

/* Only the avatar breaks the cover's edge; the name stays on the page's own
   ground, where it is legible. */
.mock-avatar { margin-top: -34px; }

.mock-avatar {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  flex: none;
  border: 3px solid var(--paper);
  border-radius: 18px;
  background: var(--lime);
  font-weight: 800;
  font-size: 19px;
  color: var(--ink);
}

.mock-name { font-size: 16px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.mock-handle { font-size: 12.5px; color: var(--stone); }

.mock-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 9px;
  padding: 0 20px 20px;
}

.tile {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 12px;
  overflow: hidden;
  background: var(--fog);
}

/* Drawn, not photographed: a flat plan of a room, which is what a tour of one
   looks like from above. Nothing here pretends to be a real property. */
.tile svg { width: 100%; height: 100%; }

.tile .badge {
  position: absolute;
  left: 6px;
  bottom: 6px;
  padding: 3px 7px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.9);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--ink);
}

/* The handle field. It previews the address as you type and checks nothing,
   because there is no availability endpoint to ask. */
.handle {
  display: flex;
  align-items: center;
  gap: 0;
  margin-top: 26px;
  padding: 6px 6px 6px 18px;
  max-width: 460px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--paper);
}

.handle .prefix {
  font-size: 15px;
  font-weight: 600;
  color: var(--stone);
  white-space: nowrap;
}

.handle input {
  flex: 1;
  min-width: 0;
  padding: 8px 10px 8px 1px;
  border: 0;
  outline: 0;
  background: none;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.handle input::placeholder { color: var(--stone); font-weight: 600; }

.handle-note { margin-top: 12px; font-size: 13px; color: var(--stone-dark); min-height: 20px; }
.handle-note b { color: var(--ink); font-weight: 700; }

/* The check. It sits in the pill, so the field and its one action are one
   object rather than a box with a button parked beside it. */
.handle-go {
  flex: none;
  height: 38px;
  padding: 0 18px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--paper);
  font-size: 13.5px;
  font-weight: 700;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}

.handle-go:hover { background: #2a3019; background: color-mix(in srgb, var(--ink) 88%, var(--paper)); }
.handle-go[disabled] { opacity: 0.45; }

/* The answer. Free is lime-as-text, because lime itself cannot be read on fog;
   taken and malformed are the palette's own two. */
.handle-note.free b,
.handle-note.free { color: var(--lime-ink); }
.handle-note.no { color: var(--danger); }
.handle-note.no b { color: var(--danger); }

/* Where an address turns out to be free, the next move goes with the answer. */
.handle-claim {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  margin-left: 10px;
  padding: 0 8px 0 15px;
  border-radius: var(--r-pill);
  background: var(--lime);
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
  vertical-align: middle;
}

.handle-claim .arrow {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--lime);
}

.handle-claim .arrow svg { width: 12px; height: 12px; }

/* ============================================================== bento === */

/* Asymmetric on purpose: the first tile is the argument and gets the room, the
   rest are evidence. */
.bento {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: 54px;
}

.bento > * { grid-column: span 2; }
.bento .wide { grid-column: span 4; }
.bento .half { grid-column: span 3; }

@media (max-width: 980px) {
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bento > *,
  .bento .wide,
  .bento .half { grid-column: span 2; }
}

.bento .core-pad { display: grid; gap: 12px; height: 100%; align-content: start; }
.bento .h3 { margin-top: 4px; }

.icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--hair);
  border-radius: 12px;
  color: var(--lime);
}

.icon svg { width: 19px; height: 19px; }
.bright .icon { color: var(--lime-ink); }

/* A rendered notification, in place of a screenshot of one. */
.notice {
  display: flex;
  gap: 12px;
  margin-top: 6px;
  padding: 14px;
  border: 1px solid var(--hair);
  border-radius: var(--r-tile);
  background: rgba(255, 255, 255, 0.03);
}

.notice .mark-dot {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 9px;
  background: var(--lime);
}

.notice .t { font-size: 13.5px; font-weight: 700; letter-spacing: -0.01em; }
.notice .b { margin-top: 3px; font-size: 12.5px; color: var(--text-2); }

/* A term bar: how much of a hosting year is gone. */
.term { display: grid; gap: 7px; }
.term .lbl { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--text-2); }
.term .bar { height: 5px; border-radius: 3px; background: var(--hair); overflow: hidden; }
.term .bar i { display: block; height: 100%; border-radius: 3px; background: var(--lime); }
.term .bar i.warn { background: var(--warn-lit); }
.term .bar i.over { background: var(--danger-lit); }

/* ========================================================= calculator === */

.calc > .bezel { display: flex; flex-direction: column; }
.calc > .bezel > .core { flex: 1; }

.calc {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: var(--gutter);
  margin-top: 48px;
  align-items: stretch;
}

@media (max-width: 900px) { .calc { grid-template-columns: minmax(0, 1fr); } }

.fields { display: grid; gap: 24px; }

.field .lbl {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 13.5px;
  color: var(--text-2);
}

.field .val { font-size: 17px; font-weight: 700; color: var(--text); }

.field input[type='range'] {
  width: 100%;
  margin-top: 12px;
  height: 4px;
  border-radius: 3px;
  background: var(--hair);
  appearance: none;
  -webkit-appearance: none;
}

.field input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--lime);
  border: 3px solid var(--surface);
  cursor: pointer;
}

.field input[type='range']::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border: 3px solid var(--surface);
  border-radius: 50%;
  background: var(--lime);
  cursor: pointer;
}

/* The output is the one lime surface in this section: a darkened lime set as
   type at display size reads as mud, and the kit's pairing for a figure this
   size is ink on lime. */
.bezel.answer { background: rgba(212, 255, 59, 0.16); border-color: rgba(212, 255, 59, 0.4); }
.bezel.answer > .core { background: var(--lime); }
.bezel.answer > .core::before { background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent); }

.out {
  display: grid;
  align-content: center;
  gap: 6px;
  text-align: center;
  color: var(--ink);
}

.out .figure {
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.out .cap { font-size: 13.5px; color: rgba(20, 24, 12, 0.66); }

.ccy {
  display: inline-flex;
  gap: 2px;
  margin: 0 auto;
  padding: 3px;
  border: 1px solid rgba(20, 24, 12, 0.2);
  border-radius: var(--r-pill);
}

.ccy button {
  padding: 5px 12px;
  border-radius: var(--r-pill);
  font-size: 12.5px;
  font-weight: 700;
  color: rgba(20, 24, 12, 0.6);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.ccy button:hover { color: var(--ink); }
.ccy button[aria-pressed='true'] { background: var(--ink); color: var(--lime); }

.calc-note { margin-top: 20px; font-size: 13px; color: var(--text-2); max-width: 68ch; }

/* ============================================================== steps === */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 4vw, 56px);
  margin-top: 56px;
}

@media (max-width: 860px) { .steps { grid-template-columns: minmax(0, 1fr); gap: 34px; } }

.step .sweep { width: 58px; height: 58px; color: var(--text); }
.step .h3 { margin-top: 20px; }
.step .body { margin-top: 8px; }

/* ============================================================= plans === */

.plans {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: 48px;
  align-items: stretch;
}

@media (max-width: 1000px) { .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .plans { grid-template-columns: minmax(0, 1fr); } }

/* The way out of the summary and into the row-by-row table. Centred under the
   four cards, because it belongs to all of them rather than to the last one. */
.plans-more { margin-top: 40px; display: flex; justify-content: center; }

.plan { height: 100%; }
.plan .core-pad { display: flex; flex-direction: column; height: 100%; }
.plan .body { margin-top: 8px; font-size: 14.5px; min-height: 4.8em; }

.plan .amount { display: flex; align-items: baseline; gap: 4px; margin-top: 20px; }
.plan .num { font-size: 2.4rem; font-weight: 800; line-height: 1; letter-spacing: -0.03em; }
.plan .per { font-size: 13.5px; color: var(--text-2); }

.plan ul { list-style: none; margin: 22px 0 26px; padding: 0; display: grid; gap: 9px; font-size: 14.5px; color: var(--text-2); }
.plan li { display: flex; gap: 9px; align-items: flex-start; }
.plan li svg { width: 15px; height: 15px; flex: none; margin-top: 3px; color: var(--lime); }
.bright .plan li svg { color: var(--lime-ink); }
.plan .btn { margin-top: auto; align-self: flex-start; }

/* The spotlight: a lime hairline and a faint bloom, not a second colour. */
.plan.lit { background: rgba(212, 255, 59, 0.09); border-color: rgba(212, 255, 59, 0.34); }
.plan.lit > .core { box-shadow: inset 0 1px 0 rgba(212, 255, 59, 0.16); }

/* The flag's row is one height, named once, because a card without a flag has
   to reserve exactly it. The four prices read as a row across the cards, and
   the flag was the one thing pushing its own card's title — and the price,
   the list and the button under it — down from the three beside it. */
.plan { --flag-row: 22px; }

.plan-flag {
  display: inline-block;
  height: var(--flag-row);
  line-height: var(--flag-row);
  padding: 0 10px;
  margin-bottom: 12px;
  border-radius: var(--r-pill);
  background: var(--highlight);
  color: var(--ink);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* A card with no flag opens its title that much lower instead. This is
   deliberately a margin and not a spacer pseudo-element: `.bezel > .core`
   already owns `::before` for the hairline across the card's top edge, and a
   second rule on the same pseudo-element does not add a box — it fights the
   first one for it, which is how a 1px hairline becomes a 22px band. */
.plan:not(:has(.plan-flag)) .h3 { margin-top: calc(var(--flag-row) + 12px); }

/* One column: there is no card beside this one to line a price up with, so the
   reserved row is just a gap over three of the four titles. This has to sit
   after the rule above rather than beside the grid's own breakpoints, because
   the two have the same specificity and order is all that separates them. */
@media (max-width: 560px) { .plan:not(:has(.plan-flag)) .h3 { margin-top: 0; } }

/* ============================================================= table === */

.compare { margin-top: 54px; overflow-x: auto; }

.compare table { width: 100%; min-width: 640px; border-collapse: collapse; font-size: 14.5px; }

.compare th,
.compare td { padding: 14px 16px; text-align: left; border-bottom: 1px solid var(--hair); }

.compare thead th { font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2); font-weight: 600; }
.compare tbody th { font-weight: 600; color: var(--text); }
.compare td { color: var(--text-2); font-variant-numeric: tabular-nums; }
.compare td svg { width: 15px; height: 15px; color: var(--lime); }
.bright .compare td svg { color: var(--lime-ink); }
.compare .grp td { padding-top: 30px; font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2); border-bottom: 0; }
/* =============================================================== faq === */

.faq {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: clamp(28px, 5vw, 72px);
}

@media (max-width: 860px) { .faq { grid-template-columns: minmax(0, 1fr); } }

.faq-side { align-self: start; position: sticky; top: 110px; }
@media (max-width: 860px) { .faq-side { position: static; } }

.faq-list { display: grid; }
.faq-item { padding: 26px 0; border-top: 1px solid var(--hair); }
.faq-item:first-child { border-top: 0; padding-top: 0; }
.faq-item .body { margin-top: 10px; max-width: 62ch; }

/* ========================================================== cta band === */

.cta {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-shell);
  background: var(--lime);
  color: var(--ink);
  padding: clamp(38px, 6vw, 76px);
}

.cta .h2 { max-width: 18ch; }
.cta .body { color: rgba(20, 24, 12, 0.72); margin-top: 16px; max-width: 52ch; }
.cta .btn { margin-top: 32px; }
.cta .btn-solid { background: var(--ink); color: var(--lime); }
.cta .btn-solid .arrow { background: var(--lime); color: var(--ink); }

/* The mascot, not the ring. It sits to the right of the copy and spends most
   of its cycle glancing left at it, which is the whole reason it is there.

   On a lime band the body has to invert: a lime body on a lime ground is not a
   logo, so it takes ink with lime eyes — the same inversion the app icon uses.
   The shadow is the brand's own, ink at 22% five units down. */
.cta .face {
  position: absolute;
  right: clamp(-26px, 1vw, 40px);
  top: 50%;
  width: clamp(150px, 17vw, 220px);
  height: auto;
  transform: translateY(-50%);
  pointer-events: none;
}

.face .body { fill: var(--ink); }
.face .eye { fill: var(--lime); }
.face .shade { fill: #000; opacity: 0.3; }

/* Below the point where the band's copy would reach it, the face stops being a
   decoration off to one side and becomes the thing you meet first. */
@media (max-width: 760px) {
  .cta .face {
    position: static;
    width: 108px;
    margin-bottom: 22px;
    transform: none;
  }
}

/* ============================================================ footer === */

.foot {
  background: transparent;
  color: var(--paper);
  padding-block: clamp(56px, 7vw, 88px) 34px;
  border-top: 1px solid var(--hair-d);
}

.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 56px);
}

@media (max-width: 860px) { .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .foot-grid { grid-template-columns: minmax(0, 1fr); } }

.foot .body { margin-top: 18px; max-width: 34ch; font-size: 14px; }
.foot h2 { margin: 0 0 16px; font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--stone); }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; font-size: 14.5px; }
.foot ul a { color: var(--stone); transition: color var(--dur-fast) var(--ease); }
.foot ul a:hover { color: var(--paper); }

.foot-base {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  justify-content: space-between;
  margin-top: clamp(40px, 6vw, 64px);
  padding-top: 24px;
  border-top: 1px solid var(--hair-d);
  font-size: 13px;
  color: var(--stone);
}

/* A placeholder is marked as one, in the markup and to the eye. */
.todo {
  border-bottom: 1px dashed rgba(212, 255, 59, 0.5);
  color: var(--lime);
}

/* On a light ground lime cannot be read as type — 1.3:1 on fog — so a
   placeholder there takes the kit's lime-as-text value, which is 6.9:1. */
.bright .todo {
  color: var(--lime-ink);
  border-bottom-color: rgba(74, 90, 16, 0.5);
}

/* ============================================================== misc === */

.note {
  padding: 18px 22px;
  border-left: 3px solid var(--lime);
  border-radius: 0 var(--r-tile) var(--r-tile) 0;
  background: rgba(255, 255, 255, 0.04);
  font-size: 14.5px;
  color: var(--text-2);
  max-width: 74ch;
}

.bright .note { background: rgba(20, 24, 12, 0.03); border-left-color: var(--lime-ink); }
.note b { color: var(--text); font-weight: 700; }

.prose { max-width: 72ch; }
.prose h2 { margin: 46px 0 12px; font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; }
.prose h3 { margin: 32px 0 10px; font-size: 1.1rem; font-weight: 700; letter-spacing: -0.015em; }
.prose p { margin: 0 0 16px; color: var(--text-2); }
.prose ul, .prose ol { margin: 0 0 16px; padding-left: 22px; color: var(--text-2); }
.prose li { margin-bottom: 8px; }
.prose a { color: var(--lime-ink); text-decoration: underline; text-underline-offset: 3px; }
.prose code { padding: 2px 6px; border-radius: 5px; background: rgba(20, 24, 12, 0.06); font-size: 0.92em; }

.toc { position: sticky; top: 110px; align-self: start; }
.toc ul { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 9px; font-size: 14px; }
.toc a { color: var(--text-2); }
.toc a:hover, .toc a.on { color: var(--text); }

.guide-grid { display: grid; grid-template-columns: minmax(0, 220px) minmax(0, 1fr); gap: clamp(28px, 5vw, 64px); }
@media (max-width: 860px) { .guide-grid { grid-template-columns: minmax(0, 1fr); } .toc { position: static; } }

.mid { min-height: 60dvh; display: grid; place-items: center; text-align: center; }
.mid .sweep { width: 140px; height: 140px; margin: 0 auto 34px; color: var(--paper); }
