/* ==========================================================================
   Lumaki marketing site — single stylesheet.

   Every colour, radius, space step, face and curve comes from
   `css/tokens.generated.css`, which design/generate.py writes from
   design/tokens.json — the same file the iOS and Android apps are generated
   from. Nothing here names a pigment or a point size; if a value looks wrong,
   fix the JSON and regenerate. Every page links `tokens.generated.css` before
   this file — a second <link>, not an @import, which the browser would only
   discover after this stylesheet had already downloaded.

   The direction is Conservatory (`.interface-design/system.md`): a glasshouse
   at dawn. Pale luminous air that follows the clock, one living green, Petrona
   for the plant's voice, glass only where chrome floats over the plant.

   Light and dark are equal citizens, as they are in the app, whose Appearance
   default is System.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Web-only additions to the token set.

   Line heights: iOS `lineSpacing` is leading *added* to the face's own, which
   CSS has no equivalent for, so the roles' line heights are set here. Running
   text gets more air than a phone screen needs — a 68ch measure asks for it.
   -------------------------------------------------------------------------- */

:root {
  --lh-display: 1.14;
  --lh-body: 1.62;
  --lh-tight: 1.4;

  /* Page measures. The header is a fixed, known height rather than sticky: a
     sticky header still occupies flow space, which pushed the full-height scroll
     stage 60px below the fold until the first scroll. Everything that isn't the
     stage adds this back as top padding. */
  --header-h: calc(var(--lk-target) + var(--lk-space-stone));
  --measure-page: 1080px;
  --measure-prose: 68ch;

  /* The air, behind the transparent plant. js/atmosphere.js moves these
     through the hour from the generated keyframes; the values here are the
     `day` keyframe, so the page is already the right colour with JS off. */
  --air-top: #E0EEE7;
  --air-mid: #EFF6F1;
  --air-bottom: #F2F6F3;
  --air-glow: #F8FCF6;
}

@media (prefers-color-scheme: dark) {
  :root {
    --air-top: #0E1F1C;
    --air-mid: #11201A;
    --air-bottom: #0E1613;
    --air-glow: #17302A;
  }
}

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

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font: var(--lk-type-body-weight) var(--lk-type-body-size) var(--lk-type-body-family);
  line-height: var(--lh-body);
  color: var(--lk-text-primary);
  background: var(--lk-surface-canvas);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Serif is the plant's voice: names, headlines, titles, observations.
   Never buttons, body copy or labels. */
h1, h2, h3 {
  font-family: var(--lk-type-headline-family);
  font-weight: var(--lk-type-headline-weight);
  line-height: var(--lh-display);
  letter-spacing: var(--lk-type-headline-tracking);
  margin: 0 0 var(--lk-space-moss);
  text-wrap: balance;
}

h1 { font-size: clamp(2.3rem, 6vw, 3.9rem); }
h2 { font-size: clamp(1.75rem, 4vw, 2.6rem); }

h3 {
  font-size: var(--lk-type-title-size);
  font-weight: var(--lk-type-title-weight);
  letter-spacing: var(--lk-type-title-tracking);
}

p {
  margin: 0 0 1em;
}

a {
  color: var(--lk-accent-text);
  text-decoration: none;
}

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

:focus-visible {
  outline: 2px solid var(--lk-accent-fill);
  outline-offset: 3px;
  border-radius: var(--lk-radius-xs);
}

img, svg {
  max-width: 100%;
  height: auto;
}

.container {
  max-width: var(--measure-page);
  margin: 0 auto;
  padding: 0 var(--lk-space-path);
}

.muted {
  color: var(--lk-text-secondary);
}

/* A label over a group — sentence case, like the app's. Title case reads stiffly
   beside a serif, and the old uppercase-mono eyebrows belonged to the palette
   that Conservatory replaced. */
.eyebrow {
  display: block;
  font-family: var(--lk-type-section-label-family);
  font-size: var(--lk-type-section-label-size);
  font-weight: var(--lk-type-section-label-weight);
  color: var(--lk-accent-text);
  margin-bottom: var(--lk-space-pebble);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--lk-surface-raised);
  color: var(--lk-text-primary);
  padding: var(--lk-space-moss) var(--lk-space-stone);
  border-radius: 0 0 var(--lk-radius-md) 0;
  box-shadow: var(--lk-shadow-floating);
}

.skip-link:focus {
  left: 0;
}

