/*
  Raphael Saeed / Visage — shared stylesheet.
  One file, every page. No frameworks, no external requests: the two display
  fonts (Sora, Nunito Sans — SIL OFL, see fonts/OFL-NOTE.txt) are self-hosted
  variable woff2 files. Dark neumorphic theme ("soft UI"): one uniform base
  surface, raised elements lit from the top-left, pressed elements inset.
*/

/* ---------- Self-hosted fonts ---------- */

@font-face {
  font-family: "Sora";
  src: url("fonts/sora-var.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
}

@font-face {
  font-family: "Nunito Sans";
  src: url("fonts/nunito-sans-var.woff2") format("woff2");
  font-weight: 200 1000;
  font-display: swap;
}

/* ---------- Reset & base ---------- */

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

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

body {
  margin: 0;
  min-height: 100vh;
}

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

a {
  color: inherit;
}

/* ---------- Design tokens (neumorphism-dark) ---------- */

:root {
  /* The single soft surface everything is carved from */
  --base: #e4e7ee;
  --base-2: #eaedf3;
  --shadow-dark: rgba(163, 170, 190, 0.65);
  --shadow-light: rgba(255, 255, 255, 0.95);

  /* Text */
  --ink: #3a3f52; /* 8.4:1 on --base */
  --ink-dim: #555d78; /* 5.4:1 */
  --ink-faint: #5f6780; /* 4.5:1 — still text, so still AA */

  /* Accents */
  --accent: #3452c9; /* 5.3:1 */
  --accent-soft: #3f5bd6; /* 4.6:1 — used as link text */
  --accent-glow: rgba(52, 82, 201, 0.28);
  --sage: #3f6a55; /* 5.0:1 */
  --buy-orange: #b53c0b; /* 4.7:1 — the Buy button is orange TEXT on the surface */
  --buy-orange-soft: #c2410c;

  /* Raised & pressed surface recipes */
  --pop: -9px -9px 18px var(--shadow-light), 9px 9px 18px var(--shadow-dark);
  --pop-sm: -5px -5px 10px var(--shadow-light), 5px 5px 10px var(--shadow-dark);
  --push: inset -5px -5px 10px var(--shadow-light),
    inset 5px 5px 10px var(--shadow-dark);
  --push-sm: inset -3px -3px 6px var(--shadow-light),
    inset 3px 3px 6px var(--shadow-dark);

  --radius-sm: 12px;
  --radius: 20px;
  --radius-lg: 28px;
  --radius-xl: 36px;
  --radius-pill: 999px;

  --font-display: "Sora", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;

  --container-wide: none;
  --container-prose: 1000px;
  --edge-pad: clamp(2.5rem, 6vw, 7rem);
}

/* ---------- Typography ---------- */

body {
  font-family: var(--font-body);
  background: var(--base);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.12;
  margin: 0 0 0.5em;
  color: var(--ink);
}

h1 {
  font-size: clamp(1.85rem, 3.8vw, 2.7rem);
  letter-spacing: -0.025em;
  line-height: 1.1;
}

h2 {
  font-size: clamp(1.5rem, 3vw, 1.9rem);
}

h3 {
  font-size: 1.16rem;
  font-weight: 600;
}

p {
  margin: 0 0 1em;
  color: var(--ink-dim);
}

p strong,
li strong {
  color: var(--ink);
  font-weight: 700;
}

.lede {
  font-size: 1.08rem;
  line-height: 1.7;
  color: var(--ink-dim);
  max-width: 52ch;
}

ul,
ol {
  color: var(--ink-dim);
  line-height: 1.7;
  padding-left: 1.25em;
}

li {
  margin-bottom: 0.4em;
}

li::marker {
  color: var(--accent);
}

code,
.license-key {
  font-family: var(--font-mono);
}

/* Eyebrow — the mockup's soft pressed pill */
.eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--sage);
  background: var(--base);
  box-shadow: var(--push-sm);
  padding: 0.65em 1.35em;
  border-radius: var(--radius-pill);
  margin: 0 0 1.4em;
}

