/* Chatte Violet — landing page styles */

/* ── Tokens ──────────────────────────────────────────────── */
:root {
  --bg:       #0b0614;
  --fg:       #e8dcff;
  --plum:     #3d1a5b;
  --violet:   #7a3fc8;
  --lilac:    #c8a0ff;
  --on-lilac: #1a0b2e;

  --label-2:    rgba(232, 220, 255, 0.66);
  --label-3:    rgba(232, 220, 255, 0.42);
  --fill:       rgba(232, 220, 255, 0.07);
  --fill-press: rgba(232, 220, 255, 0.14);
  --ring:       rgba(232, 220, 255, 0.08);
  --sep:        rgba(232, 220, 255, 0.14);
  --material:       rgba(22, 12, 36, 0.55);
  --material-solid: #170c28;

  --font: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-rounded: ui-rounded, 'SF Pro Rounded', var(--font);

  /* 1% of the visible height (svh below, where supported): sizes follow the
     screen so every link stays above the fold, even on an iPhone SE */
  --vh: 1vh;
  --gap-s: clamp(0.5rem, calc(var(--vh) * 1.5), 1rem);
  --gap-l: clamp(1rem, calc(var(--vh) * 3), 1.75rem);

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* Springs in Apple terms. Fallbacks first, exact curves below. */
  --spring:        var(--ease-out);                       /* damping 1, response 0.5 */
  --spring-bounce: cubic-bezier(0.34, 1.4, 0.64, 1);      /* damping 0.72, response 0.35 */
}

@supports (height: 1svh) {
  :root { --vh: 1svh; }
}

@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring: linear(0, 0.068, 0.208, 0.362, 0.504, 0.624, 0.72, 0.795, 0.851, 0.893, 0.924, 0.946, 0.962, 0.973, 0.981, 0.987, 0.991, 0.994, 0.996, 0.997, 1);
    --spring-bounce: linear(0, 0.024, 0.087, 0.174, 0.275, 0.38, 0.484, 0.582, 0.671, 0.75, 0.818, 0.875, 0.922, 0.958, 0.987, 1.007, 1.022, 1.031, 1.036, 1.038, 1.038, 1.036, 1.033, 1.029, 1.025, 1.021, 1.017, 1.014, 1.011, 1.008, 1.005, 1.004, 1);
  }
}

/* ── Base ────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  background-color: var(--bg);
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  padding:
    max(1.25rem, env(safe-area-inset-top))
    max(1.25rem, env(safe-area-inset-right))
    max(1.25rem, env(safe-area-inset-bottom))
    max(1.25rem, env(safe-area-inset-left));
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.47;
  letter-spacing: -0.01em;
  color: var(--fg);
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-tap-highlight-color: transparent;
}

/* Ambient light: painted once, fixed so it stays put while scrolling */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(max(130vw, 40rem) 60vh at 50% -8%, rgba(122, 63, 200, 0.42), transparent 70%),
    radial-gradient(90vmax 50vmax at 0% 100%, rgba(61, 26, 91, 0.55), transparent 70%),
    radial-gradient(70vmax 40vmax at 100% 100%, rgba(200, 160, 255, 0.08), transparent 70%);
}

/* Fine grain removes banding from the dark gradients */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px;
  opacity: 0.045;
}

a { color: inherit; }

svg { display: block; flex: none; }

:focus-visible {
  outline: 2px solid var(--lilac);
  outline-offset: 3px;
}

/* ── Layout ──────────────────────────────────────────────── */
/* Mobile first: the base is a phone held upright. Content sits straight on
   the background, edge to edge; the glass card appears only on larger
   screens (see "Larger screens" below). */
.main {
  flex: 1;
  display: grid;
  place-items: center;
  width: 100%;
}

.card {
  position: relative;
  width: 100%;
  max-width: 24rem;
  text-align: center;
}

.card > * { position: relative; }

.foot {
  padding-top: var(--gap-l);
  text-align: center;
  font-size: 0.75rem;
  line-height: 1.3;
  letter-spacing: 0;
  color: var(--label-2);
}