/* --------------------------------------------------------------------------
   Header — glass, because it floats over the plant on the landing page
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--header-h);
  z-index: 50;
  background: var(--lk-surface-chrome-solid);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  backdrop-filter: blur(20px) saturate(1.1);
  border-bottom: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  gap: var(--lk-space-moss);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--lk-space-pebble);
  font-family: var(--lk-type-plant-name-family);
  font-weight: var(--lk-type-plant-name-weight);
  font-size: 1.3rem;
  letter-spacing: var(--lk-type-plant-name-tracking);
  color: var(--lk-text-primary);
}

.wordmark:hover {
  text-decoration: none;
}

/* At or below 40px the mark uses its small cut — four branches, no forks. */
.wordmark img {
  width: 28px;
  height: 28px;
  flex: none;
}

/* Secondary button, per the app's button family: capsule, hairline, no fill. */
.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--lk-target);
  padding: 0 var(--lk-space-stone);
  font-family: var(--lk-type-button-family);
  font-size: var(--lk-type-button-size);
  font-weight: var(--lk-type-button-weight);
  color: var(--lk-accent-text);
  background: transparent;
  border: var(--lk-stroke-hairline) solid var(--lk-border-control);
  border-radius: var(--lk-radius-full);
  transition: background var(--lk-dur-micro) var(--lk-ease-micro),
    border-color var(--lk-dur-micro) var(--lk-ease-micro);
}

.btn-secondary:hover {
  text-decoration: none;
  background: var(--lk-accent-subtle);
  border-color: var(--lk-border-selected);
}

/* Everything pressable has a pressed state. Nothing in Lumaki bounces, so the
   scale is small and the curve is critically damped. */
.btn-secondary:active {
  transform: scale(0.975);
}

/* --------------------------------------------------------------------------
   App Store CTA — Apple's badge, so its own black and radius stay untouched
   -------------------------------------------------------------------------- */

.btn-appstore {
  display: inline-block;
  line-height: 0;
  border-radius: 9px; /* design-literal: Apple's badge artwork has its own corner radius */
  transition: transform var(--lk-dur-micro) var(--lk-ease-micro);
}

.btn-appstore:hover {
  text-decoration: none;
  transform: translateY(-2px);
}

.btn-appstore:active {
  transform: scale(0.975);
}

.btn-appstore .appstore-badge {
  height: 50px;
  width: auto;
  display: block;
}

.cta-microcopy {
  margin-top: var(--lk-space-moss);
  font-family: var(--lk-type-caption-family);
  font-size: var(--lk-type-caption-size);
  color: var(--lk-text-tertiary);
}

/* --------------------------------------------------------------------------
   Sections on the canvas
   -------------------------------------------------------------------------- */

.section {
  padding: clamp(var(--lk-space-garden), 10vh, 110px) 0;
}

.section-sunken {
  background: var(--lk-surface-sunken);
  border-top: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  border-bottom: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
}

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(var(--lk-space-clearing), 5vh, var(--lk-space-garden));
}

.section-head p {
  color: var(--lk-text-secondary);
  margin-bottom: 0;
}

.section-note {
  margin-top: var(--lk-space-path);
  max-width: 62ch;
  color: var(--lk-text-tertiary);
  font-size: var(--lk-type-callout-size);
}

/* --------------------------------------------------------------------------
   Cards — solid, radius lg, lifted by a contact shadow in light and by
   surface colour in dark
   -------------------------------------------------------------------------- */

.card {
  background: var(--lk-surface-raised);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  border-radius: var(--lk-radius-lg);
  box-shadow: var(--lk-shadow-card);
  padding: var(--lk-space-path);
}

.card h3 {
  margin-bottom: var(--lk-space-pebble);
}

.card p {
  margin: 0;
  color: var(--lk-text-secondary);
  font-size: var(--lk-type-callout-size);
  line-height: var(--lh-body);
}

/* Column counts are fixed rather than `auto-fit`, because both grids hold a
   number the reader is meant to take in whole — six things the app does, eight
   parts of the plant — and auto-fit leaves whichever row is short hanging. */
.grid {
  display: grid;
  gap: var(--lk-space-stone);
  grid-template-columns: 1fr;
}