.fine-print {
  font-size: 0.85rem;
  color: var(--ink-faint);
}

/* ---------- Links, focus ---------- */

a {
  text-decoration: none;
}

.text-link {
  color: var(--accent-soft);
  text-decoration: underline;
  text-decoration-color: rgba(63, 91, 214, 0.35);
  text-underline-offset: 3px;
}

.text-link:hover {
  text-decoration-color: currentColor;
}

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

/* ---------- Layout ---------- */

.container {
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: 0 var(--edge-pad);
}

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

main {
  /* positioned, but NOT a stacking context (no z-index): the diagrams in
     "Who it's for" melt into the page with `multiply`, and a blend can only
     see the backdrop inside its own stacking context. The dotted surface it
     must see lives in .glow-field, painted below everything at z-index -1. */
  position: relative;
  display: block;
}

section {
  padding: 3.5rem 0;
}

[id] {
  scroll-margin-top: 90px;
}

section.hero {
  padding-top: 4rem;
  padding-bottom: 3rem;
}

/* Engraved groove instead of a hard border — light below, dark above.
   The margin keeps card shadows from crowding the groove and the title. */
.section-border-top {
  border-top: 1px solid var(--shadow-dark);
  box-shadow: inset 0 1px 0 rgba(163, 170, 190, 0.45);
  margin-top: 2rem;
}

/* ---------- Background field ----------
   Neumorphism depends on one uniform surface colour, so the old glow blooms
   are gone; a whisper-faint dot grid stays as the echo of the particle face. */

.glow-field {
  position: fixed;
  inset: 0;
  z-index: -1; /* under the in-flow content too — see `main` */
  pointer-events: none;
  background-color: var(--base);
  background-image: radial-gradient(
    rgba(58, 63, 82, 0.07) 1px,
    transparent 1px
  );
  background-size: 26px 26px;
}

/* ---------- Header / nav ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding-top: 1.1rem;
  padding-bottom: 1.1rem;
  background: rgba(228, 231, 238, 0.85);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.06rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
}

.site-nav {
  display: flex;
  flex-wrap: wrap; /* five links never fit a phone-width row; wrap instead of overflowing the page */
  gap: 0.35rem;
  font-size: 0.9rem;
  font-weight: 700;
}

.site-nav a {
  color: var(--ink-dim);
  padding: 0.6em 1.05em;
  border-radius: var(--radius-sm);
  transition: color 0.25s, box-shadow 0.25s;
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--ink);
  box-shadow: var(--pop-sm);
}

.site-nav a:active,
.site-nav a[aria-current="page"],
.site-nav a[aria-current="page"]:hover {
  color: var(--sage);
  box-shadow: var(--push-sm);
}

/* ---------- The product logo ----------
   The PNG is transparent — let the glyph float on the page itself; the
   drop-shadow follows the logo's own contours, never a box. */

.app-icon {
  width: 112px;
  height: 112px;
  margin-top: -1rem;
  margin-bottom: 1.4rem;
  filter: drop-shadow(5px 7px 12px rgba(163, 170, 190, 0.6));
}

.app-icon--sm {
  width: 64px;
  height: 64px;
  margin-top: 0;
  margin-bottom: 1.2rem;
}

/* ---------- Buttons ---------- */

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin: 2rem 0 1rem;
}

.btn-primary,
.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.68em 1.15em;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-weight: 700;
  border: none;
  cursor: pointer;
  background: var(--base);
  box-shadow: var(--pop);
  transition: transform 0.2s, box-shadow 0.2s, color 0.2s;
}

.btn-primary {
  color: var(--buy-orange);
}

.btn-primary:hover {
  color: var(--buy-orange-soft);
  transform: translateY(-1px);
}

.btn-primary:active {
  transform: translateY(0);
  box-shadow: var(--push);
}

