/* ===========================================================================
   Lippukone — public site
   ===========================================================================

   Hand-written, no build step (PUBLIC_SITE_PLAN.md D1). Nothing else on this
   host ships CSS, so class names are plain rather than prefixed, and the
   cascade is short enough to read top to bottom.

   Dark is the default and light is the override, which is the opposite of the
   four SPAs. That is deliberate: this page is the product's first impression
   and it is designed dark, while an application someone stares at for a
   working day defaults to light. The colour values are the same slate and
   teal the apps use (frontend/shared/src/theme/index.ts), so a buyer crossing
   to the wallet does not feel handed to a different company.

   Sections:
     1. Tokens
     2. Reset and base
     3. Typography
     4. Layout primitives
     5. Buttons and controls
     6. Header and navigation
     7. Hero and page hero
     8. Footer
     9. Motion and print
   =========================================================================== */

/* --- 1. Tokens ---------------------------------------------------------- */

:root {
  color-scheme: dark;

  --bg: #0b1120;
  --bg-raised: #111827;
  --bg-elevated: #1e293b;

  --ink: #e2e8f0;
  --ink-strong: #f8fafc;
  --ink-muted: #94a3b8;

  --line: rgba(148, 163, 184, 0.16);
  --line-strong: rgba(148, 163, 184, 0.28);

  --accent: #2dd4bf;
  --accent-ink: #04231f;
  --accent-soft: rgba(45, 212, 191, 0.14);
  --accent-2: #8b5cf6;

  /* Used on the hero title and on decorative glows only. Never on body text:
     gradient-clipped paragraphs lose contrast at the pale end and stop being
     selectable-looking. */
  --gradient: linear-gradient(115deg, #2dd4bf 0%, #60a5fa 52%, #8b5cf6 100%);

  --radius: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --shadow: 0 1px 2px rgba(2, 6, 23, 0.4), 0 18px 48px -28px rgba(2, 6, 23, 0.9);

  --font-body: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-display: 'Space Grotesk', var(--font-body);

  --wrap: 1120px;
  --gutter: 20px;

  --header-height: 68px;
}

/* The light theme is a full re-declaration rather than a few overrides, so
   every token has one obvious value per theme and neither inherits a colour
   that only made sense in the other. */
:root[data-theme='light'] {
  color-scheme: light;

  --bg: #f8fafc;
  --bg-raised: #ffffff;
  --bg-elevated: #f1f5f9;

  --ink: #0f172a;
  --ink-strong: #020617;
  --ink-muted: #52627a;

  --line: #e2e8f0;
  --line-strong: #cbd5e1;

  --accent: #0d9488;
  --accent-ink: #ffffff;
  --accent-soft: rgba(13, 148, 136, 0.1);
  --accent-2: #7c3aed;

  --gradient: linear-gradient(115deg, #0d9488 0%, #2563eb 52%, #7c3aed 100%);

  --shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 18px 48px -30px rgba(15, 23, 42, 0.28);
}

/* Someone whose OS says light and who has never touched the toggle gets the
   light theme. theme-boot.js stamps data-theme only for an explicit choice,
   so this is what decides it for everyone else. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    color-scheme: light;

    --bg: #f8fafc;
    --bg-raised: #ffffff;
    --bg-elevated: #f1f5f9;

    --ink: #0f172a;
    --ink-strong: #020617;
    --ink-muted: #52627a;

    --line: #e2e8f0;
    --line-strong: #cbd5e1;

    --accent: #0d9488;
    --accent-ink: #ffffff;
    --accent-soft: rgba(13, 148, 136, 0.1);
    --accent-2: #7c3aed;

    --gradient: linear-gradient(115deg, #0d9488 0%, #2563eb 52%, #7c3aed 100%);

    --shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 18px 48px -30px rgba(15, 23, 42, 0.28);
  }
}

/* --- 2. Reset and base --------------------------------------------------- */

@font-face {
  font-family: 'Inter';
  src: url('/site/fonts/inter.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2122, U+2212;
}

@font-face {
  font-family: 'Space Grotesk';
  src: url('/site/fonts/space-grotesk.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2122, U+2212;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* A sticky header would otherwise cover the top of whatever an in-page link
     jumps to. */
  scroll-padding-top: calc(var(--header-height) + 16px);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a {
  color: inherit;
}

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 18px;
  background: var(--bg-raised);
  color: var(--ink-strong);
  border: 1px solid var(--line-strong);
  border-radius: 0 0 var(--radius) 0;
  text-decoration: none;
  font-weight: 600;
}

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

/* --- 3. Typography ------------------------------------------------------- */

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--ink-strong);
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.25rem, 6vw, 3.75rem);
}

h2 {
  font-size: clamp(1.65rem, 3.4vw, 2.4rem);
}

h3 {
  font-size: 1.1rem;
  letter-spacing: -0.015em;
}

p {
  margin: 0;
}

.eyebrow {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 18px;
}

.lede {
  font-size: clamp(1.0625rem, 1.6vw, 1.25rem);
  color: var(--ink-muted);
  /* Measure, not width: long lines are hard to track back from at any screen
     size, and this is the one number that decides whether a page reads. */
  max-width: 58ch;
}

/* --- 4. Layout primitives ------------------------------------------------ */

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

main {
  /* Anything the page ever adds sideways scrolls inside its own container;
     the document itself must not. */
  overflow-x: clip;
}

/* --- 5. Buttons and controls --------------------------------------------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font: inherit;
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease,
    transform 0.18s ease;
}

.button--lg {
  padding: 14px 26px;
  font-size: 1rem;
}

.button--primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.button--primary:hover {
  transform: translateY(-1px);
  /* Lightening the accent would drift off-brand at every hover; a soft ring
     reads as raised without changing the colour. */
  box-shadow: 0 0 0 4px var(--accent-soft);
}

