/* ══ qubie.css — the one design system ══════════════════════════════════════
 *
 * Extracted from the qubie.ml capture page 2026-07-27 and extended to carry the
 * whole funnel (landing, auth, dashboard). The pages it replaces were a
 * skeuomorphic System-7 pastiche — menubar, title bars, chiseled dialogs — a
 * completely different lane from the character the product actually ships.
 *
 * The system is one physical idea: THE KEYCAP. Qubie is a cube with a 3px ink
 * outline sitting proud of a white page, and every interactive surface here is
 * built from the same material.
 *
 *   proud    a key you can press — buttons, plan choices. Solid ink underside
 *            (`0 5px 0 ink`), and pressing collapses the travel to nothing.
 *   recessed the inverse — inputs are wells cut INTO the page, so the ink sits
 *            as an inset shadow instead of beneath. A form reads as sockets
 *            waiting for a key, which is why inputs and buttons can share a
 *            border weight without looking like the same control.
 *   flat     panels and meters: the outline, no travel. Structure, not affordance.
 *
 * Colour is chroma 0 on purpose. The only colour on the page comes from the
 * WebGL dispersion field (chroma.js) blooming around the cursor — the brand's
 * colour is light through a prism, so painting the UI would fight it.
 */

:root {
  /* avatar3d.mjs reads these two directly — do not rename */
  --face-bg: #ffffff;
  --face-outline: #121316;

  --ink: #121316;          /* 17.2:1 on white */
  --ink-2: #494a51;        /*  8.4:1 on white — body copy, not decoration */
  --ink-3: #595a61;        /*  6.7:1 on white — placeholders, still AA */
  --wall: #e9e9ef;         /* the toon shade band — the one non-white value */
  --sink: #f4f4f7;         /* inside of a recessed well */
  --ok: #157a3c;
  --bad: #b3261e;

  --line: 3px;             /* toon outline weight */
  --travel: 5px;           /* key travel */
  --r: 16px;               /* keycap radius */
  --r-lg: 22px;            /* panel radius */

  --font-d: "Gabarito", -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;

  /* fluid rhythm — generous between movements, tight within them */
  --gap: clamp(14px, 2vw, 20px);
  --bay: clamp(56px, 9vw, 104px);

  --ease: cubic-bezier(.16, 1, .3, 1);   /* ease-out-quint */

  /* semantic z-scale — never arbitrary */
  --z-field: 0;
  --z-page: 1;
  --z-nav: 10;
  --z-toast: 40;
}

* { box-sizing: border-box; margin: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  min-height: 100%;
  font-family: var(--font-d);
  font-weight: 500;
  color: var(--ink);
  background: #fff;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-underline-offset: 3px; text-decoration-thickness: 2px; }

/* ── the chromatic field: fullscreen shader behind everything ───────────── */
/* `--field` is how strongly the dispersion reads. 1 is right for a single
   non-scrolling screen (the waitlist), where the bloom IS the composition. On a
   long page the same value drags a saturated cloud behind every paragraph as
   you scroll, so content pages dial it back to a tint. */
:root { --field: 1; }
#chroma {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  z-index: var(--z-field);
  display: block;
  pointer-events: none;
  opacity: var(--field);
}
.page { position: relative; z-index: var(--z-page); }

/* ── type ────────────────────────────────────────────────────────────────── */
h1, h2, h3 { font-weight: 800; letter-spacing: -0.02em; line-height: 1.04; text-wrap: balance; }
h1 { font-size: clamp(2.5rem, 6.5vw, 4.25rem); }
h2 { font-size: clamp(1.75rem, 3.6vw, 2.6rem); }
h3 { font-size: clamp(1.12rem, 1.7vw, 1.3rem); letter-spacing: -0.015em; }
p  { text-wrap: pretty; }

.sub {
  color: var(--ink-2);
  font-size: clamp(1.02rem, 2.2vw, 1.18rem);
  line-height: 1.5;
  max-width: 46ch;
}
.fine { font-size: 14px; color: var(--ink-2); line-height: 1.5; }

/* ── nav: a plain wordmark row, no chrome ────────────────────────────────── */
.nav {
  position: relative; z-index: var(--z-nav);
  display: flex; align-items: center; gap: 16px;
  padding: 20px clamp(18px, 4vw, 40px);
}
.brand {
  display: inline-flex; align-items: center; gap: 10px;
  font-weight: 800; font-size: 20px; letter-spacing: -0.02em;
  text-decoration: none;
}
.brand img { width: 30px; height: 30px; display: block; }
.nav .spacer { flex: 1; }
.nav a.plain {
  font-weight: 700; font-size: 15.5px; color: var(--ink-2);
  text-decoration: none; padding: 8px 4px;
  transition: color .18s var(--ease);
}
.nav a.plain:hover { color: var(--ink); }
.nav a.plain { display: inline-flex; align-items: center; gap: 7px; }
.nav a.plain svg { width: 17px; height: 17px; display: block; flex: none; }
/* In-page section anchors are the first thing to go on a phone — GitHub and
   Sign in are destinations, these two are just scroll shortcuts, and four links
   plus the wordmark runs into the edge at 390px. */
