/* ============================================================
   OHANES — KAYEM.CO FLAGSHIP CONTACT · STYLESHEET
   A machined black object suspended in a soft, living gold
   atmosphere. Gold is light (reflection, energy, response),
   never surface paint. Restraint first; every rule earns its place.

   Sections
     1. tokens            5. buttons (Kayem tactile primitive)
     2. base + a11y       6. detail sheet (dialog)
     3. environment       7. entrance
     4. plate (card)      8. responsive · adaptive tiers · reduced motion
   ============================================================ */

/* ---------- 1. tokens ---------- */
:root {
  /* palette — several blacks, one gold */
  --k-black: #08080a;
  --k-black-warm: #0e0c0a;
  --k-graphite: #111113;
  --k-charcoal: #15151a;
  --k-plate-hi: #19191c;
  --k-plate-lo: #0e0e10;
  --k-text: #f1efe9;
  --k-text-2: #aaa79f;      /* 7.6:1 on plate */
  --k-text-3: #8e8b84;      /* 5.1:1 on plate — tertiary only */
  --k-gold: #c9a35a;        /* champagne, decorative */
  --k-gold-hi: #ead39a;
  --k-gold-deep: #7d612c;
  --k-gold-text: #d9b970;   /* 9.3:1 on plate — gold used as text/outline */
  --k-line: rgba(255, 255, 255, 0.08);

  /* geometry */
  --r-plate: 22px;
  --r-control: 12px;
  --r-chip: 10px;
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 20px; --s-6: 24px; --s-7: 32px;

  /* motion */
  --t-instant: 90ms;
  --t-press: 110ms;
  --t-release: 280ms;
  --t-ui: 220ms;
  --t-panel: 420ms;
  --e-press: cubic-bezier(0.2, 0.7, 0.3, 1);
  --e-release: cubic-bezier(0.22, 1.35, 0.36, 1);   /* restrained overshoot */
  --e-out: cubic-bezier(0.16, 1, 0.3, 1);
  --e-in: cubic-bezier(0.7, 0, 0.84, 0);

  /* environment state (written by js/app.js; -1…1, 0…1) */
  --ex: 0;
  --ey: 0;
  --ei: 0;
  --imp: 0;   /* interaction impulse, decays over ~0.4 s */

  --font: "SF Pro Text", "SF Pro Display", -apple-system, BlinkMacSystemFont,
          "Segoe UI Variable Text", "Segoe UI", Inter, Roboto, "Helvetica Neue", system-ui, sans-serif;
}

/* ---------- 2. base + accessibility ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  height: 100%;
  background: var(--k-black);
  color: var(--k-text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.4;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color-scheme: dark;
}
body {
  margin: 0;
  min-height: 100%;
  overflow-x: hidden;
  -webkit-tap-highlight-color: transparent;
}
html.sheet-open { overflow: hidden; }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed; left: 12px; top: -60px; z-index: 50;
  padding: 10px 14px; border-radius: var(--r-chip);
  background: var(--k-plate-hi); color: var(--k-text);
  border: 1px solid var(--k-gold-text); text-decoration: none; font-weight: 600;
  transition: top var(--t-ui) var(--e-out);
}
.skip-link:focus { top: max(12px, env(safe-area-inset-top)); }

:focus-visible { outline: 2px solid var(--k-gold-text); outline-offset: 3px; }
[hidden] { display: none !important; }
button, a { touch-action: manipulation; }
button { font: inherit; color: inherit; }
html:not(.js) .js-only { display: none !important; }   /* controls that only work with scripting */
.noscript { margin: 16px; text-align: center; color: var(--k-text-2); font-size: 14px; }
.noscript a { color: var(--k-gold-text); }

/* ---------- 3. environment — light in fog behind the interface ---------- */
.env {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none; overflow: hidden;
  /* several blacks: warm at the top, graphite through the middle, charcoal below */
  background:
    radial-gradient(70% 46% at 50% 24%, rgba(201, 163, 90, 0.10) 0%, rgba(201, 163, 90, 0.035) 42%, transparent 72%),
    radial-gradient(60% 40% at 18% 92%, rgba(118, 126, 142, 0.07) 0%, transparent 65%),
    linear-gradient(180deg, var(--k-black-warm) 0%, #101013 40%, var(--k-charcoal) 68%, #0a0a0c 100%);
}
.env-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 3; }

/* light layers: `translate` answers the environment state, `transform` carries a
   very slow drift, `opacity` breathes — all composited, nothing repaints */
.env-layer {
  position: absolute; left: 50%; top: 50%; border-radius: 50%;
  pointer-events: none; will-change: transform, translate, opacity;
}
/* the centre of energy: a warm bloom behind the portrait and upper plate */
.env-bloom {
  z-index: 2; top: 27%;
  width: 96vmax; height: 96vmax; margin: -48vmax 0 0 -48vmax;
  background: radial-gradient(closest-side,
    rgba(236, 202, 128, 0.22) 0%,
    rgba(222, 188, 116, 0.13) 16%,
    rgba(206, 168, 96, 0.06) 34%,
    rgba(201, 163, 90, 0.018) 52%,
    transparent 70%);
  translate: calc(var(--ex) * 7vw) calc(var(--ey) * 5vh);
  animation: drift-a 36s ease-in-out infinite, breath-a 11s ease-in-out infinite;
}
/* a second, dimmer light low and to the right */
.env-bloom-2 {
  z-index: 1; left: 80%; top: 82%;
  width: 62vmax; height: 62vmax; margin: -31vmax 0 0 -31vmax;
  background: radial-gradient(closest-side,
    rgba(214, 178, 108, 0.11) 0%, rgba(201, 163, 90, 0.045) 35%, transparent 70%);
  translate: calc(var(--ex) * -4vw) calc(var(--ey) * -3vh);
  animation: drift-b 47s ease-in-out infinite;
}
/* a faint cool graphite counter-light, low left, for contrast */
.env-cool {
  z-index: 1; left: 12%; top: 88%;
  width: 58vmax; height: 58vmax; margin: -29vmax 0 0 -29vmax;
  background: radial-gradient(closest-side,
    rgba(132, 142, 164, 0.09) 0%, rgba(120, 128, 150, 0.035) 40%, transparent 70%);
  translate: calc(var(--ex) * -3vw) calc(var(--ey) * -2vh);
  animation: drift-c 58s ease-in-out infinite;
}
/* haze: two soft overlapping ellipses of warm fog, slowly flowing */
.env-haze {
  z-index: 2; top: 48%;
  width: 110vmax; height: 110vmax; margin: -55vmax 0 0 -55vmax;
  background:
    radial-gradient(38% 26% at 36% 44%, rgba(255, 244, 222, 0.045) 0%, transparent 70%),
    radial-gradient(44% 30% at 66% 58%, rgba(232, 208, 160, 0.04) 0%, transparent 70%);
  translate: calc(var(--ex) * 3vw) calc(var(--ey) * 2vh);
  animation: drift-d 41s ease-in-out infinite;
}
/* the lamp: the sharpest light, the one that follows the hand most */
.env-light {
  z-index: 4; top: 34%;
  width: 100vmax; height: 100vmax; margin: -50vmax 0 0 -50vmax;
  background: radial-gradient(closest-side,
    rgba(232, 200, 130, 0.13) 0%,
    rgba(217, 185, 112, 0.055) 20%,
    rgba(255, 255, 255, 0.016) 40%,
    transparent 62%);
  translate: calc(var(--ex) * 12vw) calc(var(--ey) * 9vh);
}
/* interaction impulse: a warm flash behind the plate that decays in ~0.4 s */
.env-flash {
  z-index: 5; top: 50%;
  width: 70vmax; height: 70vmax; margin: -35vmax 0 0 -35vmax;
  background: radial-gradient(closest-side, rgba(236, 206, 140, 0.28) 0%, rgba(217, 185, 112, 0.10) 35%, transparent 70%);
  opacity: calc(var(--imp) * 0.9);
  translate: calc(var(--ex) * 4vw) calc(var(--ey) * 3vh);
}
/* dimensional framing: corners recede, the centre stays luminous */
.env-vignette {
  position: absolute; inset: 0; z-index: 6;
  background:
    radial-gradient(120% 90% at 50% 40%, transparent 48%, rgba(4, 4, 5, 0.42) 82%, rgba(3, 3, 4, 0.7) 100%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.18) 0%, transparent 18%, transparent 82%, rgba(0, 0, 0, 0.3) 100%);
}