.button--ghost {
  border-color: var(--line-strong);
  color: var(--ink-strong);
  background: transparent;
}

.button--ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease;
}

.icon-button:hover {
  color: var(--ink-strong);
  border-color: var(--line-strong);
}

.icon-button svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* One button, two glyphs: the moon offers dark, the sun offers light, and
   which one is showing is decided by the theme in force. */
.icon-button__moon {
  display: none;
}

:root[data-theme='light'] .icon-button__sun {
  display: none;
}

:root[data-theme='light'] .icon-button__moon {
  display: inline-block;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .icon-button__sun {
    display: none;
  }

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

/* --- 6. Header and navigation -------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: var(--header-height);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: -0.02em;
  color: var(--ink-strong);
  text-decoration: none;
  flex: none;
}

.mark {
  width: 24px;
  height: 24px;
  flex: none;
}

.nav {
  display: none;
  gap: 26px;
  margin-right: auto;
}

.nav__link {
  color: var(--ink-muted);
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  transition: color 0.18s ease;
}

.nav__link:hover,
.nav__link[aria-current='page'] {
  color: var(--ink-strong);
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.langs {
  display: none;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
}

.langs__link {
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  text-decoration: none;
}

.langs__link:hover {
  color: var(--ink-strong);
}

.langs__link[aria-current='true'] {
  background: var(--bg-elevated);
  color: var(--ink-strong);
}

.site-header__wallet,
.site-header__cta {
  display: none;
}

.nav-toggle {
  display: inline-flex;
}

@media (min-width: 700px) {
  .langs {
    display: inline-flex;
  }
}

@media (min-width: 900px) {
  .nav {
    display: flex;
  }

  .site-header__wallet {
    display: inline-flex;
  }

  .nav-toggle {
    display: none;
  }
}

@media (min-width: 1040px) {
  .site-header__cta {
    display: inline-flex;
  }
}

.site-menu {
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
}

.site-menu__inner {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-block: 12px 20px;
}

.site-menu__link {
  padding: 11px 0;
  color: var(--ink);
  text-decoration: none;
  font-size: 1.0625rem;
  font-weight: 500;
  border-bottom: 1px solid var(--line);
}

.site-menu__cta {
  margin-top: 14px;
  align-self: flex-start;
}

/* --- 7. Hero and page hero ----------------------------------------------- */

.hero {
  position: relative;
  isolation: isolate;
  border-bottom: 1px solid var(--line);
  overflow: clip;
}

/* Positioned in pixels from the top rather than a percentage: the hero's height changes with
   its own content, and a percentage offset pushed most of the colour above the fold on a wide
   screen — visible as a band behind the header instead of a field behind the headline. */
.hero__glow {
  position: absolute;
  inset: -120px -15% auto -15%;
  height: 780px;
  z-index: -1;
  background:
    radial-gradient(38% 46% at 24% 46%, color-mix(in srgb, var(--accent) 36%, transparent), transparent 70%),
    radial-gradient(34% 42% at 76% 30%, color-mix(in srgb, var(--accent-2) 32%, transparent), transparent 72%);
  filter: blur(42px);
  opacity: 0.85;
}

:root[data-theme='light'] .hero__glow {
  opacity: 0.5;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .hero__glow {
    opacity: 0.5;
  }
}

.hero__inner {
  padding-block: clamp(64px, 11vw, 120px) clamp(56px, 9vw, 104px);
}

.hero__title {
  /* The one place the gradient touches type. Background-clip needs a
     transparent fill, and a browser that supports neither simply renders the
     heading in --ink-strong, which is the declared colour above it. */
  max-width: 17ch;
  background: var(--gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding-bottom: 0.08em;
}

.hero__lede {
  margin-top: 22px;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 34px;
}

.page-hero {
  border-bottom: 1px solid var(--line);
}

.page-hero__inner {
  padding-block: clamp(48px, 8vw, 88px);
}

.page-hero .lede {
  margin-top: 20px;
}

/* --- 7b. Sections and content blocks -------------------------------------- */

.section,
.band {
  padding-block: clamp(56px, 8vw, 96px);
}

/* Alternating bands give a long page a rhythm without drawing a line every time. */
.band {
  background: var(--bg-raised);
  border-block: 1px solid var(--line);
}

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(28px, 4vw, 44px);
}

.section-head .lede {
  margin-top: 14px;
}

.wrap--narrow {
  max-width: 760px;
}

.prose p {
  color: var(--ink-muted);
  max-width: 68ch;
  margin-top: 16px;
  font-size: 1.0625rem;
}

/* Fact chips under the hero. */
.facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}