@media (max-width: 620px) { .nav a.plain.sect { display: none; } }

/* ── THE KEYCAP: every button on the site ────────────────────────────────── */
.key {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: 700 16.5px/1 var(--font-d);
  letter-spacing: .005em;
  color: var(--ink);
  padding: 15px 22px;
  border: var(--line) solid var(--ink);
  border-radius: var(--r);
  /* toon cap face: flat white with ONE hard shade band, never a soft gradient */
  background: linear-gradient(180deg, #fff 0 68%, var(--wall) 68% 100%);
  box-shadow: 0 var(--travel) 0 var(--ink), 0 12px 18px -8px rgba(18, 19, 22, .34);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: transform .09s var(--ease), box-shadow .09s var(--ease);
}
.key:hover { transform: translateY(-1px); box-shadow: 0 6px 0 var(--ink), 0 14px 20px -8px rgba(18,19,22,.36); }
.key:active {
  transform: translateY(var(--travel));
  box-shadow: 0 0 0 var(--ink), 0 4px 8px -4px rgba(18, 19, 22, .35);
}
.key:focus-visible { outline: none; box-shadow: 0 var(--travel) 0 var(--ink), 0 0 0 4px #fff, 0 0 0 7px var(--ink); }
.key[disabled] { opacity: .45; cursor: default; transform: none; }
.key[disabled]:hover { transform: none; box-shadow: 0 var(--travel) 0 var(--ink); }
/* the one key that matters on a page: solid ink, the cube's own silhouette */
.key.solid {
  color: #fff;
  background: var(--ink);
  box-shadow: 0 var(--travel) 0 #000, 0 12px 20px -8px rgba(18, 19, 22, .45);
}
.key.solid:hover { box-shadow: 0 6px 0 #000, 0 14px 22px -8px rgba(18,19,22,.48); }
.key.solid:active { box-shadow: 0 0 0 #000, 0 4px 8px -4px rgba(18, 19, 22, .4); }
.key.solid:focus-visible { box-shadow: 0 var(--travel) 0 #000, 0 0 0 4px #fff, 0 0 0 7px var(--ink); }
.key.wide { width: 100%; }
.key.small { font-size: 15px; padding: 12px 16px; --travel: 4px; }

/* ── the recessed well: inputs are the keycap inverted ───────────────────── */
.well {
  display: block; width: 100%;
  font: 500 16.5px/1.2 var(--font-d);
  color: var(--ink);
  padding: 16px 16px 14px;
  border: var(--line) solid var(--ink);
  border-radius: 13px;
  background: var(--sink);
  box-shadow: inset 0 3px 0 rgba(18, 19, 22, .13);
  outline: none;
  transition: box-shadow .14s var(--ease), background .14s var(--ease);
}
.well::placeholder { color: var(--ink-3); }
.well:focus { background: #fff; box-shadow: inset 0 3px 0 rgba(18,19,22,.10), 0 0 0 4px #fff, 0 0 0 7px var(--ink); }
.well[readonly] { color: var(--ink-2); }

.fld { display: grid; gap: 8px; }
.fld > span { font-weight: 700; font-size: 14.5px; }

/* ── the capture key: input + submit sharing ONE cap (the qubie.ml original) */
.capture {
  display: flex; align-items: stretch;
  width: min(440px, 100%);
  border: var(--line) solid var(--ink);
  border-radius: var(--r);
  background: #fff;
  box-shadow: 0 var(--travel) 0 var(--ink), 0 12px 18px -8px rgba(18, 19, 22, .38);
  transition: transform .08s var(--ease), box-shadow .08s var(--ease);
}
.capture:focus-within { box-shadow: 0 var(--travel) 0 var(--ink), 0 0 0 4px #fff, 0 0 0 7px var(--ink); }
.capture:has(button:active) {
  transform: translateY(var(--travel));
  box-shadow: 0 0 0 var(--ink), 0 4px 8px -4px rgba(18, 19, 22, .35);
}
.capture input {
  flex: 1; min-width: 0;
  font: 500 16.5px/1 var(--font-d);
  color: var(--ink);
  padding: 17px 18px 15px;
  border: 0; border-radius: 13px 0 0 13px;
  background: transparent; outline: none;
}
.capture input::placeholder { color: var(--ink-3); }
.capture button {
  font: 700 17px/1 var(--font-d);
  color: var(--ink);
  padding: 0 22px;
  border: 0; border-left: var(--line) solid var(--ink);
  border-radius: 0 13px 13px 0;
  background: linear-gradient(180deg, #fff 0 68%, var(--wall) 68% 100%);
  cursor: pointer; white-space: nowrap;
}
.capture button:focus-visible { outline: 3px solid var(--ink); outline-offset: -6px; border-radius: 12px; }
.capture button:disabled { opacity: .6; cursor: default; }

/* ── chip: a keycap shrunk to a label. Not pressable, so it keeps the outline
   and a shallower underside but drops the travel and the hover lift. ─────── */
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 700; font-size: 14.5px;
  padding: 9px 14px 8px;
  border: 2px solid var(--ink); border-radius: 12px;
  background: #fff; color: var(--ink);
  box-shadow: 0 3px 0 var(--ink);
}
.chip img, .chip svg { width: 18px; height: 18px; display: block; flex: none; }
/* a chip that IS a link gets the press, because it does something */
a.chip { text-decoration: none; transition: transform .09s var(--ease), box-shadow .09s var(--ease); }
a.chip:hover { transform: translateY(-1px); box-shadow: 0 4px 0 var(--ink); }
a.chip:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
a.chip:focus-visible { outline: none; box-shadow: 0 3px 0 var(--ink), 0 0 0 3px #fff, 0 0 0 6px var(--ink); }
.chip .sep { color: var(--ink-2); font-weight: 500; }

/* ── panels: structure, not affordance — outline, minimal travel ─────────── */
.panel {
  border: var(--line) solid var(--ink);
  border-radius: var(--r-lg);
  background: #fff;
  box-shadow: 0 4px 0 var(--ink);
  padding: clamp(20px, 3vw, 30px);
}
.panel > h3 { margin-bottom: 6px; }

/* ── meters ──────────────────────────────────────────────────────────────── */
.meter-row { display: grid; gap: 8px; margin-top: 18px; }
.meter-lab { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 15px; }
.meter-lab b { font-weight: 700; }
.meter-lab span { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.meter {
  height: 16px;
  border: var(--line) solid var(--ink);
  border-radius: 999px;
  background: var(--sink);
  box-shadow: inset 0 2px 0 rgba(18, 19, 22, .12);
  overflow: hidden;
}
.meter i {
  display: block; height: 100%;
  background: linear-gradient(180deg, var(--ink) 0 62%, #2c2d34 62% 100%);
  border-radius: 999px 0 0 999px;
  transition: width .5s var(--ease);
}

/* ── badge: a tiny flat chip, no travel ──────────────────────────────────── */
.badge {
  display: inline-block;
  font-weight: 700; font-size: 13.5px;
  padding: 6px 12px;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--ink); color: #fff;
  white-space: nowrap;
}
.badge.free { background: #fff; color: var(--ink); }

/* ── messages ────────────────────────────────────────────────────────────── */
.note { min-height: 22px; font-size: 15px; font-weight: 500; color: var(--ink-2); }
.note.ok { color: var(--ok); }
.note.err { color: var(--bad); }

.msg {
  display: none;
  font-size: 15px; font-weight: 500; line-height: 1.45;
  padding: 13px 15px;
  border: var(--line) solid var(--bad);
  border-radius: 13px;
  background: #fdf3f2; color: #8f1d17;
}
.msg.show { display: block; }

.toast {
  position: fixed; z-index: var(--z-toast);
  left: 50%; bottom: 26px;
  transform: translate(-50%, 20px);
  font-weight: 700; font-size: 15px;
  padding: 13px 20px;
  border: var(--line) solid var(--ink);
  border-radius: var(--r);
  background: var(--ink); color: #fff;
  box-shadow: 0 var(--travel) 0 #000, 0 14px 24px -10px rgba(18, 19, 22, .5);
  opacity: 0; pointer-events: none;
  transition: opacity .28s var(--ease), transform .28s var(--ease);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.bad { background: var(--bad); border-color: var(--bad); box-shadow: 0 var(--travel) 0 #7d1a14; }

/* ── the waitlist sheet: a keycap that opened ────────────────────────────── */
/* Native <dialog>, so focus trapping, Esc, the top layer and an inert page all
   come from the platform instead of from us. It renders in the top layer, which
   is also why no z-index appears here — nothing can stack above it. */
dialog.sheet {
  /* `* { margin: 0 }` above wipes the UA's `margin: auto`, which is the ONLY
     thing centring a modal <dialog> in the top layer — without this it pins to
     the top-left corner. Restore it explicitly rather than exempting dialog
     from the reset. */
  margin: auto;
  position: relative;   /* the close key is positioned against this box */
  width: min(430px, calc(100vw - 32px));
  padding: clamp(24px, 4vw, 32px);
  border: var(--line) solid var(--ink);
  border-radius: var(--r-lg);
  background: #fff;
  color: var(--ink);
  box-shadow: 0 var(--travel) 0 var(--ink), 0 30px 60px -24px rgba(18, 19, 22, .5);
  text-align: center;
  overflow: visible;
}
dialog.sheet::backdrop { background: rgba(18, 19, 22, .34); backdrop-filter: blur(3px); }
/* the sheet arrives like a key being pressed down onto the page */
@keyframes sheet-in { from { opacity: 0; transform: translateY(-14px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes veil-in  { from { opacity: 0; } to { opacity: 1; } }
dialog.sheet[open] { animation: sheet-in .3s var(--ease); }
dialog.sheet[open]::backdrop { animation: veil-in .3s var(--ease); }
dialog.sheet h3 { font-size: clamp(1.4rem, 4vw, 1.75rem); margin-bottom: 8px; }
dialog.sheet .sub { font-size: 15.5px; margin: 0 auto 20px; max-width: 34ch; }
dialog.sheet .capture { margin-inline: auto; }
dialog.sheet .note { margin-top: 14px; }
/* the close key sits proud on the sheet's own corner */
dialog.sheet .x {
  position: absolute; top: -14px; right: -14px;
  width: 38px; height: 38px; padding: 0;
  font: 700 19px/1 var(--font-d);
  border: var(--line) solid var(--ink); border-radius: 50%;
  background: #fff; color: var(--ink);
  box-shadow: 0 3px 0 var(--ink);
  cursor: pointer;
  transition: transform .09s var(--ease), box-shadow .09s var(--ease);
}
dialog.sheet .x:active { transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }
dialog.sheet .x:focus-visible { outline: none; box-shadow: 0 3px 0 var(--ink), 0 0 0 4px #fff, 0 0 0 7px var(--ink); }
@media (max-width: 480px) { dialog.sheet .x { top: -12px; right: -6px; } }
@media (prefers-reduced-motion: reduce) {
  dialog.sheet[open], dialog.sheet[open]::backdrop { animation: none; }
  dialog.sheet .x { transition: none; }
}

/* ── the character (buddy.js DOM contract, verbatim from the app) ────────── */
.qub-stage { position: relative; height: 224px; display: grid; place-items: center; }
.qub-scale { position: relative; transform: scale(1.45); transform-origin: center; }
.qub-shadow {
  position: absolute; left: 50%; bottom: -8px;
  width: 96px; height: 14px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(18,19,22,.32), rgba(18,19,22,.10) 62%, transparent 100%);
  animation: shadowbob 4.4s ease-in-out infinite;
  pointer-events: none;
}
@keyframes shadowbob {
  0%, 100% { transform: translateX(-50%) scaleX(1); opacity: 1; }
  50%      { transform: translateX(-50%) scaleX(.88); opacity: .72; }
}
#self-cube { position: relative; width: 132px; height: 132px; cursor: pointer; }
#self-cube .sc-cube { position: absolute; inset: 0; }
#self-cube .sc-face { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.sc-face svg { display: block; width: 100%; height: 100%; }
.vs-hand {
  position: absolute; left: 0; top: 0;
  width: 30px; height: 40px;
  pointer-events: none; opacity: 0;
  transform-origin: 15px 20px;
  transform: translate(var(--hx,51px), var(--hy,120px)) rotate(var(--hr,0deg)) scale(var(--hs,0));
  transition: transform .3s cubic-bezier(.34,1.45,.4,1);
}

/* ── layout helpers ──────────────────────────────────────────────────────── */
.wrap { width: min(1080px, 100%); margin-inline: auto; padding-inline: clamp(18px, 4vw, 40px); }
.narrow { width: min(430px, 100%); margin-inline: auto; }
.stack { display: grid; gap: var(--gap); }
.center-page { display: grid; place-items: center; min-height: calc(100dvh - 74px); padding: 28px 18px 56px; }

@media (max-width: 560px) {
  .qub-stage { height: 200px; }
  .qub-scale { transform: scale(1.25); }
  .capture input { padding: 16px 14px 14px; }
  .capture button { padding: 0 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .qub-shadow { animation: none; }
  .key, .well, .capture, .vs-hand, .meter i, .toast { transition: none; }
  .key:hover { transform: none; }
}