@media (min-width: 620px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 940px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .grid-parts { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------------------
   Scroll stage — one sticky live plant that grows through the acts.

   The plant's canvas is transparent (the renderer clears to alpha 0), exactly
   as in the app, so the air the stage paints is the plant's sky. That air
   follows the clock: see js/atmosphere.js.
   -------------------------------------------------------------------------- */

.stage {
  position: relative;
  /* One viewport of scroll per act — six of them, counting the hero.
     js/stage.js reads this height rather than assuming it. */
  height: 600vh;
  background: var(--air-bottom);
}

.stage-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  /* The vertical gradient under an elliptical glow behind the plant —
     `ui.backdrop.atmosphere`'s geometry, in CSS. */
  background:
    radial-gradient(ellipse 47.5% 17% at 50% 76%, var(--air-glow), transparent 72%),
    linear-gradient(to bottom, var(--air-top) 0%, var(--air-mid) 58%, var(--air-bottom) 100%);
  transition: background var(--lk-dur-slow-fade) var(--lk-ease-slow-fade);
}

/* The renderer fits its plant to whatever box it is given, so the box *is* the
   composition. An absolutely positioned iframe with `width: auto` falls back to
   its intrinsic 300×150, so the inset has to be subtracted explicitly rather
   than left to `inset: 0`. */
.stage-plant {
  position: absolute;
  top: 0;
  left: var(--plant-left, 0px);
  width: calc(100% - var(--plant-left, 0px));
  height: calc(100% - var(--plant-bottom, 0px));
  border: 0;
  pointer-events: none; /* never capture scroll / touch */
  /* The iframe paints nothing of its own; the stage's air shows through. */
  background: transparent;
  color-scheme: normal;
}

.stage-fallback {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Wide: the panes sit against the left edge, so the plant takes the space to
   their right rather than the two fighting over the middle. */
@media (min-width: 1000px) {
  .stage-sticky {
    --plant-left: clamp(140px, 17vw, 280px);
  }
}

/* Narrow: the panes stack at the foot, so the plant takes the space above them.
   Without this the seed is framed dead centre — behind the copy. */
@media (max-width: 999px) {
  .stage-sticky {
    --plant-bottom: 38%;
  }
}

.stage-fallback {
  display: none;
  align-items: center;
  justify-content: center;
}

.stage-fallback svg {
  width: min(70vw, 360px);
  height: auto;
}

.stage-overlays {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.act {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(var(--lk-space-moss));
  pointer-events: none;
  transition: opacity var(--lk-dur-plant-reveal) var(--lk-ease-plant-reveal),
    transform var(--lk-dur-plant-reveal) var(--lk-ease-plant-reveal),
    visibility var(--lk-dur-plant-reveal) step-end;
}

.act.is-active {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition: opacity var(--lk-dur-plant-reveal) var(--lk-ease-plant-reveal),
    transform var(--lk-dur-plant-reveal) var(--lk-ease-plant-reveal),
    visibility 0s;
}

.act-inner,
.act-card {
  margin-left: clamp(var(--lk-space-path), 8vw, 120px);
  margin-right: var(--lk-space-path);
  max-width: 34rem;
}

/* Text never sits directly on the plant. The hero headline is the one place it
   would, so it gets the same glass panel the acts use — just a wider one. */
.act-inner,
.act-card {
  /* `chromeSolid`, not `chrome`: the app's glass floats over a plant on a phone,
     where it is mostly sky behind it. A full-bleed plant puts soil behind a whole
     pane, and the audit rule is the same one onboarding follows — copy sits on a
     scrim that is opaque enough above where the text begins. */
  background: var(--lk-surface-chrome-solid);
  -webkit-backdrop-filter: blur(28px) saturate(1.1);
  backdrop-filter: blur(28px) saturate(1.1);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  border-radius: var(--lk-radius-xl);
  box-shadow: var(--lk-shadow-floating);
  padding: var(--lk-space-clearing);
}

.act-card {
  max-width: 30rem;
}

.act-inner .subhead {
  font-size: clamp(var(--lk-type-body-size), 2vw, 1.2rem);
  color: var(--lk-text-secondary);
  max-width: 32em;
  margin-bottom: var(--lk-space-path);
}

.act-card p:last-child {
  margin-bottom: 0;
}

.act .btn-appstore {
  margin-top: var(--lk-space-pebble);
}

/* Reduce Transparency: glass becomes a solid raised surface. */
@media (prefers-reduced-transparency: reduce) {
  .site-header,
  .act-inner,
  .act-card {
    background: var(--lk-surface-raised);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

.scroll-hint {
  margin: var(--lk-space-path) 0 0;
  font-family: var(--lk-type-caption-family);
  font-size: var(--lk-type-caption-size);
  color: var(--lk-text-tertiary);
  animation: breathe var(--lk-dur-breathing) var(--lk-ease-breathing) infinite;
}

@keyframes breathe {
  0%, 100% { opacity: 0.55; transform: translateY(0); }
  50% { opacity: 1; transform: translateY(3px); }
}

/* Growth rail along the foot of the stage. */
.stage-rail {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: var(--lk-border-hairline);
  z-index: 3;
}

.stage-rail span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--lk-accent-fill);
  transition: width 120ms linear;
}

/* The signals act: pills over the receding plant, so they sit on glass too. */
.act-signals .act-card {
  max-width: 44rem;
  max-height: 84vh;
  overflow-y: auto;
}

/* Narrow screens stack: the pane sits at the foot of the frame, under the plant.
   The bottom gap is padding on the act rather than a margin on the pane, so it is
   part of the flex container's own box and can't be swallowed by the alignment. */
@media (max-width: 760px) {
  .act {
    align-items: flex-end;
    padding-bottom: var(--lk-space-clearing);
  }

  .act-inner,
  .act-card {
    margin-left: var(--lk-space-stone);
    margin-right: var(--lk-space-stone);
    max-width: none;
    max-height: calc(100vh - var(--lk-space-garden) - var(--lk-space-clearing));
    overflow-y: auto;
    padding: var(--lk-space-path);
  }
}

/* --------------------------------------------------------------------------
   Pills — the signals list and the connected-app logos
   -------------------------------------------------------------------------- */

.pills {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--lk-space-pebble);
}

.pills li {
  display: inline-flex;
  align-items: center;
  gap: var(--lk-space-pebble);
  font-size: var(--lk-type-callout-size);
  color: var(--lk-text-secondary);
  background: var(--lk-surface-raised);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  border-radius: var(--lk-radius-full);
  padding: var(--lk-space-pebble) var(--lk-space-stone);
}

/* On glass, a raised pill would read as a second pane. */
.act .pills li {
  background: var(--lk-surface-raised);
  box-shadow: var(--lk-shadow-card);
}

.pills-signals li::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--lk-accent-fill);
  flex: none;
}