.facts__item {
  padding: 7px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  font-size: 0.875rem;
  color: var(--ink-muted);
  background: color-mix(in srgb, var(--bg-raised) 60%, transparent);
}

/* Text beside an illustration, alternating sides on wide screens. */
.feature-row {
  padding-block: clamp(48px, 7vw, 84px);
}

.feature-row__inner {
  display: grid;
  gap: clamp(28px, 5vw, 56px);
  align-items: center;
}

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

  /* Source order stays text-then-art on every row, so a narrow screen and a screen reader
     always get the heading before its picture; only the wide layout swaps them. */
  .feature-row--reverse .feature-row__text {
    order: 2;
  }
}

.feature-row__text h2 {
  margin-bottom: 16px;
}

.feature-row__text .lede {
  margin-bottom: 22px;
}

.checklist {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-muted);
}

.checklist--two {
  gap: 12px 28px;
}

@media (min-width: 640px) {
  .checklist--two {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.checklist li {
  position: relative;
  padding-left: 30px;
}

/* Drawn rather than an emoji or an icon font: one rule, no request, and it inherits the
   accent in both themes. */
.checklist li::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 0.55em;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

.code-card {
  margin: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.code-card pre {
  margin: 0;
  padding: 22px;
  /* Wrapped rather than scrolled. This snippet is the one thing on the page a reader is meant
     to copy, and a line clipped mid-attribute behind a scrollbar nobody notices reads as a
     broken card — the opposite of "this is the whole integration". */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8125rem;
  line-height: 1.8;
  color: var(--ink);
  tab-size: 2;
}

.code-card figcaption {
  padding: 14px 22px;
  border-top: 1px solid var(--line);
  background: var(--bg-elevated);
  color: var(--ink-muted);
  font-size: 0.875rem;
}

.card-grid {
  display: grid;
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}

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

  .card-grid--four {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.card {
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  transition: border-color 0.18s ease, transform 0.18s ease;
}

.band .card {
  background: var(--bg);
}

.card:hover {
  border-color: var(--line-strong);
}

.card h3 {
  margin-bottom: 8px;
}

.card p {
  color: var(--ink-muted);
  font-size: 0.9375rem;
}

.steps {
  display: grid;
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

@media (min-width: 860px) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 28px;
  }
}

.steps__item {
  padding-top: 20px;
  border-top: 2px solid var(--line-strong);
}

.steps__number {
  display: block;
  font-family: var(--font-display);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--accent);
  margin-bottom: 10px;
}

.steps__item h3 {
  margin-bottom: 8px;
}

.steps__item p {
  color: var(--ink-muted);
  font-size: 0.9375rem;
}

.faq {
  border-top: 1px solid var(--line);
}

.faq__item {
  border-bottom: 1px solid var(--line);
}

.faq__item summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 0;
  cursor: pointer;
  font-weight: 600;
  color: var(--ink-strong);
  list-style: none;
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

/* A plus that becomes a minus. Two pseudo-elements rather than an icon, so it cannot get out
   of step with the element's open state. */
.faq__item summary::after {
  content: '+';
  flex: none;
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1;
  color: var(--accent);
}

.faq__item[open] summary::after {
  content: '−';
}

.faq__item p {
  padding-bottom: 22px;
  color: var(--ink-muted);
  max-width: 68ch;
}

.cta-band {
  padding-block: clamp(48px, 7vw, 80px);
  border-top: 1px solid var(--line);
  background:
    radial-gradient(60% 140% at 12% 50%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%),
    var(--bg-raised);
}

.cta-band__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  align-items: center;
  justify-content: space-between;
}

.cta-band__body {
  margin-top: 12px;
}

/* The band's two doors: applying is the button, the walkthrough conversation stays a link —
   stacked so there is never a question about which one is the ask. */
.cta-band__actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
}