/* translate-only drift: a scaling or rotating layer re-rasterises, a moving
   one only composites — the difference is measurable on every device */
@keyframes drift-a {
  0%   { transform: translate(0, 0); }
  30%  { transform: translate(4vw, -3vh); }
  62%  { transform: translate(-3.5vw, 2vh); }
  100% { transform: translate(0, 0); }
}
@keyframes drift-b {
  0%   { transform: translate(0, 0); }
  40%  { transform: translate(-5vw, -4vh); }
  75%  { transform: translate(3vw, 3vh); }
  100% { transform: translate(0, 0); }
}
@keyframes drift-c {
  0%   { transform: translate(0, 0); }
  45%  { transform: translate(4vw, -3vh); }
  100% { transform: translate(0, 0); }
}
@keyframes drift-d {
  0%   { transform: translate(0, 0); }
  35%  { transform: translate(-4vw, 3vh); }
  70%  { transform: translate(4vw, -2vh); }
  100% { transform: translate(0, 0); }
}
@keyframes breath-a { 0%, 100% { opacity: 0.88; } 50% { opacity: 1; } }
@keyframes breath-b { 0%, 100% { opacity: 0.78; } 50% { opacity: 1; } }

/* ---------- 4. the plate ---------- */
.stage {
  position: relative; z-index: 1;
  min-height: 100vh;
  min-height: 100svh;
  display: grid; place-items: center; align-content: center;
  gap: var(--s-5);
  padding:
    max(var(--s-5), env(safe-area-inset-top))
    max(var(--s-4), env(safe-area-inset-right))
    max(var(--s-5), env(safe-area-inset-bottom))
    max(var(--s-4), env(safe-area-inset-left));
  transition: transform var(--t-panel) var(--e-out), filter var(--t-panel) var(--e-out);
}
html.sheet-open .stage { transform: scale(0.975) translateY(-4px); filter: brightness(0.62); }

.plate {
  position: relative;
  width: min(100%, 400px);
  padding: var(--s-7) var(--s-6) var(--s-4);
  border-radius: var(--r-plate);
  background: linear-gradient(168deg, var(--k-plate-hi) 0%, var(--k-graphite) 55%, var(--k-plate-lo) 100%);
  box-shadow:
    0 40px 90px -30px rgba(0, 0, 0, 0.9),
    0 2px 0 rgba(0, 0, 0, 0.7),
    0 0 0 1px rgba(0, 0, 0, 0.6),
    0 0 90px -20px rgba(201, 163, 90, 0.16);
  transform: perspective(1400px) rotateX(calc(var(--ey) * -1.5deg)) rotateY(calc(var(--ex) * 2deg));
  will-change: transform;
  isolation: isolate;
}
/* machined edge: a 1 px ring whose gold highlight travels with the light and
   brightens with an interaction impulse */
.plate-edge {
  position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  pointer-events: none; overflow: hidden;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  background: rgba(255, 255, 255, 0.07);
}
.plate-edge i {
  position: absolute; left: -50%; top: -50%; width: 200%; height: 200%;
  background: radial-gradient(34% 26% at 50% 26%,
    rgba(240, 220, 166, 0.95) 0%,
    rgba(222, 190, 118, 0.45) 26%,
    rgba(255, 255, 255, 0.14) 52%,
    rgba(255, 255, 255, 0.03) 100%);
  translate: calc(var(--ex) * 30%) calc(var(--ey) * 22%);
  opacity: calc(0.86 + var(--imp) * 0.14);
  animation: breath-b 13s ease-in-out infinite;
  will-change: translate;
}
/* satin sheen: a broad, faint reflection that slides across the surface */
.plate-sheen {
  position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none;
}
.plate-sheen::before {
  content: ""; position: absolute; left: -50%; top: -60%; width: 200%; height: 200%;
  background: radial-gradient(40% 32% at 50% 30%,
    rgba(255, 250, 235, 0.085) 0%, rgba(255, 250, 235, 0.03) 45%, transparent 70%);
  translate: calc(var(--ex) * 26%) calc(var(--ey) * 18%);
  will-change: translate;
}

.identity { text-align: center; margin-bottom: var(--s-6); }
.avatar {
  position: relative;
  width: 88px; height: 88px; margin: 0 auto var(--s-4);
  border-radius: 50%; padding: 3px;
  background:
    conic-gradient(from calc(210deg + var(--ex) * 70deg),
      var(--k-gold-deep) 0deg, var(--k-gold-hi) 70deg, var(--k-gold) 130deg,
      var(--k-gold-deep) 210deg, var(--k-gold) 300deg, var(--k-gold-deep) 360deg);
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(0, 0, 0, 0.7);
}
/* soft energy behind the portrait; it leans away from the light like a shadow would */
.avatar::before {
  content: ""; position: absolute; inset: -26px; border-radius: 50%; z-index: -1;
  background: radial-gradient(closest-side, rgba(236, 202, 128, 0.30) 0%, rgba(217, 185, 112, 0.10) 46%, transparent 72%);
  translate: calc(var(--ex) * -6px) calc(var(--ey) * -5px);
  opacity: calc(0.9 + var(--imp) * 0.1);
  animation: breath-a 9s ease-in-out infinite;
}
/* a specular highlight that moves around the ring with the light */
.avatar::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; padding: 3px; pointer-events: none;
  background: conic-gradient(from calc(-40deg + var(--ex) * 110deg + var(--ey) * -30deg),
    transparent 0deg, rgba(255, 248, 228, 0.9) 22deg, rgba(255, 248, 228, 0.35) 34deg, transparent 58deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
.avatar img {
  display: block; width: 100%; height: 100%; border-radius: 50%; object-fit: cover;
  background: #2a2a2e;
  box-shadow: inset 0 0 0 2px var(--k-graphite);
}
.name {
  margin: 0;
  font-size: 30px; line-height: 1.1; font-weight: 640; letter-spacing: -0.02em;
  color: var(--k-text);
}
.org {
  margin: var(--s-2) 0 0;
  display: flex; justify-content: center; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 500; color: var(--k-text-2); letter-spacing: 0.005em;
}
.org-sep { width: 3px; height: 3px; border-radius: 50%; background: var(--k-gold); opacity: 0.8; }
.descriptor {
  margin: var(--s-3) 0 0;
  font-size: 11px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--k-gold-text); opacity: 0.85;
}

.actions { display: grid; gap: var(--s-3); }
.quad { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-2); }
.links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); margin-top: var(--s-3); }

.plate-foot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: var(--s-4); padding-top: var(--s-3);
  border-top: 1px solid var(--k-line);
  min-height: 44px;
}
.plate-settings { display: flex; gap: var(--s-1); }
/* when no setting applies on this device, More sits centred like the identity above it */
.plate-foot:not(:has(.plate-settings > :not([hidden]))) { justify-content: center; }