.pills-logos li img {
  width: 24px;
  height: 24px;
  border-radius: var(--lk-radius-xs);
  object-fit: contain;
  flex: none;
}

.pills-label {
  font-family: var(--lk-type-section-label-family);
  font-size: var(--lk-type-section-label-size);
  font-weight: var(--lk-type-section-label-weight);
  color: var(--lk-text-tertiary);
  margin-bottom: var(--lk-space-moss);
}

/* --------------------------------------------------------------------------
   What grows what — the mapping, which only marketing ever states
   -------------------------------------------------------------------------- */

.part,
.usecase {
  display: flex;
  flex-direction: column;
}

.part h3 {
  font-family: var(--lk-type-plant-name-family);
  font-weight: var(--lk-type-plant-name-weight);
  font-size: var(--lk-type-plant-name-size);
  letter-spacing: var(--lk-type-plant-name-tracking);
  margin-bottom: var(--lk-space-grain);
}

/* The `sectionLabel` role, not `data`: mono is for pronunciations and figures,
   and these are words. */
.part .part-source {
  font-family: var(--lk-type-section-label-family);
  font-size: var(--lk-type-section-label-size);
  font-weight: var(--lk-type-section-label-weight);
  color: var(--lk-accent-text);
  margin-bottom: var(--lk-space-moss);
}

/* --------------------------------------------------------------------------
   Plant styles — a live plant beside a radio group of the four styles

   The list is content before it is a control: with no JS it reads as four
   named styles with their descriptions, which is what the section is for.
   js/styles.js upgrades the `li`s into buttons and adds the frame.
   -------------------------------------------------------------------------- */

.styles {
  display: grid;
  gap: var(--lk-space-path);
  align-items: center;
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .styles {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--lk-space-garden);
  }
}

/* The plant is transparent, so the stage paints the hour's air behind it here
   too — the same glasshouse the scroll stage sits in. */
.styles-stage {
  position: relative;
  aspect-ratio: 1 / 1;
  max-height: 60vh;
  border-radius: var(--lk-radius-lg);
  overflow: hidden;
  background:
    radial-gradient(ellipse 60% 24% at 50% 76%, var(--air-glow), transparent 72%),
    linear-gradient(to bottom, var(--air-top) 0%, var(--air-mid) 58%, var(--air-bottom) 100%);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
}