.cta-band__secondary {
  color: var(--ink-muted);
  text-underline-offset: 3px;
}

.cta-band__secondary:hover {
  color: var(--accent);
}

/* The features page's four stages: a sticky-ish label column beside the detail. */
.stage__inner {
  display: grid;
  gap: 20px clamp(28px, 5vw, 64px);
}

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

.stage__body .lede {
  margin-bottom: 20px;
}

/* Pricing: what is included, and why there is no figure beside it. */
.pricing {
  display: grid;
  gap: clamp(28px, 5vw, 56px);
  align-items: start;
}

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

.pricing__included h2 {
  margin-bottom: 12px;
}

.pricing__included .lede {
  margin-bottom: 26px;
}

.pricing__model {
  padding: 28px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow);
}

.pricing__model h2 {
  font-size: 1.35rem;
  margin-bottom: 12px;
}

.pricing__model p {
  color: var(--ink-muted);
  margin-bottom: 22px;
}

.demo,
.contact {
  display: grid;
  gap: clamp(28px, 5vw, 56px);
  align-items: start;
}

@media (min-width: 900px) {
  .demo,
  .contact {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  }
}

.demo__site h2,
.demo__try h2,
.contact__what h2,
.contact__email h2 {
  margin-bottom: 14px;
}

.demo__site .lede {
  margin-bottom: 26px;
}

.demo__note {
  margin-top: 16px;
  color: var(--ink-muted);
  font-size: 0.875rem;
}

.contact__email {
  padding: 28px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow);
}

.contact__email p {
  color: var(--ink-muted);
}

.contact__address {
  display: inline-block;
  margin-top: 18px;
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  word-break: break-word;
}

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