.btn-secondary {
  color: var(--accent);
}

.btn-secondary:hover {
  color: var(--accent-soft);
  transform: translateY(-1px);
}

.btn-secondary:active {
  transform: translateY(0);
  box-shadow: var(--push);
}

/* ---------- Cards ---------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.6rem;
  margin-top: 2rem;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.6rem;
  margin-top: 2rem;
}

.card {
  background: var(--base);
  border-radius: var(--radius-lg);
  padding: 2.1rem 1.75rem;
  box-shadow: var(--pop);
  transition: transform 0.3s;
}

.card:hover {
  transform: translateY(-6px);
}

.card h3 {
  color: var(--ink);
  margin-bottom: 0.5em;
}

.card p {
  font-size: 0.92rem;
  line-height: 1.7;
}

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

.project-card {
  display: block;
  background: var(--base);
  border-radius: var(--radius-xl);
  padding: 2.25rem;
  box-shadow: var(--pop);
  transition: transform 0.3s;
}

.project-card:hover {
  transform: translateY(-6px);
}

.project-card h2 {
  color: var(--ink);
}

.card-cta {
  display: inline-block;
  margin-top: 0.75rem;
  color: var(--accent-soft);
  font-weight: 700;
  font-size: 0.95rem;
}

/* ---------- Video placeholder — a recessed "screen" ---------- */

.video-placeholder {
  margin: 2.25rem 0;
  border: none;
  border-radius: var(--radius-lg);
  background: var(--base);
  box-shadow: var(--push);
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-placeholder-inner {
  text-align: center;
  color: var(--ink-faint);
}

.video-placeholder-glyph {
  display: block;
  width: 58px;
  height: 58px;
  margin: 0 auto 0.9rem;
  border-radius: 50%;
  background: var(--base);
  box-shadow: var(--pop-sm);
  position: relative;
}

.video-placeholder-glyph::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 56%;
  width: 0;
  height: 0;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 8px 0 8px 13px;
  border-color: transparent transparent transparent var(--accent);
}

.video-placeholder figcaption {
  margin-top: 0;
  font-size: 0.85rem;
  color: var(--ink-faint);
}

/* Four reserved video slots, small title under each */
.video-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.8rem 1.6rem;
  margin-top: 2rem;
}

.video-slot {
  margin: 0;
}

.video-slot .video-placeholder {
  margin: 0 0 0.85rem;
}

.video-slot .video-placeholder-glyph {
  width: 46px;
  height: 46px;
  margin-bottom: 0;
}

.video-slot > figcaption {
  text-align: center;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--ink-dim);
}

/* "See in action" (2026-09-22; the cards went on 2026-09-29): two portrait
   shorts as split blocks (same anatomy as "Who it's for"), then two landscape
   demos. Every video is one recessed window straight on the page.
   Self-hosted MP4s, click to play — only the posters load until then. */
.video-slot video,
.split--video .split-media {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--push);
  background: var(--base);
}

.split--video .split-media {
  background: #101318; /* behind the poster while it loads; matches the recordings' dark desktop */
}

@media (max-width: 800px) {
  .video-grid {
    grid-template-columns: 1fr;
  }
}

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

.price-card {
  background: var(--base);
  border-radius: var(--radius-xl);
  box-shadow: var(--pop);
  padding: 2.4rem;
  max-width: 480px;
}

.price {
  font-family: var(--font-display);
  font-size: 3rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--accent);
}

.price-suffix {
  font-size: 1rem;
  color: var(--ink-dim);
  font-weight: 600;
  margin-left: 0.35em;
}

.price-features {
  margin: 1.5rem 0;
}