/* Until the renderer answers, the frame is empty air rather than a broken box. */
.styles-plant {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
  color-scheme: normal;
  opacity: 0;
  transition: opacity var(--lk-dur-plant-reveal) var(--lk-ease-plant-reveal);
}

.styles-stage[data-ready="true"] .styles-plant {
  opacity: 1;
}

/* Switching rebuilds the geometry, which takes a moment on a phone. Dimming says
   something is happening; it beats a frame that looks stuck. */
.styles-stage[data-switching="true"] .styles-plant {
  opacity: 0.35;
}

.styles-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--lk-space-moss);
}

.styles-list li {
  margin: 0;
}

/* Before the upgrade the items are plain text; after it they are buttons. */
.styles-list:not(.is-interactive) li {
  padding: var(--lk-space-stone);
  border-radius: var(--lk-radius-lg);
  background: var(--lk-surface-raised);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  box-shadow: var(--lk-shadow-card);
}

.style-option {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--lk-space-grain) var(--lk-space-moss);
  width: 100%;
  min-height: var(--lk-target);
  padding: var(--lk-space-stone);
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border-radius: var(--lk-radius-lg);
  background: var(--lk-surface-raised);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  box-shadow: var(--lk-shadow-card);
  transition: border-color var(--lk-dur-micro) var(--lk-ease-micro),
    background var(--lk-dur-micro) var(--lk-ease-micro),
    transform var(--lk-dur-micro) var(--lk-ease-micro);
}

.style-option:hover {
  border-color: var(--lk-border-control);
}

.style-option:active {
  transform: scale(0.99);
}

/* Selection is the one accent, and carries a second cue beside colour: the
   border thickens, so it does not rely on hue alone. */
.style-option[aria-checked="true"] {
  border-color: var(--lk-border-selected);
  box-shadow: var(--lk-shadow-card), inset 0 0 0 1px var(--lk-border-selected);
  background: var(--lk-accent-subtle);
}

/* Placed explicitly: in DOM order the access chip would fall under the
   description, where it reads as a footnote rather than a label on the name. */
.style-name {
  grid-area: 1 / 1;
  font-family: var(--lk-type-title-family);
  font-weight: var(--lk-type-title-weight);
  font-size: var(--lk-type-title-size);
  letter-spacing: var(--lk-type-title-tracking);
  line-height: var(--lh-tight);
}

.style-sub {
  grid-area: 2 / 1 / 3 / 3;
  color: var(--lk-text-secondary);
  font-size: var(--lk-type-callout-size);
  line-height: var(--lh-body);
}

.style-access {
  grid-area: 1 / 2;
  align-self: center;
  justify-self: end;
  font-family: var(--lk-type-caption-family);
  font-size: var(--lk-type-caption-size);
  color: var(--lk-text-tertiary);
}

/* --------------------------------------------------------------------------
   Pricing
   -------------------------------------------------------------------------- */

.plans {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--lk-space-moss);
  margin: 0 0 var(--lk-space-path);
  padding: 0;
  list-style: none;
}

.plan {
  background: var(--lk-surface-raised);
  border: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  border-radius: var(--lk-radius-md);
  box-shadow: var(--lk-shadow-card);
  padding: var(--lk-space-moss) var(--lk-space-stone);
}

.plan-name {
  display: flex;
  align-items: center;
  gap: var(--lk-space-pebble);
  font-family: var(--lk-type-section-label-family);
  font-size: var(--lk-type-section-label-size);
  font-weight: var(--lk-type-section-label-weight);
  color: var(--lk-text-secondary);
  margin-bottom: var(--lk-space-grain);
}

.plan-price {
  font-family: var(--lk-type-data-large-family);
  font-size: var(--lk-type-data-large-size);
  font-weight: var(--lk-type-data-large-weight);
  font-variant-numeric: tabular-nums;
  color: var(--lk-text-primary);
}

.plan-price span {
  font-size: var(--lk-type-callout-size);
  font-weight: var(--lk-type-callout-weight);
  color: var(--lk-text-tertiary);
}

.plan-note {
  margin: var(--lk-space-pebble) 0 0;
  font-size: var(--lk-type-caption-size);
  color: var(--lk-text-tertiary);
}

/* The one earned-moment colour. Gold is rare on purpose. */
.badge {
  display: inline-block;
  font-family: var(--lk-type-badge-family);
  font-size: var(--lk-type-badge-size);
  font-weight: var(--lk-type-badge-weight);
  color: var(--lk-status-on-highlight);
  background: var(--lk-status-highlight);
  border-radius: var(--lk-radius-full);
  padding: var(--lk-space-grain) var(--lk-space-pebble);
}