/* ── Profile ─────────────────────────────────────────────── */
/* portrait poster; the initials behind it show only if the photo fails */
.avatar {
  --avatar-h: clamp(6.5rem, calc(var(--vh) * 24), 13.5rem);
  position: relative;
  display: grid;
  place-items: center;
  width: calc(var(--avatar-h) * 0.75);   /* 3:4 portrait */
  height: var(--avatar-h);
  margin: 0 auto var(--gap-l);
  overflow: hidden;
  border-radius: 1.5rem;
  background: linear-gradient(160deg, var(--violet), var(--plum));
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.16),
    0 12px 32px -10px rgba(8, 2, 20, 0.8);
  font-family: var(--font-rounded);
  font-weight: 600;
  font-size: 2.25rem;
  color: #fff;
}

.avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.name {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-weight: 700;
  font-size: 1.75rem;
  line-height: 1.15;
  letter-spacing: -0.022em;
}

.accent {
  background: linear-gradient(100deg, #e3cfff 0%, var(--lilac) 45%, #a77bf0 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.seal { width: 1.25rem; height: 1.25rem; }

.handle {
  margin-top: 0.25rem;
  font-size: 0.9375rem;
  color: var(--label-2);
}

/* one sentence per line, each balanced on its own */
.bio {
  margin-top: var(--gap-s);
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--label-2);
}

.bio span {
  display: block;
  text-wrap: balance;
}

.links { margin-top: var(--gap-l); }

/* ── Primary button ──────────────────────────────────────── */
.btn {
  --glow: rgba(255, 255, 255, 0.6);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  min-height: clamp(3.25rem, calc(var(--vh) * 7), 3.5rem);
  padding: 0.75rem 1.25rem;
  border-radius: 1.25rem;
  background: linear-gradient(180deg, var(--fg), var(--lilac));
  color: var(--on-lilac);
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.2;
  letter-spacing: -0.015em;
  text-decoration: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 0 rgba(61, 26, 91, 0.18),
    0 10px 30px -10px rgba(200, 160, 255, 0.55);
  transition: scale 450ms var(--spring-bounce), filter 250ms var(--ease-out);
}

/* press responds on pointer-down; release settles with a small spring */
.btn:active {
  scale: 0.97;
  filter: brightness(0.94);
  transition: scale 100ms var(--ease-out), filter 0ms;
}

.btn svg { width: 1.125rem; height: 1.125rem; }

button.btn {
  font-family: inherit;
  border: 0;
  cursor: pointer;
}

/* secondary button: same shape, quieter material */
.btn--plain {
  --glow: rgba(200, 160, 255, 0.18);
  background: rgba(232, 220, 255, 0.1);
  color: var(--fg);
  box-shadow: inset 0 0 0 1px var(--ring);
}

.btn--plain:active { filter: brightness(1.25); }

/* one-time light sweep after the page settles */
.shine {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  z-index: -1;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.7), transparent);
  transform: skewX(-18deg);
  pointer-events: none;
}

/* soft highlight that follows the pointer (position set in main.js) */
.glow::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(180px circle at var(--x, 50%) var(--y, 50%), var(--glow), transparent 70%);
  opacity: 0;
  transition: opacity 300ms var(--ease-out);
}

@media (hover: hover) {
  .glow:hover::before { opacity: 1; }
}

/* ── Grouped list (iOS inset style) ──────────────────────── */
.group {
  margin-top: var(--gap-s);
  overflow: hidden;
  list-style: none;
  border-radius: 1.25rem;
  background: var(--fill);
  box-shadow: inset 0 0 0 1px rgba(232, 220, 255, 0.05);
  text-align: left;
}

.row {
  --glow: rgba(200, 160, 255, 0.18);
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 1.875rem 1fr auto;
  align-items: center;
  column-gap: 0.875rem;
  min-height: 3.5rem;
  padding: clamp(0.5rem, calc(var(--vh) * 1.2), 0.625rem) 1rem;
  padding-left: 0.875rem;
  text-decoration: none;
  transition: background-color 300ms var(--ease-out);
}