/* maker's mark: the current identity (kayem.co with its gold period), small and quiet below the card */
.makers-mark {
  margin: 0; display: inline-flex; align-items: baseline; gap: 3px; opacity: 0.45;
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em; line-height: 1; color: var(--k-gold-text);
}
.makers-mark .mark-dot { width: 3px; height: 3px; border-radius: 50%; background: #fff6dc; box-shadow: 0 0 6px 1px rgba(240, 220, 166, 0.6); translate: 0 -1px; }

/* ---------- 5. buttons — the Kayem tactile primitive ----------
   Rest → hover → press (pressure enters the material at the touch point,
   edge light concentrates there) → held → release (spring back, a thin gold
   ring leaves the press point) → success / error (ring, sweep, label).
   Press-point origin lives in --px / --py (%), set by js/interaction.js. */
.kb {
  --kb-y: 0px;
  --kb-s: 1;
  --px: 50%;
  --py: 50%;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 52px; padding: 0 var(--s-4);
  border-radius: var(--r-control);
  border: 1px solid transparent;
  color: var(--k-text);
  font-size: 15px; font-weight: 600; letter-spacing: 0.005em; line-height: 1.2;
  text-decoration: none; text-align: center; cursor: pointer; user-select: none;
  -webkit-user-select: none;
  background:
    linear-gradient(180deg, #202024 0%, #17171a 100%) padding-box,
    linear-gradient(180deg, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0.05) 60%, rgba(0, 0, 0, 0.2) 100%) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 1.5px 0 rgba(0, 0, 0, 0.7),
    0 12px 22px -12px rgba(0, 0, 0, 0.95);
  transform: translateY(var(--kb-y)) scale(var(--kb-s));
  transition:
    transform var(--t-release) var(--e-release),
    box-shadow var(--t-release) var(--e-out),
    color var(--t-ui) ease,
    background-color var(--t-ui) ease;
  overflow: hidden;
  isolation: isolate;
}
/* sheen that follows the light (composited, no repaint) */
.kb::after {
  content: ""; position: absolute; left: -50%; top: -80%; width: 200%; height: 220%;
  border-radius: inherit; pointer-events: none;
  background: radial-gradient(35% 28% at 50% 34%, rgba(255, 250, 235, 0.11) 0%, transparent 70%);
  translate: calc(var(--ex) * 24%) calc(var(--ey) * 16%);
  opacity: 0.75;
  transition: opacity var(--t-ui) ease;
  z-index: -1;
}
/* feedback layers injected by js/interaction.js: pressure, ring, sweep */
.kb-fx { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; z-index: -1; }
.kb-press {
  position: absolute; left: var(--px); top: var(--py); width: 170%; aspect-ratio: 1;
  translate: -50% -50%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 250, 235, 0.17) 0%, rgba(255, 250, 235, 0.06) 32%, transparent 70%);
  opacity: 0; scale: 0.5;
  transition: opacity var(--t-release) var(--e-out), scale var(--t-release) var(--e-out);
}
.kb-ring {
  position: absolute; left: var(--px); top: var(--py); width: 30px; height: 30px;
  translate: -50% -50%; border-radius: 50%;
  border: 1px solid rgba(240, 220, 166, 0.95);
  box-shadow: 0 0 10px rgba(234, 211, 154, 0.35), inset 0 0 6px rgba(234, 211, 154, 0.25);
  opacity: 0;
}
.kb-sweep {
  position: absolute; top: -60%; bottom: -60%; left: -70%; width: 46%;
  rotate: 18deg; opacity: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255, 246, 222, 0.22) 45%, rgba(255, 246, 222, 0.34) 50%, rgba(255, 246, 222, 0.22) 55%, transparent 100%);
}
.kb-icon { width: 20px; height: 20px; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.kb-label { display: inline-block; transition: opacity var(--t-instant) ease, transform var(--t-instant) ease; }
.kb.is-swapping .kb-label { opacity: 0; transform: translateY(3px); }

@media (hover: hover) and (pointer: fine) {
  .kb:hover { --kb-y: -1px; }
  .kb:hover::after { opacity: 1; }
  .kb:not(.kb-primary):not(.kb-quiet):hover {
    background:
      linear-gradient(180deg, #232327 0%, #18181b 100%) padding-box,
      linear-gradient(180deg, rgba(255, 255, 255, 0.26) 0%, rgba(255, 255, 255, 0.07) 60%, rgba(0, 0, 0, 0.2) 100%) border-box;
  }
}
/* press: the surface moves inward, the shadow collapses, light concentrates
   at the touch point (edge and pressure highlight) */
.kb.is-pressed {
  --kb-y: 2px;
  --kb-s: 0.985;
  transition-duration: var(--t-press), var(--t-press), var(--t-ui), var(--t-ui);
  transition-timing-function: var(--e-press), var(--e-press), ease, ease;
  background:
    linear-gradient(180deg, #17171a 0%, #131316 100%) padding-box,
    radial-gradient(90% 130% at var(--px) var(--py), rgba(240, 220, 166, 0.55) 0%, rgba(255, 255, 255, 0.10) 40%, rgba(0, 0, 0, 0.25) 100%) border-box;
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(0, 0, 0, 0.3),
    0 0.5px 0 rgba(0, 0, 0, 0.6),
    0 2px 6px -4px rgba(0, 0, 0, 0.9);
}
.kb.is-pressed::after { opacity: 0.3; }
.kb.is-pressed .kb-press { opacity: 1; scale: 1; transition-duration: var(--t-press); }
/* release: a thin gold ring leaves the press point */
.kb.is-released .kb-ring { animation: kb-ring-out 560ms var(--e-out) both; }
@keyframes kb-ring-out {
  0%   { opacity: 0.95; scale: 0.2; }
  100% { opacity: 0;    scale: 3.4; }
}

/* outcomes: the whole edge warms, one ring leaves the surface, the label swaps */
.kb::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  border: 1px solid var(--k-gold-hi); opacity: 0; z-index: 1;
}
.kb.is-success::before { animation: kb-edge 760ms var(--e-out) both; }
.kb.is-success {
  background:
    linear-gradient(180deg, #242420 0%, #19191a 100%) padding-box,
    linear-gradient(180deg, rgba(240, 220, 166, 0.65) 0%, rgba(201, 163, 90, 0.25) 60%, rgba(0, 0, 0, 0.2) 100%) border-box;
}
.kb.is-success .kb-label { color: var(--k-gold-text); }
.kb.is-error {
  background:
    linear-gradient(180deg, #221c1c 0%, #1a1616 100%) padding-box,
    linear-gradient(180deg, rgba(255, 160, 150, 0.4) 0%, rgba(255, 160, 150, 0.12) 60%, rgba(0, 0, 0, 0.2) 100%) border-box;
}
@keyframes kb-edge {
  0%   { opacity: 0.95; transform: scale(1); }
  100% { opacity: 0;    transform: scale(1.06); }
}
/* action-specific completion: a light sweep (save), an outward radiation (share),
   a concentrated inward pulse (copy) */
.kb.fx-sweep .kb-sweep { animation: kb-sweep 680ms var(--e-out) 40ms both; }
@keyframes kb-sweep {
  0%   { opacity: 0; translate: 0 0; }
  18%  { opacity: 1; }
  100% { opacity: 0; translate: 380% 0; }
}
.kb.fx-outward .kb-ring { animation: kb-ring-far 820ms var(--e-out) both; }
@keyframes kb-ring-far {
  0%   { opacity: 0.9; scale: 0.3; border-width: 1.5px; }
  100% { opacity: 0;   scale: 6;   border-width: 0.5px; }
}
.kb.fx-inward .kb-ring { animation: kb-ring-in 520ms var(--e-in) both; }
@keyframes kb-ring-in {
  0%   { opacity: 0;   scale: 2.6; }
  35%  { opacity: 0.9; }
  100% { opacity: 0;   scale: 0.15; }
}

/* primary — satin champagne gold, dark ink */
.kb-primary {
  min-height: 56px; font-size: 16px; font-weight: 650; letter-spacing: 0.01em;
  color: #17120a;
  background:
    linear-gradient(180deg, #e8d296 0%, #d0ac60 42%, #b9934b 100%) padding-box,
    linear-gradient(180deg, #f7e9c2 0%, #a8843f 55%, #6b5224 100%) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    inset 0 -1px 0 rgba(0, 0, 0, 0.15),
    0 1.5px 0 #5a4520,
    0 16px 32px -12px rgba(201, 163, 90, 0.6),
    0 0 40px -14px rgba(236, 202, 128, 0.5);
}
.kb-primary::after {
  background: radial-gradient(35% 30% at 50% 30%, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
}
.kb-primary .kb-press {
  width: 140%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.30) 0%, rgba(255, 255, 255, 0.10) 32%, transparent 70%);
}
.kb-primary .kb-ring { border-color: rgba(255, 252, 240, 0.95); box-shadow: 0 0 10px rgba(255, 246, 220, 0.5); }
.kb-primary .kb-sweep {
  background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.28) 45%, rgba(255, 255, 255, 0.45) 50%, rgba(255, 255, 255, 0.28) 55%, transparent 100%);
}
@media (hover: hover) and (pointer: fine) {
  .kb-primary:hover {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.5),
      inset 0 -1px 0 rgba(0, 0, 0, 0.15),
      0 1.5px 0 #5a4520,
      0 18px 34px -12px rgba(201, 163, 90, 0.7),
      0 0 54px -12px rgba(236, 202, 128, 0.62);
  }
}
.kb-primary.is-pressed {
  background:
    linear-gradient(180deg, #d5b76c 0%, #c19f56 42%, #ad8a45 100%) padding-box,
    radial-gradient(90% 130% at var(--px) var(--py), rgba(255, 250, 230, 0.95) 0%, rgba(247, 233, 194, 0.4) 40%, #6b5224 100%) border-box;
  box-shadow:
    inset 0 2px 6px rgba(60, 40, 10, 0.5),
    inset 0 1px 0 rgba(0, 0, 0, 0.1),
    0 0.5px 0 #5a4520,
    0 4px 10px -8px rgba(201, 163, 90, 0.4),
    0 0 26px -12px rgba(236, 202, 128, 0.35);
}
.kb-primary.is-success {
  color: #17120a;
  background:
    linear-gradient(180deg, #f1dfaa 0%, #dab96f 42%, #bf9a50 100%) padding-box,
    linear-gradient(180deg, #fff6d8 0%, #b48d45 55%, #6b5224 100%) border-box;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    inset 0 -1px 0 rgba(0, 0, 0, 0.15),
    0 1.5px 0 #5a4520,
    0 18px 36px -12px rgba(201, 163, 90, 0.75),
    0 0 70px -10px rgba(236, 202, 128, 0.7);
}
.kb-primary.is-success .kb-label { color: #17120a; }
.kb-primary:focus-visible { outline-color: var(--k-gold-hi); }

/* stacked icon-over-label (the contact quad) */
.kb-stack { flex-direction: column; gap: 6px; min-height: 62px; padding: 8px 4px; font-size: 12.5px; font-weight: 600; }
.kb-stack .kb-icon { width: 21px; height: 21px; color: var(--k-text); }

/* chips — secondary links */
.kb-chip {
  min-height: 42px; padding: 0 6px; gap: 7px;
  border-radius: var(--r-chip);
  font-size: 12.5px; font-weight: 550; color: var(--k-text-2);
  background:
    linear-gradient(180deg, #18181b 0%, #131316 100%) padding-box,
    linear-gradient(180deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.035) 60%, rgba(0, 0, 0, 0.15) 100%) border-box;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.6), 0 6px 14px -10px rgba(0, 0, 0, 0.9);
}
.kb-chip .kb-icon { width: 16px; height: 16px; stroke-width: 1.6; opacity: 0.85; }
.kb-chip:hover { color: var(--k-text); }
.kb-chip .kb-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* quiet — text-level controls (More, Motion, Sound, Copy, Close) */
.kb-quiet {
  min-height: 40px; padding: 0 10px; gap: 8px; border-radius: var(--r-chip);
  font-size: 13px; font-weight: 550; color: var(--k-text-2);
  background: transparent; box-shadow: none;
}
.kb-quiet::after { display: none; }
.kb-quiet .kb-icon { width: 18px; height: 18px; }
.kb-quiet:hover { color: var(--k-text); background: rgba(255, 255, 255, 0.04); }
.kb-quiet.is-pressed { background: rgba(0, 0, 0, 0.35); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5); }
.kb-quiet .kb-press { background: radial-gradient(closest-side, rgba(255, 250, 235, 0.10) 0%, transparent 70%); }
.kb-quiet.is-success { background: rgba(201, 163, 90, 0.08); }
.kb-tiny { padding: 0 8px; font-size: 12px; }
.kb-icon-only { width: 40px; padding: 0; }
.kb-quiet[aria-pressed="true"] { color: var(--k-gold-text); }
.kb-quiet[aria-pressed="true"] .i-sound-off { display: none; }
.kb-quiet[aria-pressed="false"] .i-sound-wave { display: none; }
.kb-quiet.is-on { color: var(--k-gold-text); }

/* ---------- 6. detail sheet ---------- */
.sheet {
  position: fixed; inset: auto 0 0 0; margin: 0 auto;
  width: min(100%, 440px); max-height: min(88vh, 88dvh);
  padding: 0; border: 0; color: var(--k-text);
  background: transparent; overflow: visible;
}
.sheet:not([open]) { display: none; }
.sheet::backdrop { background: rgba(3, 3, 4, 0.55); }
.sheet[open]::backdrop { animation: sheet-veil var(--t-panel) var(--e-out) both; }
.sheet.is-closing::backdrop { animation: sheet-veil var(--t-ui) var(--e-in) reverse both; }
@keyframes sheet-veil { from { opacity: 0; } to { opacity: 1; } }

.sheet-body {
  position: relative;
  max-height: min(88vh, 88dvh); overflow-y: auto; overscroll-behavior: contain;
  padding: var(--s-5) var(--s-6) max(var(--s-6), env(safe-area-inset-bottom));
  border-radius: var(--r-plate) var(--r-plate) 0 0;
  background: linear-gradient(180deg, #1a1a1d 0%, #121214 100%);
  box-shadow: 0 -30px 80px -30px rgba(0, 0, 0, 0.9), inset 0 1px 0 rgba(255, 255, 255, 0.09), 0 0 80px -30px rgba(201, 163, 90, 0.25);
  animation: sheet-in var(--t-panel) var(--e-out) both;
}
.sheet.is-closing .sheet-body { animation: sheet-out var(--t-ui) var(--e-in) both; }
.sheet-body::before {
  content: ""; position: absolute; left: 50%; top: 8px; width: 36px; height: 3px; margin-left: -18px;
  border-radius: 2px; background: rgba(255, 255, 255, 0.14);
}
@keyframes sheet-in  { from { transform: translateY(28px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes sheet-out { from { transform: none; opacity: 1; } to { transform: translateY(24px); opacity: 0; } }

.sheet-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s-3); margin-top: var(--s-2); }
.sheet-title { margin: 0; font-size: 20px; font-weight: 640; letter-spacing: -0.015em; line-height: 1.2; }
.sheet-sub { margin: 4px 0 0; font-size: 14px; color: var(--k-text-2); }
.sheet-sub-2 { color: var(--k-text-3); }
.sheet-close { margin: -6px -8px 0 0; }
.sheet-about { margin: var(--s-4) 0 0; font-size: 14.5px; line-height: 1.5; color: var(--k-text-2); }

.sheet-rows { list-style: none; margin: var(--s-4) 0 0; padding: 0; border-top: 1px solid var(--k-line); }
.sheet-row {
  display: grid; grid-template-columns: 76px minmax(0, 1fr) 40px; align-items: center; gap: var(--s-2);
  min-height: 48px; padding: 4px 0; border-bottom: 1px solid var(--k-line);
}
.sheet-row-k { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--k-text-3); }
.sheet-row-v { font-size: 15px; color: var(--k-text); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 8px 0; }
.sheet-row-v:hover { color: var(--k-gold-text); }
.sheet-row-ext { width: 16px; height: 16px; margin: 0 auto; fill: none; stroke: var(--k-text-3); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sheet-note { margin: var(--s-4) 0 0; font-size: 12.5px; line-height: 1.5; color: var(--k-text-3); }
.sheet-actions { display: grid; gap: var(--s-2); margin-top: var(--s-5); }

.sheet-compact { width: min(100% - 32px, 380px); inset: auto 0 max(16px, env(safe-area-inset-bottom)) 0; }
.sheet-compact .sheet-body { border-radius: var(--r-plate); }
.sheet-compact .sheet-body::before { display: none; }

@media (min-width: 640px) {
  .sheet { inset: 0; margin: auto; max-height: none; width: min(100% - 48px, 420px); }
  .sheet-body { border-radius: var(--r-plate); max-height: 86vh; box-shadow: 0 40px 100px -30px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.09), 0 0 90px -30px rgba(201, 163, 90, 0.25); }
  .sheet-body::before { display: none; }
  @keyframes sheet-in  { from { transform: translateY(14px) scale(0.985); opacity: 0; } to { transform: none; opacity: 1; } }
  @keyframes sheet-out { from { transform: none; opacity: 1; } to { transform: translateY(10px) scale(0.99); opacity: 0; } }
}

/* ---------- 7. entrance ----------
   The environment exists first: it fades in from black while a point, two
   hairlines and the K mark play over it; then the plate arrives out of the
   dark. Nothing switches on afterwards. */
.intro {
  position: fixed; inset: 0; z-index: 20; display: none;
  pointer-events: none;
}
.intro-stage { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }

/* the cinematic identity: the COMPLETE "kayem.co" wordmark is centred on the
   viewport (flex row, translated by half its own size). Its period is the gold
   energy point — the origin of the hairlines and of the letters' motion — so
   the point sits a little right of centre, by design. Shared by the intro and
   the departure. */
.brand-word {
  position: absolute; left: 0; top: 0; translate: -50% -50%; margin: 0;
  display: flex; align-items: baseline; gap: 5px;
  font-family: var(--font); font-size: 26px; font-weight: 600; letter-spacing: 0.02em; line-height: 1;
  color: var(--k-text); white-space: nowrap; pointer-events: none;
  text-shadow: 0 0 18px rgba(240, 220, 166, 0.22);
}
.brand-word .w-a, .brand-word .w-b { opacity: 0; margin-right: -0.02em; }   /* no trailing tracking in the glyph box */
.brand-word .w-dot {
  position: relative; width: 6px; height: 6px; border-radius: 50%; translate: 0 -1px;
  background: #fff6dc;
  box-shadow: 0 0 14px 3px rgba(240, 220, 166, 0.7), 0 0 60px 14px rgba(217, 185, 112, 0.25);
  transform: scale(0); opacity: 0;
}
/* hairlines hang off the period and clear each word: "kayem" on the left
   (≈ 78 px incl. gap) and "co" on the right (≈ 36 px) — an intentionally
   asymmetric composition that stays balanced across the viewport */
.brand-word .w-line {
  position: absolute; top: 50%; height: 1px; width: min(30vw, 150px); margin-top: -0.5px;
  background: linear-gradient(90deg, rgba(240, 220, 166, 0.85), rgba(217, 185, 112, 0));
  transform: scaleX(0); opacity: 0;
}
.brand-word .w-line-l { right: calc(100% + 98px); transform-origin: right center; background: linear-gradient(270deg, rgba(240, 220, 166, 0.85), rgba(217, 185, 112, 0)); }
.brand-word .w-line-r { left: calc(100% + 50px); transform-origin: left center; }

/* ---------- 6b. entry gate ----------
   A fresh document opens here: the ambient environment stays alive behind a
   minimal card-less layer — kicker, Access Contact, "Tap to begin", a sound
   control. The tap is the first gesture (audio unlocks), a brief
   PREPARING EXPERIENCE hold follows, then the entrance plays. Removed with the
   html.gated class; never shown without JavaScript. */
.gate { position: fixed; inset: 0; z-index: 15; display: none; place-items: center; padding: 24px; overflow: hidden; }
html.gated .gate { display: grid; }
html.gated .stage, html.gated .makers-mark { visibility: hidden; }   /* the card waits behind the gate */
.stage:focus { outline: none; }   /* focus lands on the main region after entry; the card's controls carry the visible ring */
.gate-body {
  display: grid; justify-items: center; gap: 14px; text-align: center;
  transition: opacity 240ms ease, translate 240ms var(--e-out);
}
.gate-kicker { margin: 0 0 6px; font-size: 11px; font-weight: 600; letter-spacing: 0.24em; text-transform: uppercase; color: var(--k-gold-text); opacity: 0.85; }
.gate-enter { min-width: 228px; min-height: 56px; font-size: 16px; }
.gate-hint { margin: 0; font-size: 13px; letter-spacing: 0.04em; color: var(--k-text-3); }
.gate-sound { margin-top: 12px; }
.gate-staging {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%; margin: 0; white-space: nowrap;
  font-size: 12px; font-weight: 600; letter-spacing: 0.26em; text-transform: uppercase; color: var(--k-gold-text);
  opacity: 0; pointer-events: none;
}
.gate-staging::before {
  content: ""; display: block; width: 28px; height: 1px; margin: 0 auto 12px;
  background: linear-gradient(90deg, rgba(240, 220, 166, 0), rgba(240, 220, 166, 0.9), rgba(240, 220, 166, 0));
}
.gate.is-staging .gate-body { opacity: 0; translate: 0 -6px; pointer-events: none; }
.gate.is-staging .gate-staging { opacity: 1; transition: opacity 220ms ease 140ms; }
.gate.is-leaving { opacity: 0; transition: opacity 280ms ease; pointer-events: none; }
/* the environment already exists behind the gate: entering does not fade it in from black again */
html.from-gate.intro-full .env { animation: none; }
html.from-gate.intro-full .env-bloom { animation: drift-a 36s ease-in-out infinite, breath-a 11s ease-in-out infinite; }

/* ---------- 6c. gate arrival + idle — motion and light only ----------
   Silent, nothing new on screen, no layout change. Arrival (~1.4 s, once per
   fresh document, the intro's own language adapted to the gate): the
   environment resolves in from black and its bloom opens; a hairline of gold
   draws above the kicker and dissolves; the kicker settles its tracking;
   Access Contact rises into place under a warm halo; the hint and the sound
   control follow. Idle, as the settled continuation: the halo breathes on a
   5.5 s period, the lamp behind it pulses on the same period, and a satin
   light passes across the button every 7 s. Everything is opacity / translate /
   scale on existing boxes and pseudo-elements: composited, no repaint. */
html.gated .env { animation: env-in 1100ms ease-out both; }
html.gated .env-bloom { animation: drift-a 36s ease-in-out infinite, breath-a 11s ease-in-out infinite, bloom-in 1400ms var(--e-out) both; }
html.gated .env-light { animation: gate-lamp 5.5s ease-in-out 1620ms infinite; }
.gate-body { position: relative; --gate-halo-y: 63px; }   /* the halo centre = the button centre (kicker 15.4 + 6 + gap 14 + 28) */
.gate-body::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  left: 50%; top: var(--gate-halo-y); width: 440px; height: 230px; margin: -115px 0 0 -220px; border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(236, 202, 128, 0.24) 0%, rgba(222, 188, 116, 0.12) 30%, rgba(201, 163, 90, 0.04) 58%, transparent 100%);
  opacity: 0; will-change: opacity, transform;
}
.gate-body::after {
  content: ""; position: absolute; pointer-events: none;
  left: 50%; top: -24px; width: 140px; height: 1px; margin-left: -70px;
  background: linear-gradient(90deg, rgba(240, 220, 166, 0), rgba(240, 220, 166, 0.9), rgba(240, 220, 166, 0));
  transform: scaleX(0); opacity: 0;
}
html.gated .gate-body::before { animation: gate-halo-in 1200ms var(--e-out) 420ms both, gate-halo-breathe 5.5s ease-in-out 1620ms infinite; }
html.gated .gate-body::after { animation: gate-line 1100ms var(--e-out) 120ms both; }
html.gated .gate-kicker { animation: gate-kicker 900ms var(--e-out) 260ms both; }
html.gated .gate-enter { animation: gate-rise 820ms var(--e-out) 420ms both; }
html.gated .gate-hint { animation: gate-fade-up 700ms var(--e-out) 700ms both; }
html.gated .gate-sound { animation: gate-fade-up 700ms var(--e-out) 840ms both; }
html.gated .gate-enter .kb-sweep { animation: gate-sheen 7s ease-in-out 2400ms infinite; }
@keyframes gate-line {
  0%   { transform: scaleX(0); opacity: 0; }
  25%  { opacity: 1; }
  60%  { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}
@keyframes gate-kicker {
  0%   { opacity: 0; letter-spacing: 0.34em; translate: 0 4px; }
  100% { opacity: 0.85; letter-spacing: 0.24em; translate: 0 0; }
}
@keyframes gate-rise {
  0%   { opacity: 0; translate: 0 14px; }
  100% { opacity: 1; translate: 0 0; }
}
@keyframes gate-fade-up {
  0%   { opacity: 0; translate: 0 6px; }
  100% { opacity: 1; translate: 0 0; }
}
@keyframes gate-halo-in {
  0%   { opacity: 0; scale: 0.7; }
  100% { opacity: 1; scale: 1; }
}
@keyframes gate-halo-breathe {
  0%, 100% { opacity: 1;    scale: 1; }
  50%      { opacity: 0.62; scale: 0.965; }
}
@keyframes gate-lamp {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.88; }
}
@keyframes gate-sheen {
  0%   { opacity: 0;    translate: 0 0; }
  7%   { opacity: 0.55; }
  17%  { opacity: 0;    translate: 380% 0; }
  100% { opacity: 0;    translate: 380% 0; }
}

/* full entrance */
html.intro-full .intro { display: block; }
html.intro-full .env { animation: env-in 1500ms ease-out both; }
html.intro-full .env-bloom { animation: drift-a 36s ease-in-out infinite, breath-a 11s ease-in-out infinite, bloom-in 1400ms var(--e-out) both; }
html.intro-full .intro-word .w-dot { animation: intro-point 1400ms var(--e-out) 80ms both; }
html.intro-full .intro-word .w-a { animation: intro-word-a 880ms var(--e-out) 380ms both; }   /* resolved by ~640 ms, read until ~1060 ms, gone by 1260 ms */
html.intro-full .intro-word .w-b { animation: intro-word-b 880ms var(--e-out) 380ms both; }
html.intro-full .intro-word .w-line { animation: intro-line 880ms var(--e-out) 520ms both; }
html.intro-full .plate { animation: plate-in 680ms var(--e-out) 1200ms both; }               /* the card arrives as the wordmark has gone */
html.intro-full .makers-mark { animation: fade-in 900ms ease-out 1580ms both; }

/* skipped or finished: everything at rest */
html.intro-done .intro { display: none; }
html.intro-done .plate, html.intro-done .env, html.intro-done .makers-mark { animation: none; }
html.intro-done .env-bloom { animation: drift-a 36s ease-in-out infinite, breath-a 11s ease-in-out infinite; }

@keyframes intro-point {
  0%   { transform: scale(0); opacity: 0; }
  18%  { transform: scale(1); opacity: 1; }
  70%  { transform: scale(1); opacity: 1; }
  100% { transform: scale(0.4); opacity: 0; }
}
@keyframes intro-line {
  0%   { transform: scaleX(0); opacity: 0; }
  25%  { opacity: 1; }
  60%  { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}
/* the wordmark resolves outward from its period, holds to be read, then gives way to the plate */
@keyframes intro-word-a {
  0%   { opacity: 0; translate: 10px 0; letter-spacing: 0.14em; }
  30%  { opacity: 1; translate: 0 0; letter-spacing: 0.02em; }
  77%  { opacity: 1; translate: 0 0; }
  100% { opacity: 0; translate: -3px 0; letter-spacing: 0.02em; }
}
@keyframes intro-word-b {
  0%   { opacity: 0; translate: -10px 0; letter-spacing: 0.14em; }
  30%  { opacity: 1; translate: 0 0; letter-spacing: 0.02em; }
  77%  { opacity: 1; translate: 0 0; }
  100% { opacity: 0; translate: 3px 0; letter-spacing: 0.02em; }
}
@keyframes plate-in {
  from { opacity: 0; transform: perspective(1400px) translateY(14px) rotateX(2deg); }
  to   { opacity: 1; transform: perspective(1400px) translateY(0) rotateX(calc(var(--ey) * -1.5deg)) rotateY(calc(var(--ex) * 2deg)); }
}
@keyframes env-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes bloom-in { from { scale: 0.6; } to { scale: 1; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------- 7b. departure — the card leaves the way it arrived ----------
   Web destinations (~1100 ms), five phases:
     A   0–180    the plate withdraws into depth, its edge light and the portrait
                  glow retreat, the lamp and bloom gather inward, the hairlines
                  converge (canvas)
     B 120–330    a small gold rule resolves, "OPENING <DESTINATION>" emerges
                  above the centred wordmark, kayem.co resolves beneath it
     C 330–720    readable hold — nothing moves
     D 700–1060   the letters contract into the period, the hairlines draw in,
                  the announcement contracts away
     E 1100       navigation
   Contact apps (html.departing-app, ~650 ms): the same phases, compressed
   (resolved by ~215, hold to ~430, collapsed by ~600, hand-off at 650).
   Share (html.departing-share): phases A–C only — the composition holds until
   the native share sheet settles, then the card returns. */
.depart {
  position: fixed; inset: 0; z-index: 20; pointer-events: none;
}
.depart-stage { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }
.depart-word .w-line { transform: scaleX(1); }   /* departure lines contract inward from full length */
/* the announcement is the guide, the wordmark the signature: larger, clearly separated,
   centred on the same line; responsive size so OPENING SHARE SHEET fits from 320 px up */
.depart-text {
  position: absolute; left: 0; bottom: 44px; translate: -50% 0; margin: 0;
  text-align: center; white-space: nowrap; opacity: 0; max-width: calc(100vw - 32px);
  font-size: clamp(15px, 4.3vw, 19px); font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; line-height: 1.1;
}
@media (max-width: 300px) { .depart-text { white-space: normal; text-wrap: balance; } }
.depart-rule {
  display: block; width: 28px; height: 1px; margin: 0 auto 12px;
  background: linear-gradient(90deg, rgba(240, 220, 166, 0), rgba(240, 220, 166, 0.9), rgba(240, 220, 166, 0));
  transform: scaleX(0); opacity: 0;
}
.depart-kicker { color: var(--k-gold-text); opacity: 0.85; }
.depart-dest { color: var(--k-text); }

.depart.is-on .depart-rule { animation: depart-rule 140ms var(--e-out) 120ms both; }
.depart.is-on .depart-text { animation: depart-text 880ms linear 180ms both; }          /* in by 330, holds to ~900, gone by 1060 */
.depart.is-on .depart-word .w-line { animation: depart-line 860ms linear 160ms both; }  /* visible through the hold, draws in from ~745 */
.depart.is-on .depart-word .w-a { animation: depart-word-a 860ms linear 160ms both; }   /* resolved 320, holds to ~720, collapsed 1020 */
.depart.is-on .depart-word .w-b { animation: depart-word-b 860ms linear 160ms both; }
.depart.is-on .depart-word .w-dot { animation: depart-point 460ms var(--e-out) 200ms both; }
/* the wordmark resolves, holds still, then its letters contract into the period */
@keyframes depart-word-a {
  0%   { opacity: 0; translate: -6px 0; letter-spacing: 0.02em; animation-timing-function: var(--e-out); }
  19%  { opacity: 1; translate: 0 0; letter-spacing: 0.02em; animation-timing-function: linear; }
  65%  { opacity: 1; translate: 0 0; letter-spacing: 0.02em; animation-timing-function: var(--e-in); }
  100% { opacity: 0; translate: 16px 0; letter-spacing: -0.05em; }
}
@keyframes depart-word-b {
  0%   { opacity: 0; translate: 6px 0; letter-spacing: 0.02em; animation-timing-function: var(--e-out); }
  19%  { opacity: 1; translate: 0 0; letter-spacing: 0.02em; animation-timing-function: linear; }
  65%  { opacity: 1; translate: 0 0; letter-spacing: 0.02em; animation-timing-function: var(--e-in); }
  100% { opacity: 0; translate: -16px 0; letter-spacing: -0.05em; }
}
@keyframes depart-line {
  0%   { transform: scaleX(1); opacity: 0; animation-timing-function: ease; }
  12%  { transform: scaleX(1); opacity: 0.9; animation-timing-function: linear; }
  68%  { transform: scaleX(1); opacity: 0.9; animation-timing-function: var(--e-in); }
  100% { transform: scaleX(0); opacity: 0.4; }
}
@keyframes depart-point {
  0%   { transform: scale(0); opacity: 0; }
  55%  { transform: scale(1); opacity: 1; }
  100% { transform: scale(0.9); opacity: 1; }
}
@keyframes depart-rule { 0% { transform: scaleX(0); opacity: 0; } 100% { transform: scaleX(1); opacity: 1; } }
/* emerges from the same energy, holds still with the wordmark, then contracts away with it */
@keyframes depart-text {
  0%   { opacity: 0; translate: -50% 8px; letter-spacing: 0.28em; animation-timing-function: ease; }
  17%  { opacity: 1; translate: -50% 0; letter-spacing: 0.22em; animation-timing-function: linear; }
  82%  { opacity: 1; translate: -50% 0; letter-spacing: 0.22em; animation-timing-function: var(--e-in); }
  100% { opacity: 0; translate: -50% -4px; letter-spacing: 0.18em; }
}

/* native contact apps: the same phases, compressed to ~650 ms */
html.departing-app .depart.is-on .depart-rule { animation-duration: 110ms; animation-delay: 50ms; }
html.departing-app .depart.is-on .depart-text { animation-duration: 560ms; animation-delay: 110ms; }    /* in by 205, holds to ~580, gone by 670 */
html.departing-app .depart.is-on .depart-word .w-line,
html.departing-app .depart.is-on .depart-word .w-a,
html.departing-app .depart.is-on .depart-word .w-b { animation-duration: 530ms; animation-delay: 100ms; }   /* resolved 200, holds to ~445, collapsed 630 */
html.departing-app .depart.is-on .depart-word .w-dot { animation-duration: 260ms; animation-delay: 120ms; }
/* (plate / environment overrides for the app and share variants follow the generic
   html.departing rules further down, so they win the cascade) */

/* share: resolve and hold (no collapse) until the share sheet settles */
html.departing-share .depart.is-on .depart-rule { animation-duration: 110ms; animation-delay: 60ms; }
html.departing-share .depart.is-on .depart-text { animation: depart-text-hold 160ms ease 120ms both; }
html.departing-share .depart.is-on .depart-word .w-a { animation: depart-word-hold-a 170ms var(--e-out) 110ms both; }
html.departing-share .depart.is-on .depart-word .w-b { animation: depart-word-hold-b 170ms var(--e-out) 110ms both; }
html.departing-share .depart.is-on .depart-word .w-line { animation: depart-line-hold 200ms ease 110ms both; }
html.departing-share .depart.is-on .depart-word .w-dot { animation-duration: 260ms; animation-delay: 130ms; }
@keyframes depart-text-hold { 0% { opacity: 0; translate: -50% 8px; letter-spacing: 0.28em; } 100% { opacity: 1; translate: -50% 0; letter-spacing: 0.22em; } }
@keyframes depart-word-hold-a { 0% { opacity: 0; translate: -6px 0; } 100% { opacity: 1; translate: 0 0; } }
@keyframes depart-word-hold-b { 0% { opacity: 0; translate: 6px 0; } 100% { opacity: 1; translate: 0 0; } }
@keyframes depart-line-hold { 0% { transform: scaleX(1); opacity: 0; } 100% { transform: scaleX(1); opacity: 0.9; } }

html.departing .plate {
  transition: transform 320ms var(--e-in), opacity 220ms ease;
  transform: perspective(1400px) translateY(-6px) translateZ(-140px) rotateX(-3deg);
  opacity: 0;
}
html.departing .plate-edge i,
html.departing .avatar::before,
html.departing .avatar::after { opacity: 0; transition: opacity 240ms ease; }
html.departing .env-bloom,
html.departing .env-light {
  translate: 0 0; scale: 0.55;
  transition: translate 420ms var(--e-in), scale 420ms var(--e-in);
}
html.departing .env-haze,
html.departing .env-bloom-2,
html.departing .env-cool { opacity: 0.35; transition: opacity 400ms ease; }
html.departing .env-flash { opacity: 0.55; transition: opacity 180ms ease; }
html.departing .makers-mark { opacity: 0; transition: opacity 200ms ease; }
html.departing .stage { pointer-events: none; }
/* app / share variants: quicker plate and light, and for share the control stays put and hittable */
html.departing-app .plate { transition: transform 260ms var(--e-in), opacity 130ms ease; }
html.departing-app .env-bloom, html.departing-app .env-light { transition: translate 300ms var(--e-in), scale 300ms var(--e-in); }
html.departing-share .plate { transform: none; transition: opacity 130ms ease; }
html.departing-share .stage { pointer-events: auto; }   /* the share press must complete on the control */

/* ---------- 7d. contact flash — the destination's identity shines through on touch ----------
   For ~140 ms after pointer-down (js/interaction.js adds .is-contact) a control that
   carries --brand shows a small coloured bloom at the touch point and a coloured edge,
   then settles back into the normal dark pressed state; the release stays Kayem gold.
   data-brand="brand" (web destinations) vs "soft" (contact apps: quieter, semantic tones). */
.kb-contact {
  position: absolute; inset: -1px; border-radius: inherit; pointer-events: none; opacity: 0;
  background: radial-gradient(44% 70% at var(--px) var(--py), var(--brand-2, var(--brand)) 0%, var(--brand) 30%, transparent 58%);
  box-shadow: inset 0 0 0 1px var(--brand), inset 0 0 14px -6px var(--brand-2, var(--brand));
  transition: opacity 260ms var(--e-out);
}
.kb[data-brand] .kb-contact { display: block; }
.kb:not([data-brand]) .kb-contact { display: none; }
.kb[data-brand].is-contact .kb-contact { opacity: 0.5; transition-duration: 50ms; }
.kb[data-brand="soft"].is-contact .kb-contact { opacity: 0.28; }
.kb[data-brand="instagram"].is-contact .kb-contact {
  background: radial-gradient(52% 80% at var(--px) var(--py), var(--brand-3, var(--brand)) 0%, var(--brand) 26%, var(--brand-2, var(--brand)) 48%, transparent 64%);
  opacity: 0.48;
}
/* the contact pressure highlight takes the brand tint for the same instant */
.kb[data-brand].is-contact .kb-press { background: radial-gradient(closest-side, var(--brand-2, var(--brand)) 0%, transparent 70%); opacity: 0.35; }

/* ---------- 7c. sheet utilities (Replay Intro, Sound) ---------- */
.sheet-utils {
  display: flex; gap: var(--s-2);
  margin-top: var(--s-4); padding-top: var(--s-3);
  border-top: 1px solid var(--k-line);
}
.sheet-utils .kb { flex: 1 1 0; min-width: 0; }
.sheet-utils .kb .kb-label { white-space: nowrap; }

/* page volume: dark track, champagne fill, a thumb sized for a thumb; dims when Sound is off */
.sheet-volume { margin-top: var(--s-3); display: grid; gap: 2px; transition: opacity var(--t-ui) ease; }
.sheet-volume.is-off { opacity: 0.38; }
.sheet-volume-label {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--k-text-3);
}
.sheet-volume-label output { font-size: 13px; letter-spacing: 0.04em; color: var(--k-gold-text); font-variant-numeric: tabular-nums; }
.sheet-volume-range {
  -webkit-appearance: none; appearance: none; width: 100%; height: 44px; margin: 0; padding: 0;
  background: transparent; cursor: pointer; --fill: 50%;
}
.sheet-volume-range:disabled { cursor: default; }
.sheet-volume-range::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px;
  background: linear-gradient(90deg, var(--k-gold) 0, var(--k-gold) var(--fill), #202024 var(--fill), #202024 100%);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.04);
}
.sheet-volume-range::-moz-range-track { height: 4px; border-radius: 2px; background: #202024; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5); }
.sheet-volume-range::-moz-range-progress { height: 4px; border-radius: 2px; background: var(--k-gold); }
.sheet-volume-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 22px; height: 22px; margin-top: -9px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #f6efdc, #cdb06a 70%, #8a6d34);
  border: 1px solid rgba(255, 246, 220, 0.5);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6), 0 0 0 4px rgba(201, 163, 90, 0.12);
  transition: box-shadow var(--t-ui) ease, transform var(--t-press) var(--e-press);
}
.sheet-volume-range::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #f6efdc, #cdb06a 70%, #8a6d34);
  border: 1px solid rgba(255, 246, 220, 0.5);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6), 0 0 0 4px rgba(201, 163, 90, 0.12);
}
.sheet-volume-range:active::-webkit-slider-thumb { transform: scale(0.94); }
.sheet-volume-range:focus-visible { outline: none; }
.sheet-volume-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6), 0 0 0 3px var(--k-black), 0 0 0 5px var(--k-gold-text); }
.sheet-volume-range:focus-visible::-moz-range-thumb { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6), 0 0 0 3px var(--k-black), 0 0 0 5px var(--k-gold-text); }