/* --------------------------------------------------------------------------
   Use cases
   -------------------------------------------------------------------------- */

.usecase-tag {
  display: inline-block;
  align-self: flex-start;
  font-family: var(--lk-type-badge-family);
  font-size: var(--lk-type-badge-size);
  font-weight: var(--lk-type-badge-weight);
  color: var(--lk-accent-text);
  background: var(--lk-accent-subtle);
  border-radius: var(--lk-radius-full);
  padding: var(--lk-space-grain) var(--lk-space-moss);
  margin-bottom: var(--lk-space-moss);
}

/* Kept unused on purpose: the invented testimonials were deleted, and real beta
   quotes go back in as `<blockquote class="testimonial">` inside a use-case card.
   See website/TODO.md. */
.testimonial {
  margin: auto 0 0;
  padding-top: var(--lk-space-stone);
  border-top: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
}

.testimonial p {
  font-family: var(--lk-type-observation-family);
  font-style: italic;
  color: var(--lk-text-secondary);
  margin-bottom: var(--lk-space-pebble);
}

.testimonial cite {
  font-family: var(--lk-type-caption-family);
  font-style: normal;
  font-size: var(--lk-type-caption-size);
  color: var(--lk-text-tertiary);
}

/* --------------------------------------------------------------------------
   Final CTA band
   -------------------------------------------------------------------------- */

.cta-band {
  text-align: center;
  padding: clamp(var(--lk-space-horizon), 12vh, 130px) 0;
  background:
    radial-gradient(ellipse 60% 50% at 50% 100%, var(--air-glow), transparent 75%),
    var(--lk-surface-canvas);
}

.cta-band .glyph {
  width: 56px;
  height: 56px;
  margin: 0 auto var(--lk-space-stone);
  display: block;
}

.cta-band h2 {
  margin-bottom: var(--lk-space-path);
}

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

.site-footer {
  border-top: var(--lk-stroke-hairline) solid var(--lk-border-hairline);
  padding: var(--lk-space-garden) 0;
  font-size: var(--lk-type-caption-size);
  color: var(--lk-text-tertiary);
}

.site-footer .footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lk-space-pebble) var(--lk-space-path);
  margin: 0 0 var(--lk-space-stone);
  padding: 0;
  list-style: none;
}

.site-footer a {
  color: var(--lk-text-secondary);
}

.site-footer p {
  margin: 0 0 var(--lk-space-grain);
}

.site-footer .meaning {
  font-family: var(--lk-type-observation-family);
  font-size: var(--lk-type-observation-size);
  font-style: italic;
  color: var(--lk-text-secondary);
  margin-bottom: var(--lk-space-pebble);
}

/* --------------------------------------------------------------------------
   Prose pages (privacy / terms / support) and 404
   -------------------------------------------------------------------------- */

.prose {
  max-width: var(--measure-prose);
  padding-top: calc(var(--header-h) + clamp(var(--lk-space-clearing), 7vh, 72px));
  padding-bottom: clamp(var(--lk-space-garden), 10vh, 110px);
}

.prose h1 {
  font-size: clamp(1.9rem, 4.5vw, 2.6rem);
}

.prose h2 {
  font-size: var(--lk-type-title-size);
  font-weight: var(--lk-type-title-weight);
  margin-top: 2em;
}

.prose h3 {
  margin-top: 1.6em;
}

.prose ul {
  padding-left: 1.2em;
}

.prose li {
  margin-bottom: 0.4em;
}

.prose .meta-line {
  color: var(--lk-text-tertiary);
  font-size: var(--lk-type-callout-size);
  margin-bottom: 2.2em;
}

.error-page {
  min-height: 55vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: calc(var(--header-h) + var(--lk-space-horizon)) var(--lk-space-path) var(--lk-space-horizon);
}

.error-page img {
  width: 64px;
  height: 64px;
  margin-bottom: var(--lk-space-stone);
  opacity: 0.55;
}

/* --------------------------------------------------------------------------
   Reduce Motion: reveals cross-fade rather than travel, and nothing pulses.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition-duration: 1ms !important;
  }

  .act,
  .act.is-active {
    transition: opacity var(--lk-dur-gentle) var(--lk-ease-gentle) !important;
    transform: none;
  }

  .btn-appstore:hover,
  .btn-secondary:active,
  .btn-appstore:active {
    transform: none;
  }
}