.row:active {
  background-color: var(--fill-press);
  transition-duration: 0ms;
}

.row:focus-visible {
  outline-offset: -4px;
  border-radius: 1rem;
}

/* inset separator, aligned with the text like iOS */
li + li > .row::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  left: 3.625rem;
  border-top: 0.5px solid var(--sep);
}

.tile {
  display: grid;
  place-items: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 0.5rem;
  background: linear-gradient(180deg, var(--lilac), var(--violet));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
  color: #fff;
}

.group li:nth-child(3n+2) .tile { background: linear-gradient(180deg, var(--violet), var(--plum)); }
.group li:nth-child(3n)   .tile { background: linear-gradient(180deg, var(--fg), var(--lilac)); color: var(--on-lilac); }

.tile svg { width: 1.125rem; height: 1.125rem; }

.row__text {
  display: grid;
  gap: 0.125rem;
  min-width: 0;
}

.row__title {
  font-weight: 500;
  font-size: 1.0625rem;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

.row__note {
  font-size: 0.8125rem;
  line-height: 1.3;
  letter-spacing: 0;
  color: var(--label-2);
}

.chev {
  width: 0.5rem;
  height: 0.875rem;
  color: var(--label-3);
}

/* ── Content notice (dialog) ─────────────────────────────── */
html:has(.notice[open]) { overflow: hidden; }

/* radii are concentric: notice = button (1.25rem) + padding (1rem) */
.notice {
  width: min(100% - 2rem, 21rem);
  max-width: none;
  max-height: calc(100dvh - 2rem);
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: 2.25rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(26, 14, 44, 0.86);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  backdrop-filter: blur(40px) saturate(180%);
  color: var(--fg);
  text-align: center;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 0 0 1px rgba(232, 220, 255, 0.08),
    0 40px 100px -20px rgba(0, 0, 0, 0.8);
}

/* the dialog takes focus on open, like an iOS alert: no ring on the
   container; Tab still reaches the buttons with their own ring */
.notice:focus-visible { outline: none; }

.notice::backdrop {
  background: rgba(6, 3, 12, 0.62);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.notice__body { padding: 1.75rem 1rem 1rem; }

.notice__text {
  padding-inline: 0.75rem;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* iOS alert: cancel on the left, action on the right */
.notice__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.625rem;
  margin-top: 1.5rem;
}

.notice .btn { min-height: 3.25rem; }

/* ── Larger screens ──────────────────────────────────────── */
/* Tablet and desktop: the content floats on a glass card.
   Radii are concentric: card = inner (1.25rem) + padding (1rem). */
@media (min-width: 36rem) and (min-height: 40rem) {
  .card {
    max-width: 25rem;
    padding: 2rem 1rem 1rem;
    border-radius: 2.25rem;
    background: var(--material);
    -webkit-backdrop-filter: blur(40px) saturate(180%);
    backdrop-filter: blur(40px) saturate(180%);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.16),
      inset 0 0 0 1px rgba(232, 220, 255, 0.06),
      0 2px 6px rgba(8, 2, 20, 0.25),
      0 32px 80px -24px rgba(8, 2, 20, 0.7);
  }

  /* rim that catches the light from above */
  .card::before {
    content: '';
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0.03) 45%, rgba(255, 255, 255, 0.08));
    -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 exclude, linear-gradient(#000 0 0);
    pointer-events: none;
  }

  @media (prefers-reduced-transparency: reduce) {
    .card {
      background: var(--material-solid);
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
  }

  @media (prefers-contrast: more) {
    .card {
      background: var(--material-solid);
      box-shadow: inset 0 0 0 1px rgba(232, 220, 255, 0.5), 0 32px 80px -24px rgba(8, 2, 20, 0.7);
    }
  }

  @media (forced-colors: active) {
    .card { border: 1px solid CanvasText; }
  }
}

/* Phone on its side: profile and links side by side, so the links stay in
   view instead of falling below a 320–430px tall screen. */
@media (orientation: landscape) and (max-height: 31.25rem) {
  .card {
    display: flex;
    align-items: center;
    gap: clamp(1.5rem, 5vw, 3rem);
    max-width: 48rem;
  }

  .profile { flex: 1 1 0; min-width: 0; }

  .avatar {
    --avatar-h: clamp(6rem, calc(var(--vh) * 40), 11rem);
    margin-bottom: var(--gap-s);
  }

  .links {
    flex: 1.2 1 0;
    min-width: 0;
    margin-top: 0;
  }
}

/* ── Motion ──────────────────────────────────────────────── */
/* "backwards" fill only: once settled, nothing overrides press feedback */
@media (prefers-reduced-motion: no-preference) {
  .profile > *,
  .links {
    animation: rise 800ms var(--spring) backwards;
    animation-delay: calc(var(--base, 0ms) + var(--i, 0) * 70ms);
  }

  .profile > :nth-child(2) { --i: 1; }
  .profile > :nth-child(3) { --i: 2; }
  .profile > :nth-child(4) { --i: 3; }
  .links { --i: 4; }

  /* the glass thickens as it arrives */
  .card {
    --base: 140ms;
    animation: materialize 900ms var(--spring) backwards;
  }

  .foot { animation: fade 600ms var(--ease-out) 350ms backwards; }

  .shine { animation: sweep 1.1s cubic-bezier(0.45, 0, 0.55, 1) 1s backwards; }

  /* notice grows in and shrinks out along the same path */
  .notice {
    opacity: 0;
    scale: 0.94;
    transition:
      opacity 180ms ease-in,
      scale 180ms ease-in,
      overlay 180ms allow-discrete,
      display 180ms allow-discrete;
  }

  .notice[open] {
    opacity: 1;
    scale: 1;
    transition:
      opacity 250ms var(--ease-out),
      scale 600ms var(--spring),
      overlay 600ms allow-discrete,
      display 600ms allow-discrete;
  }

  .notice::backdrop {
    opacity: 0;
    transition:
      opacity 200ms ease-in,
      overlay 200ms allow-discrete,
      display 200ms allow-discrete;
  }

  .notice[open]::backdrop {
    opacity: 1;
    transition-duration: 300ms;
    transition-timing-function: var(--ease-out);
  }

  @starting-style {
    .notice[open] { opacity: 0; scale: 0.94; }
    .notice[open]::backdrop { opacity: 0; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .profile > *,
  .links,
  .card,
  .foot { animation: fade 300ms ease-out backwards; }

  .btn { transition: filter 250ms var(--ease-out); }
  .btn:active { scale: none; }
}

@keyframes rise {
  from { opacity: 0; translate: 0 14px; }
}

@keyframes materialize {
  from {
    opacity: 0;
    translate: 0 20px;
    scale: 0.96;
    -webkit-backdrop-filter: blur(0px) saturate(100%);
    backdrop-filter: blur(0px) saturate(100%);
  }
}

@keyframes fade {
  from { opacity: 0; }
}

@keyframes sweep {
  from { transform: translateX(0) skewX(-18deg); }
  to   { transform: translateX(380%) skewX(-18deg); }
}

/* ── Accessibility preferences ───────────────────────────── */
@media (prefers-reduced-transparency: reduce) {
  .notice {
    background: var(--material-solid);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .notice::backdrop {
    background: rgba(6, 3, 12, 0.85);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

@media (prefers-contrast: more) {
  :root {
    --label-2: rgba(232, 220, 255, 0.85);
    --label-3: rgba(232, 220, 255, 0.6);
    --sep:     rgba(232, 220, 255, 0.35);
    --ring:    rgba(232, 220, 255, 0.4);
  }
  .notice {
    background: var(--material-solid);
    box-shadow: inset 0 0 0 1px rgba(232, 220, 255, 0.5), 0 32px 80px -24px rgba(8, 2, 20, 0.7);
  }
  .group { box-shadow: inset 0 0 0 1px rgba(232, 220, 255, 0.3); }
}

@media (forced-colors: active) {
  .btn,
  .notice,
  .group { border: 1px solid CanvasText; }
  .accent { background: none; color: inherit; }
}