/* ---------- 8. responsive ---------- */
@media (max-width: 360px) {
  .plate { padding: var(--s-6) var(--s-5) var(--s-3); }
  .name { font-size: 27px; }
  .descriptor { font-size: 10px; letter-spacing: 0.13em; white-space: nowrap; }
  .kb-stack { font-size: 12px; }
}
@media (max-height: 640px) and (orientation: portrait) {
  .stage { align-content: start; }
  .avatar { width: 76px; height: 76px; }
}
@media (orientation: landscape) and (max-height: 520px) {
  .stage { align-content: center; }
  .plate {
    width: min(100%, 700px);
    display: grid; grid-template-columns: 250px minmax(0, 1fr); column-gap: var(--s-6); align-items: center;
    padding: var(--s-5) var(--s-6);
  }
  .descriptor { font-size: 10px; letter-spacing: 0.1em; white-space: nowrap; }
  /* the ring and sheen are absolutely positioned: with auto placement their
     containing block is the whole plate, not a single grid cell */
  .plate-edge, .plate-sheen { grid-area: auto; }
  .identity { grid-column: 1; grid-row: 1 / span 3; margin: 0; }
  .actions, .links, .plate-foot { grid-column: 2; }
  .avatar { width: 72px; height: 72px; margin-bottom: var(--s-3); }
  .name { font-size: 24px; }
  .links { margin-top: var(--s-2); }
  .plate-foot { margin-top: var(--s-2); padding-top: var(--s-2); }
  .makers-mark { display: none; }
  .env-bloom { top: 40%; }
}
@media (min-width: 900px) {
  .plate { width: 420px; padding: 36px 28px 18px; }
  .name { font-size: 32px; }
}
/* phones: the plate covers most of the width, so the bloom sits a little
   higher and larger to stay visible above and around it */