/* Compact button pair inside the pricing card — always side by side */
.price-card .cta-row {
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* Wide variant: one row of three buttons, Buy leading; spans the full
   container like the card grids in the sections above */
.price-card--wide {
  max-width: none;
}


/* ---------- FAQ (details/summary, no JS) ---------- */

.faq-item {
  background: var(--base);
  border-radius: var(--radius);
  box-shadow: var(--pop-sm);
  padding: 1.2rem 1.5rem;
  margin-bottom: 1.1rem;
  border-bottom: none;
  transition: box-shadow 0.25s;
}

.faq-item summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--ink);
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

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

.faq-item summary::after {
  content: "+";
  color: var(--accent);
  font-weight: 400;
  font-size: 1.3rem;
  flex-shrink: 0;
}

.faq-item[open] {
  box-shadow: var(--push);
}

.faq-item[open] summary::after {
  content: "\2212";
}

.faq-item p,
.faq-item ul {
  margin-top: 0.9rem;
}

.faq-item p:last-child {
  margin-bottom: 0.3rem;
}

/* ---------- Legal ---------- */

.legal-status {
  display: inline-block;
  background: var(--base);
  box-shadow: var(--push-sm);
  color: var(--sage);
  border: none;
  border-radius: var(--radius-pill);
  padding: 0.65em 1.35em;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-bottom: 2rem;
}

.legal-todo {
  color: var(--sage);
  border-bottom: 1px dashed rgba(63, 106, 85, 0.55);
}

.legal-body h2 {
  margin-top: 2.5rem;
  font-size: 1.45rem;
}

.legal-body h2:first-of-type {
  margin-top: 0;
}

.legal-body h3 {
  margin-top: 1.75rem;
}

.legal-body p,
.legal-body li {
  font-size: 0.95rem;
}

/* ---------- Thanks / key result ---------- */

.status-card {
  background: var(--base);
  border-radius: var(--radius-xl);
  box-shadow: var(--pop);
  padding: 2.4rem;
  max-width: 560px;
}

#status {
  color: var(--ink-dim);
}

.key-result {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--shadow-dark);
  box-shadow: inset 0 1px 0 rgba(163, 170, 190, 0.45);
}

.license-key {
  display: block;
  background: var(--base);
  box-shadow: var(--push);
  border: none;
  border-radius: var(--radius-sm);
  padding: 1.1em 1.2em;
  font-size: 1.05rem;
  letter-spacing: 0.03em;
  color: var(--accent-soft);
  word-break: break-all;
  margin-bottom: 1.1rem;
}

.key-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

.copy-note {
  font-size: 0.85rem;
  color: var(--ink-faint);
}

/* ---------- Simple standalone pages (licences) ---------- */

.page {
  max-width: var(--container-prose);
  margin: 0 auto;
  padding: 4rem var(--edge-pad);
  position: relative;
  z-index: 1;
}

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

.site-footer {
  position: relative;
  z-index: 1;
  padding: 3rem var(--edge-pad) 4rem;
  margin-top: 3rem;
  border-top: 1px solid var(--shadow-dark);
  box-shadow: inset 0 1px 0 rgba(163, 170, 190, 0.45);
  font-size: 0.88rem;
  color: var(--ink-faint);
}

.site-footer a {
  color: var(--ink-faint);
  text-decoration: underline;
  text-decoration-color: rgba(95, 103, 128, 0.4);
  text-underline-offset: 3px;
}

.site-footer a:hover {
  color: var(--ink-dim);
}

.footer-links {
  margin-top: 0.5rem;
}

.footer-links a + a {
  margin-left: 0.4em;
}

/* ---------- Responsive ---------- */

@media (max-width: 800px) {
  .card-grid {
    grid-template-columns: 1fr;
  }

  .feature-grid {
    grid-template-columns: 1fr;
  }

  section {
    padding: 2.5rem 0;
  }
}

@media (max-width: 520px) {
  .cta-row {
    flex-direction: column;
    align-items: stretch;
  }

  .btn-primary,
  .btn-secondary {
    text-align: center;
  }

  .price {
    font-size: 2.4rem;
  }
}

/* ---------- Visage landing: brand lockup, duo cards, spec table ---------- */