/* An unset placeholder should look like one, not like an address. */
.contact__address--missing {
  color: var(--ink-muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9375rem;
  font-weight: 400;
}

/* --- 7f. Legal documents ---------------------------------------------------- */

/*
 * Rendered from Markdown, so this styles element selectors rather than classes — there is no
 * opportunity to put a class on anything, and that is the point: the document stays a document.
 * Sized for reading a long text rather than scanning a page.
 */
.legal {
  color: var(--ink-muted);
  font-size: 1.0625rem;
  line-height: 1.75;
}

.legal h1 {
  /* The page hero already carries the document's title; the file's own h1 repeats it. Kept in
     the Markdown so the file reads correctly on its own, hidden here so the page does not say
     the same thing twice. */
  display: none;
}

.legal h2 {
  font-size: 1.45rem;
  margin-top: 2.2em;
  margin-bottom: 0.6em;
}

.legal h3 {
  font-size: 1.1rem;
  margin-top: 1.8em;
  margin-bottom: 0.5em;
}

.legal p,
.legal ul,
.legal ol,
.legal table {
  margin-bottom: 1.1em;
}

.legal ul,
.legal ol {
  padding-left: 1.4em;
}

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

.legal a {
  color: var(--accent);
}

.legal strong {
  color: var(--ink-strong);
}

.legal hr {
  margin-block: 2.4em;
  border: 0;
  border-top: 1px solid var(--line);
}

/* The drafts open with a blockquote saying they are drafts. It should look like a notice. */
.legal blockquote {
  margin: 0 0 1.6em;
  padding: 16px 20px;
  border: 1px solid color-mix(in srgb, var(--warning, #fbbf24) 45%, transparent);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--warning, #fbbf24) 10%, transparent);
  color: var(--ink);
}

.legal blockquote p:last-child {
  margin-bottom: 0;
}

:root {
  --warning: #fbbf24;
}

:root[data-theme='light'] {
  --warning: #b45309;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --warning: #b45309;
  }
}

/* Legal documents carry tables of retention periods and data categories. They must scroll
   inside their own container rather than widening the page. */
.legal table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
  display: block;
  overflow-x: auto;
}

.legal th,
.legal td {
  padding: 10px 14px;
  border: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

.legal th {
  color: var(--ink-strong);
  font-weight: 600;
  background: var(--bg-raised);
}

.legal code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.875em;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--bg-elevated);
}

/* --- 7e. Events ------------------------------------------------------------ */

.section-head--row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  max-width: none;
}

.event-grid {
  display: grid;
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
}

.event-card {
  display: flex;
}

/* The whole card is the link, so there is no small target to aim at and no ambiguity about
   which part is clickable. */
.event-card__link {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-raised);
  text-decoration: none;
  transition: border-color 0.18s ease, transform 0.18s ease;
}

.event-card__link:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}

.event-card__date {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--accent);
}

.event-card__title {
  font-size: 1.25rem;
}

.event-card__venue {
  color: var(--ink-muted);
  font-size: 0.9375rem;
}

.event-card__organizer {
  margin-top: auto;
  padding-top: 14px;
  color: var(--ink-muted);
  font-size: 0.8125rem;
}

.event-card__organizer span {
  opacity: 0.7;
}

.event-card__cta {
  color: var(--accent);
  font-weight: 600;
  font-size: 0.9375rem;
  margin-top: 10px;
}

.empty {
  max-width: 56ch;
}

.empty h2 {
  margin-bottom: 14px;
}

.empty .lede {
  margin-bottom: 26px;
}

/* One event's page: detail beside the ticket picker, which is the point of the page. */
.event-page {
  display: grid;
  gap: clamp(28px, 5vw, 56px);
  align-items: start;
}

@media (min-width: 900px) {
  .event-page {
    grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
  }
}

.event-page__organizer {
  margin-top: 28px;
  color: var(--ink-muted);
  font-size: 0.9375rem;
}