@media (max-width: 700px) and (orientation: portrait) {
  .env-bloom { top: 21%; width: 120vmax; height: 120vmax; margin: -60vmax 0 0 -60vmax; }
  .env-light { top: 30%; }
}

/* ---------- adaptive tiers (set by js/app.js from device signals) ---------- */
html.tier-lite .env-haze, html.tier-lite .env-cool { display: none; }
html.tier-lite .env-bloom-2 { animation: none; }
html.tier-lite .env-layer { will-change: auto; }
html.tier-static .env-layer { animation: none !important; }

/* ---------- reduced motion: still, but still radiant ---------- */
@media (prefers-reduced-motion: reduce) {
  :root { --e-release: var(--e-out); --t-release: 160ms; }
  .plate { transform: none; }
  .env-layer, .plate-edge i, .plate-sheen::before, .avatar::before, .kb::after { translate: none; animation: none; }
  .avatar::after { background: conic-gradient(from -40deg, transparent 0deg, rgba(255, 248, 228, 0.9) 22deg, rgba(255, 248, 228, 0.35) 34deg, transparent 58deg); }
  .stage { transition: none; }
  .kb { transition-duration: var(--t-press); }
  .kb-press { transition-duration: var(--t-press); }
  .kb.is-released .kb-ring, .kb.fx-sweep .kb-sweep, .kb.fx-outward .kb-ring, .kb.fx-inward .kb-ring { animation: none; }
  .kb.is-success::before { animation-duration: 300ms; }
  .sheet[open]::backdrop, .sheet.is-closing::backdrop, .sheet-body, .sheet.is-closing .sheet-body { animation-duration: 1ms; }
  .kb-label { transition: none; }
}
html.reduced-motion { --e-release: var(--e-out); --t-release: 160ms; }
html.reduced-motion .plate { transform: none; }
html.reduced-motion .env-layer, html.reduced-motion .plate-edge i, html.reduced-motion .plate-sheen::before,
html.reduced-motion .avatar::before, html.reduced-motion .kb::after { translate: none; animation: none; }
html.reduced-motion .avatar::after { background: conic-gradient(from -40deg, transparent 0deg, rgba(255, 248, 228, 0.9) 22deg, rgba(255, 248, 228, 0.35) 34deg, transparent 58deg); }
html.reduced-motion .stage { transition: none; }
html.reduced-motion .kb, html.reduced-motion .kb-press { transition-duration: var(--t-press); }
html.reduced-motion .kb.is-released .kb-ring, html.reduced-motion .kb.fx-sweep .kb-sweep,
html.reduced-motion .kb.fx-outward .kb-ring, html.reduced-motion .kb.fx-inward .kb-ring { animation: none; }
html.reduced-motion .sheet[open]::backdrop, html.reduced-motion .sheet.is-closing::backdrop,
html.reduced-motion .sheet-body, html.reduced-motion .sheet.is-closing .sheet-body { animation-duration: 1ms; }
html.reduced-motion .kb-label { transition: none; }
html.reduced-motion .gate-body, html.reduced-motion .gate.is-staging .gate-staging, html.reduced-motion .gate.is-leaving { transition-duration: 1ms; transition-delay: 0ms; }
/* reduced motion gate: a light fade in, a still halo, no hairline, no loops (environment stays still as elsewhere) */
html.reduced-motion.gated .env, html.reduced-motion.gated .env-bloom, html.reduced-motion.gated .env-light { animation: none; }
html.reduced-motion.gated .gate-body::before { animation: none; opacity: 0.55; scale: 1; }
html.reduced-motion.gated .gate-body::after { animation: none; }
html.reduced-motion.gated .gate-kicker, html.reduced-motion.gated .gate-enter,
html.reduced-motion.gated .gate-hint, html.reduced-motion.gated .gate-sound { animation: fade-in 220ms ease-out; }
html.reduced-motion.gated .gate-enter .kb-sweep { animation: none; }
/* reduced motion departure: a brief static acknowledgment (announcement + rule), then navigate quickly */
html.reduced-motion .depart.is-on .depart-word .w-line, html.reduced-motion .depart.is-on .depart-word .w-dot,
html.reduced-motion .depart.is-on .depart-word .w-a, html.reduced-motion .depart.is-on .depart-word .w-b { animation: none; }
html.reduced-motion .depart.is-on .depart-word .w-a, html.reduced-motion .depart.is-on .depart-word .w-b { opacity: 1; }
html.reduced-motion .depart.is-on .depart-word .w-dot { transform: scale(1); opacity: 1; }
html.reduced-motion .depart.is-on .depart-text { animation: fade-in 90ms ease both; translate: -50% 0; letter-spacing: 0.22em; }
html.reduced-motion .depart.is-on .depart-rule { animation: none; transform: scaleX(1); opacity: 1; }
html.reduced-motion .kb-contact { transition-duration: 1ms; }   /* the contact flash is effectively instantaneous */
html.reduced-motion.departing .plate { transform: none; opacity: 0.08; transition: opacity 70ms ease; }   /* clears quickly beneath the announcement; no movement */
html.reduced-motion.departing .env-bloom, html.reduced-motion.departing .env-light { scale: 1; translate: none; transition: none; }
html.reduced-motion.departing .env-haze, html.reduced-motion.departing .env-bloom-2, html.reduced-motion.departing .env-cool { transition: none; }