/* Brand header: logo + headline on the left, nav on the right. The tall
   brand row must not stick, and the logo's top aligns with the nav links. */
.site-header--brand {
  /* relative, not static: keeps the header painted above the fixed
     .glow-field (z-index needs a positioned box) without being sticky */
  position: relative;
  align-items: flex-start;
  /* opaque page colour (not transparent): the duo-gif's multiply blend needs
     an opaque backdrop inside this stacking context to melt its box into */
  background: var(--base);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  /* one size, used by the title AND the logo-alignment maths below */
  --brand-title-size: clamp(1.85rem, 2.9vw, 2.55rem);
}

/* The nav floats top-right, out of the flow: the headline starts lower
   than the nav row, so the full container width belongs to the headline. */
.site-header--brand .site-nav {
  position: absolute;
  top: 1.1rem;
  right: var(--edge-pad);
}

/* The copy column sits to the right of the logo: headline first (its bottom
   near the logo's bottom), the two statement cards directly beneath, both
   sharing the same left/right edges as the headline. */
.brand-lockup {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
  /* flexible: compress the copy column rather than wrap the nav below */
  flex: 1 1 0;
  min-width: 0;
}

.brand-lockup .app-icon {
  margin: 0;
  flex-shrink: 0;
}

.brand-copy {
  max-width: 66rem;
  /* headline bottom lands on the logo's bottom edge (112px logo,
     1.1 line-height) at every viewport size */
  padding-top: calc(112px - 1.1 * var(--brand-title-size, 2.6rem));
}

.brand-title {
  margin: 0 0 1rem;
  font-size: var(--brand-title-size, 2.6rem);
}

/* The face with one statement beside it (2026-09-22: one card, was a pair;
   2026-09-29: the card went too — bare accent-blue text on the page). */
.duo-grid {
  display: grid;
  /* the live face stage leads (2026-09-29); the statement sits beside it */
  grid-template-columns: minmax(0, 30rem) minmax(0, 1fr);
  gap: 2rem 2.5rem;
  align-items: center;
}

/* ---- The live face (2026-09-29): the app's own FaceMorph bundle drawn on a
   transparent canvas, six expression labels around it and a colour arc
   beneath. Script: face/hero-face.js. Until it boots — and forever when it
   cannot (no WebGL2, reduced motion) — the GIF still shows, alone. ---- */
.face-stage {
  display: grid;
  justify-items: center;
  gap: 0.2rem;
  width: 100%;
}

.face-scene {
  position: relative;
  width: 100%;
  aspect-ratio: 480 / 320;
  /* the scene's box overlaps the arc tucked beneath it: let the pointer fall
     through everywhere except the words (they opt back in below) */
  pointer-events: none;
}

/* The canvas is half again larger than the scene on every side and takes no
   pointer events: the scattered cloud needs room past the face, and while
   "Disperse" is held the script scales the canvas up so the dots drift out
   over the page around it (camDist in hero-face.js compensates the size). */
.face-canvas {
  position: absolute;
  left: -25%;
  top: -36%; /* lifted: the crown sits up against the heading (owner, 2026-09-29) */
  width: 150%;
  height: 150%;
  pointer-events: none;
  transform-origin: 50% 47%;
  transition: transform 0.6s ease-out;
}

/* The GIF fallback: its own white backdrop is lighter than the page base, so
   `multiply` keeps only the particles and dissolves the rectangle into the
   page (the header paints an opaque base for exactly this). */
.duo-gif {
  position: absolute;
  left: 50%;
  top: 50%;
  height: 64%;
  width: auto;
  max-width: none;
  transform: translate(-50%, -50%);
  mix-blend-mode: multiply;
}