.event-page__back {
  display: inline-block;
  margin-top: 20px;
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.event-page__tickets {
  padding: 26px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow);

  /* The widget's own theming hooks — the only styling that crosses its shadow boundary. Set
     from this page's tokens so it looks like part of the page in both themes, exactly the way
     demo/index.html does it for an organizer's site. */
  --lk-font-family: var(--font-body);
  --lk-background: var(--bg-raised);
  --lk-text-color: var(--ink);
  --lk-muted-color: var(--ink-muted);
  --lk-border-color: var(--line-strong);
  --lk-primary-color: var(--accent);
  --lk-notice-background: var(--accent-soft);
}

.event-page__tickets h2 {
  font-size: 1.35rem;
  margin-bottom: 18px;
}

/* The element is inline by default and its own root caps at 360px; let it fill the panel. */
lippukone-tickets {
  display: block;
}

.event-page__fallback {
  margin-top: 14px;
  padding: 14px 16px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  color: var(--ink-muted);
  font-size: 0.875rem;
}

/* --- 7d. Forms ------------------------------------------------------------- */

.contact__form-column {
  min-width: 0;
}

.contact__aside {
  display: grid;
  gap: 28px;
}

.form {
  display: grid;
  gap: 20px;
  margin-top: 24px;
}

.form__row {
  display: grid;
  gap: 20px;
}

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

/* The label wraps its control, so the whole thing is one hit target and no `for`/`id` pair can
   drift apart. */
.form__field {
  display: grid;
  gap: 7px;
  min-width: 0;
}

.form__label {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink-strong);
}

.form__optional {
  font-weight: 400;
  color: var(--ink-muted);
  font-size: 0.8125rem;
}

.form input,
.form select,
.form textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.form textarea {
  resize: vertical;
  min-height: 140px;
}

.form input:focus,
.form select:focus,
.form textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Colour is not the only signal — the message below the field says what is wrong, and the
   border change is confirmation rather than the whole story. */
.form [aria-invalid='true'] {
  border-color: var(--error, #f87171);
}

.form__error {
  font-size: 0.875rem;
  color: var(--error, #f87171);
}

:root {
  --error: #f87171;
}

:root[data-theme='light'] {
  --error: #b91c1c;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --error: #b91c1c;
  }
}

.form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 22px;
}

.form__note {
  color: var(--ink-muted);
  font-size: 0.875rem;
  max-width: 44ch;
}

/* The honeypot. Off-screen rather than display:none — a bot that skips hidden fields should
   still find this one, which is the entire point of it. */
.form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.notice {
  padding: 18px 20px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  margin-bottom: 28px;
}

.notice h2 {
  font-size: 1.15rem;
  margin-bottom: 6px;
}

.notice p,
.notice li {
  color: var(--ink-muted);
  font-size: 0.9375rem;
}

.notice ul {
  margin: 0;
  padding-left: 20px;
}

.notice--success {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: var(--accent-soft);
}

.notice--error {
  border-color: color-mix(in srgb, var(--error) 55%, transparent);
  background: color-mix(in srgb, var(--error) 10%, transparent);
}

/* --- 7c. Illustrations ----------------------------------------------------- */

.art {
  width: 100%;
  height: auto;
  max-width: 460px;
  display: block;
  margin-inline: auto;
}

.art__frame {
  fill: var(--bg-raised);
  stroke: var(--line-strong);
  stroke-width: 1.5;
}

.art__screen {
  fill: var(--bg-elevated);
}

.art__screen--ok {
  fill: color-mix(in srgb, var(--accent) 22%, var(--bg-elevated));
}