.face-labels {
  list-style: none;
  margin: 0;
  padding: 0;
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.face-label {
  position: absolute;
  left: var(--x);
  top: var(--y);
  pointer-events: auto;
}

.face-label--tl { --x: 26%; --y: 4%;  --drift: 5.2s; --lag: 0s; }
.face-label--tr { --x: 61%; --y: 2%;  --drift: 6.1s; --lag: -2.1s; }
.face-label--ml { --x: 15%; --y: 34%; --drift: 5.6s; --lag: -3.4s; }
.face-label--mr { --x: 68%; --y: 32%; --drift: 6.6s; --lag: -1.2s; }
.face-label--bl { --x: 12%; --y: 57%; --drift: 5.9s; --lag: -4.3s; }
.face-label--br { --x: 70%; --y: 58%; --drift: 5.4s; --lag: -2.8s; }

@media (max-width: 640px) {
  .face-label button {
    font-size: 0.8rem;
  }

  .face-label--tl { --x: 18%; --y: 4%; }
  .face-label--tr { --x: 62%; --y: 2%; }
  .face-label--ml { --x: 6%;  --y: 36%; }
  .face-label--mr { --x: 68%; --y: 34%; }
  .face-label--bl { --x: 5%;  --y: 59%; }
  .face-label--br { --x: 69%; --y: 60%; }

  .face-palette {
    width: 80%;
  }
}

/* Bare floating words, no box (owner, 2026-09-29): each drifts up and down
   on its own slow cycle; hovering one brightens it while it holds the look. */
.face-label button {
  font: 700 0.92rem/1 var(--font-body);
  letter-spacing: 0.01em;
  color: var(--ink-dim);
  background: none;
  border: 0;
  padding: 0.35em 0.5em;
  cursor: pointer;
  white-space: nowrap;
  text-shadow: 0 1px 0 var(--shadow-light);
  animation: face-label-float var(--drift, 6s) ease-in-out var(--lag, 0s) infinite;
  transition: color 0.2s, transform 0.2s;
}

.face-label button:hover,
.face-label button:focus-visible,
.face-label button.is-on {
  color: var(--sage);
  transform: scale(1.08);
  outline: none;
}

@keyframes face-label-float {
  0%, 100% { translate: 0 -4px; }
  50% { translate: 0 4px; }
}

@media (prefers-reduced-motion: reduce) {
  .face-label button {
    animation: none;
  }
}

.face-palette {
  display: block;
  width: 58%;
  height: auto;
  margin-top: -24%; /* tucked up so the bowl cradles the neck */
  overflow: visible;
}

.face-palette path {
  cursor: pointer;
  stroke: transparent;
  stroke-width: 2;
  transition: stroke 0.15s;
}

.face-palette path:hover,
.face-palette path:focus-visible,
.face-palette path.is-active {
  stroke: var(--ink);
  outline: none;
}

.face-canvas[hidden],
.face-fallback[hidden],
.face-labels[hidden],
.face-palette[hidden] {
  display: none;
}

.duo-statement {
  margin: 0;
  /* a little above the stage's centre line (owner, 2026-09-29) */
  position: relative;
  top: -2.5rem;
  color: var(--accent);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.6;
}

/* Tightened section: pulls the "Who it's for" block up under the header,
   its eyebrow pill sitting right against the groove line */
.section-tight {
  margin-top: 0.75rem;
  padding-top: 0;
}

.section-tight .feature-grid,
.section-tight .video-grid {
  margin-top: 1.1rem;
}

/* "Who it's for" split blocks (2026-09-19 as cards; the cards and the tiles
   went on 2026-09-29): heading edge to edge, then the diagram on the left and
   the short text on the right, both straight on the page. The diagrams are
   portrait GIFs (538×652) drawn on white; `multiply` turns that white into
   whatever the page paints beneath — the base colour AND the dot grid — so
   only the drawing remains. Needs `main` to stay out of the stacking order. */
.split h3 {
  margin-bottom: 0.35em;
  text-align: center;
}

/* Heading colours sampled from each diagram's face: green face on the left,
   amber face on the right */
.split--green h3 {
  color: #2c7324; /* 4.7:1 */
}

.split--amber h3 {
  color: #8c5b07; /* 4.7:1 */
}

.split-body {
  display: grid;
  grid-template-columns: minmax(0, 9fr) minmax(0, 11fr);
  gap: 1.3rem;
  /* the text block sits on the picture's (or video's) vertical centre */
  align-items: center;
  margin-top: 0.55rem;
}

.split-media {
  display: block;
  width: 100%;
  height: auto;
}

/* the diagrams (images) melt into the page; the videos stay windows (below) */
img.split-media {
  mix-blend-mode: multiply;
}

/* Three short beats per block (2026-09-21), set compact (2026-09-29): one
   idea per paragraph, tight leading and a half-line between beats, so the
   block reads as one compact unit centred on the picture beside it */
.split-text p {
  font-size: 0.95rem;
  line-height: 1.5;
  margin: 0 0 0.55em;
}

.split-text p:last-child {
  margin-bottom: 0;
}

/* The two split grids on the landing page: with no card edges between the
   blocks, a wider gutter keeps each pair reading as one unit */
.grid--loose {
  gap: 2.6rem 3rem;
}

@media (max-width: 800px) {
  .split-body {
    grid-template-columns: 1fr;
  }

  .split-media {
    max-width: 340px;
    margin: 0 auto;
  }
}

/* Specifications table — engraved row separators, quiet labels */
.spec-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 2rem;
}

.spec-table th,
.spec-table td {
  text-align: left;
  vertical-align: top;
  padding: 0.5em 0;
}

.spec-table th {
  color: var(--ink);
  font-weight: 700;
  white-space: nowrap;
  padding-right: 2.5rem;
  width: 15.5rem;
}

.spec-table td {
  color: var(--ink-dim);
}

.spec-table tr + tr th,
.spec-table tr + tr td {
  border-top: 1px solid var(--shadow-dark);
  box-shadow: inset 0 1px 0 rgba(163, 170, 190, 0.45);
}

/* Prose sections that hug the left edge instead of centring. The section
   itself stays full-width (so its groove line spans the page like every
   other section); only the text content is capped at prose width. */
.prose--flush {
  max-width: none;
  margin-left: 0;
}

.prose--flush > * {
  max-width: var(--container-prose);
}

@media (max-width: 800px) {
  .duo-grid {
    grid-template-columns: 1fr;
  }

  .duo-statement {
    top: 0; /* stacked under the stage, nothing to rise above */
  }

  /* small screens: nav rejoins the flow instead of overlapping the copy */
  .site-header--brand .site-nav,
  .site-header--float .site-nav {
    position: static;
  }

  /* ...on its own row above the lockup: sharing the row left the lockup
     (flex-basis 0) with the leftover width and squeezed the copy into a
     narrow column (seen at 760 px, fixed 2026-09-22) */
  .site-header--brand .site-nav {
    flex: 1 1 100%;
    order: -1;
  }
}

@media (max-width: 640px) {
  .brand-lockup {
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }

  .brand-copy {
    padding-top: 0;
  }

  .spec-table th {
    white-space: normal;
    width: 8.5rem;
    padding-right: 1.25rem;
  }
}

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

  * {
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Prose tables (Guide etc.) — the spec-table tones, generalized.
   Added 2026-09-03: rendered markdown tables had NO styling, so cell text fell
   to UA defaults and read near-invisible on the dark ground. ---------- */

.prose table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.4rem 0;
}

.prose th,
.prose td {
  text-align: left;
  vertical-align: top;
  padding: 0.5em 1.1em 0.5em 0;
}

.prose th {
  color: var(--ink);
  font-weight: 700;
}

.prose td {
  color: var(--ink-dim);
}

.prose tr + tr th,
.prose tr + tr td {
  border-top: 1px solid var(--shadow-dark);
  box-shadow: inset 0 1px 0 rgba(163, 170, 190, 0.45);
}