.art__check {
  fill: none;
  stroke: var(--accent);
  stroke-width: 6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.art__bar {
  fill: var(--ink-muted);
}

.art__bar--dim {
  fill: var(--ink-muted);
  opacity: 0.45;
}

.art__wave {
  fill: none;
  stroke: var(--ink-muted);
  stroke-width: 3;
  stroke-linecap: round;
  opacity: 0.5;
}

.art__wave--dim {
  opacity: 0.28;
}

.art__wave--dimmer {
  opacity: 0.14;
}

.art__strike {
  stroke: var(--ink-muted);
  stroke-width: 2.5;
  stroke-linecap: round;
  opacity: 0.6;
}

.art__qr {
  fill: none;
  stroke: var(--ink-muted);
  stroke-width: 1.5;
  opacity: 0.5;
}

.art__qr-eye {
  fill: var(--ink);
}

.art__stub {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  opacity: 0.8;
}

/* --- 8. Footer ----------------------------------------------------------- */

.site-footer {
  margin-top: clamp(64px, 10vw, 120px);
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
  font-size: 0.9375rem;
}

.site-footer__inner {
  display: grid;
  gap: 36px;
  padding-block: 52px 40px;
}

@media (min-width: 640px) {
  .site-footer__inner {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 940px) {
  .site-footer__inner {
    grid-template-columns: 1.6fr repeat(3, minmax(0, 1fr));
    gap: 40px;
  }
}

.site-footer__tagline {
  margin-top: 14px;
  color: var(--ink-muted);
  max-width: 34ch;
}

.site-footer__column {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: start;
}

.site-footer__heading {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 4px;
}

.site-footer__column a {
  color: var(--ink);
  text-decoration: none;
}

.site-footer__column a:hover {
  color: var(--accent);
}

.site-footer__note {
  color: var(--ink-muted);
  font-size: 0.875rem;
  max-width: 28ch;
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding-block: 20px 32px;
  border-top: 1px solid var(--line);
  color: var(--ink-muted);
  font-size: 0.875rem;
}

/* --- 8b. Coming-soon page ------------------------------------------------- */

/* The pre-launch curtain (resources/views/coming-soon.blade.php). It is not part of the site
   — it is served on admin.* and wallet.* too — so it has no header, no footer and no nav, and
   borrows only the tokens, the type and the hero's glow.

   A stage element rather than the body, and it earns its keep three times over.

   `isolation` is what makes .hero__glow reusable at all: that element sits at z-index: -1, so
   it needs a positioned ancestor that isolates, or it paints behind the page background and
   disappears. On the site that ancestor is .hero.

   `overflow: clip` is the half that was missing, and its absence is why this page scrolled in
   both directions on every screen. The glow is inset -15% horizontally and 780px tall from
   -120px, so it hangs outside its container on purpose — .hero clips it and nothing here did.
   The clip has to be on an element *inside* the body: overflow set on the body propagates to
   the viewport, which would stop the page scrolling even when the content genuinely needs it,
   on a short screen or at a large text size.

   min-height rather than height, for the same reason: the stage grows past the viewport when
   the content asks for it, and only then does the page scroll. */
.coming-soon__stage {
  position: relative;
  isolation: isolate;
  /* hidden first, clip second: identical here, but `clip` is the honest one (it does not make
     this a scroll container) and Safari only learned it in 16. A browser that skips the second
     line still gets the glow contained rather than the scrollbars back. */
  overflow: hidden;
  overflow: clip;
  /* svh, so the mobile URL bar collapsing does not leave a strip of scroll behind. The vh
     line above it is the fallback for a browser that has not heard of svh. */
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
}

.coming-soon__inner {
  padding-block: clamp(48px, 10vw, 96px);
}

.coming-soon .eyebrow {
  margin-top: 40px;
}

.coming-soon .lede {
  margin-top: 22px;
}

.coming-soon__contact {
  margin-top: 34px;
  color: var(--ink-muted);
}

/* The one line on the maintenance page somebody is reloading to read, so it is the one thing
   that is not muted like the lede above it. The accent border does the emphasising rather than
   a colour on the text itself: the accent is a low-contrast teal against both themes'
   backgrounds, and putting it on the words would trade legibility for prominence in exactly the
   sentence that has to be read correctly. */
.maintenance__eta {
  margin-top: 28px;
  padding-left: 16px;
  border-left: 3px solid var(--accent);
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  max-width: 58ch;
}

/* --- 9. Motion and print -------------------------------------------------- */

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

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

@media print {
  .site-header,
  .site-menu,
  .hero__glow,
  .skip-link {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }
}