/* Sub-page headers carry the product logo instead of the wordmark (2026-09-03);
   the hero logo margins don't apply in a flex header row. */
.site-header .app-icon--sm {
  margin: 0;
}

/* Wide prose (2026-09-03, owner: the Guide must extend horizontally like the main
   page) — keeps every .prose style (incl. the table tones) at container width. */
.prose--wide {
  max-width: var(--container-wide);
}

/* Nav continuity (2026-09-03, owner: buttons must not shift between pages) —
   sub-page headers top-align like the brand header, so the nav row sits at the
   same y everywhere; the item set is identical page-to-page in the markup. */
.site-header:not(.site-header--brand) {
  align-items: flex-start;
}

/* Pinned brand chrome (2026-09-03, owner ruling: the logo and menu stay up on the
   MAIN page too — and the big logo keeps its size, floating/spilling over the page
   as it scrolls; only the headline and cards scroll away). Coordinates chosen so
   NOTHING moves at rest: the nav's first pill stays at the same y as every other
   page (18px), the glyph keeps its exact in-flow spot. Desktop only — a fixed
   112px glyph would smother small screens. */
@media (min-width: 801px) {
  .site-header--brand .site-nav,
  .site-header--float .site-nav {
    position: fixed;
    top: 0.95rem;
    right: calc(var(--edge-pad) - 0.3rem);
    z-index: 60;
    padding: 0.15rem 0.3rem;
    border-radius: var(--radius-sm);
    /* the sub-page header's own material, for legibility over scrolled content */
    background: rgba(228, 231, 238, 0.85);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }

  .site-header--brand .brand-lockup .app-icon,
  .site-header--float .app-icon {
    position: fixed;
    top: 1.1rem;
    left: var(--edge-pad);
    z-index: 60;
    margin: 0;
  }

  /* The glyph left the flow — hold the headline column exactly where it was. */
  .site-header--brand .brand-lockup {
    padding-left: calc(112px + 1.5rem);
  }
}

/* Floating chrome on sub-pages too (2026-09-03, owner: "use exactly the same
   style in Guide and Support") — the bar dissolves on desktop; the full-size
   glyph and the glass nav float exactly as on the main page. The header keeps
   enough flow height that content starts below the pinned glyph. On small
   screens the old sticky bar returns, with the glyph sized down to fit it. */
@media (min-width: 801px) {
  .site-header--float {
    position: static;
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    min-height: calc(112px + 2.4rem);
    align-items: flex-start;
  }
}

@media (max-width: 800px) {
  .site-header--float .app-icon {
    width: 64px;
    height: 64px;
  }
}

/* ---------- Home: two-up project row + the light Raphs card (2026-09-03) ----------
   The Raphs card borrows raphs.app's whitish ground while keeping this page's
   theme language (same radius, same pop shadow, same card anatomy). */

.project-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.6rem;
}

@media (max-width: 800px) {
  .project-row {
    grid-template-columns: 1fr;
  }
}

.project-card--light {
  background: #f4f2ec;
}

.project-card--light h2 {
  color: #23252c;
}

.project-card--light p {
  color: #4c4f58;
}

.project-card--light .eyebrow {
  color: #a4581d;
}

.project-card--light .card-cta {
  color: #c2410c;
}

.project-card--light .app-icon--raphs {
  width: auto;
  height: 56px;
  margin: 0 0 1.2rem;
}

/* Light theme: the Apple glyph is a white PNG drawn for the dark theme — darken it so it
   reads on the grey surface; the Windows glyph is coloured and needs nothing. */
img[src$="apple-logo.png"] {
  filter: brightness(0.25);
}

/* Legal pages: the change notice promised by the privacy policy's §12 — raised, accent-edged,
   impossible to miss above the fold. Added 2026-09-21 with the RAPHS LTD version 1.1. */
.legal-notice {
  margin: 1.25rem 0 2rem;
  padding: 1rem 1.25rem;
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--pop-sm);
  color: var(--ink);
}
