/* yaminaamane — "Ink and Ember"
   Tokens, the ruled bar language, the trailing ring, and the lander.
   Written mobile-first: 99% of traffic is a phone in an in-app browser. */

/* ------------------------------------------------------------- fonts ---- */

@font-face {
  font-family: 'Unbounded';
  src: url('/assets/fonts/Unbounded-var.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/Archivo-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/Archivo-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ------------------------------------------------------------ tokens ---- */

:root {
  --ground: #0c0c0d;
  --deep: #17171a;
  --ember: #ff6a1f;
  --ember-dim: #b8480f;
  --bone: #ece9e4;
  --muted: rgba(236, 233, 228, 0.58);
  --silver: #8b8884;
  --hairline: rgba(236, 233, 228, 0.24);

  --f-display: 'Unbounded', ui-sans-serif, system-ui, sans-serif;
  --f-body: 'Archivo', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* The rule. One weight drives every drawn edge on the site. */
  --rule: 1px;
  --corner: 3px;

  /* Trailing-ring position; script.js overwrites these each frame. Parked
     off-canvas so it never flashes in a corner before the first move. */
  --rx: -100px;
  --ry: -100px;

  --pad: 22px;
  --measure: 34rem;
  color-scheme: dark;
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--bone);
  font-family: var(--f-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Film grain. Static, generated, and cheap — an animated canvas grain is a
   battery and paint-cost mistake on a phone. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0.055;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

::selection {
  background: var(--ember);
  color: #fff;
}

a {
  color: var(--ember);
}

:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 3px;
  border-radius: 1px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* -------------------------------------------------------------- drip ---- */
/* The signature. A hairline with a bead that swells, falls, and starts over.
   It appears under every page title and nowhere else, so it reads as a mark
   rather than as decoration. */

.drip {
  position: relative;
  width: 62px;
  height: 30px;
  margin: 10px auto 0;
  flex: none;
}
.drip::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--ember) 22%, var(--ember) 78%, transparent);
}
.drip i {
  position: absolute;
  top: 1px;
  left: 50%;
  width: 7px;
  height: 7px;
  margin-left: -3.5px;
  border-radius: 50%;
  background: var(--ember);
  transform-origin: 50% 0;
  animation: drip 7.5s cubic-bezier(0.55, 0.06, 0.68, 0.19) infinite;
}
@keyframes drip {
  0%, 48% { transform: translateY(0) scale(0.85, 0.35); opacity: 0; }
  58%     { transform: translateY(0) scale(1, 1);       opacity: 1; }
  66%     { transform: translateY(3px) scale(0.78, 1.55); opacity: 1; }
  100%    { transform: translateY(26px) scale(0.6, 1.15); opacity: 0; }
}

/* ------------------------------------------------------------ buttons ---- */
/* Two layers: the outer element paints the rim, .face paints the fill. Both
   carry the same clip path, and because .face is inset by 1px the gap between
   the two clips becomes a border on every edge — including the diagonals,
   which a plain border cannot follow. */

.btn {
  display: block;
  width: 100%;
  max-width: 460px;
  margin: 0 auto;
  padding: 0;
  border-radius: var(--corner);
  text-decoration: none;
  border: 0;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  background: transparent;
  transition: color 0.2s ease;
}

.btn .face {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  min-height: 64px;
  padding: 0 26px;
  border-radius: var(--corner);
  /* Drawn, not filled: the resting state is a rule and nothing else, so the
     hover has somewhere to go. */
  box-shadow: inset 0 0 0 var(--rule) var(--hairline);
  font-family: var(--f-body);
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-align: center;
  color: var(--bone);
  transition: color 0.22s ease, box-shadow 0.22s ease;
}

/* The wipe. An ember block sweeps in from the left and the label inverts on
   top of it. transform-origin does the work so nothing animates layout. */
.btn .face::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ember);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

.btn .face > * {
  position: relative;
  z-index: 1;
}

.btn:hover .face::before,
.btn:focus-visible .face::before {
  transform: scaleX(1);
}

.btn:hover .face,
.btn:focus-visible .face {
  color: var(--ground);
  box-shadow: inset 0 0 0 var(--rule) var(--ember);
}

/* The paid link is the one that starts already drawn in ember. */
.btn-vip .face {
  box-shadow: inset 0 0 0 2px var(--ember);
  color: var(--ember);
  font-size: 0.98rem;
  min-height: 72px;
}

.btn-tiktok .face {
  color: var(--muted);
}

@media (prefers-reduced-motion: reduce) {
  .btn .face::before {
    transition: none;
  }
}

.btn-tiktok .face {
  background: rgba(10, 5, 7, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--bone);
}

/* A press state, not a hover state — there is no hover on a phone. */
.btn:active {
  transform: scale(0.985);
}
.btn-vip:active {
  filter: drop-shadow(0 4px 26px rgba(255, 45, 74, 0.7));
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    transform: translateY(-2px);
  }
  .btn-vip:hover {
    filter: drop-shadow(0 12px 30px rgba(255, 45, 74, 0.6));
  }
  .btn-tiktok:hover {
    background: rgba(236, 228, 230, 0.42);
  }
}

/* ------------------------------------------------------------- lander ---- */

.stage {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  min-height: calc(var(--vh, 1vh) * 100);
}

.video-panel {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--ground);
}
.video-panel video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Darkens the top and the bottom, leaves the middle — where her face is —
   alone. The content sits in the dark bottom band rather than over her. */
.scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(
      180deg,
      rgba(10, 5, 7, 0.86) 0%,
      rgba(10, 5, 7, 0.24) 15%,
      rgba(10, 5, 7, 0.08) 26%,
      /* The name sits around a third of the way down. Without this stop it
         lands on her face at almost no contrast and the type has to be rescued
         by a heavy shadow. Darkening from here keeps her eyes clear above and
         gives the display type a ground to sit on. */
      rgba(10, 5, 7, 0.5) 40%,
      rgba(10, 5, 7, 0.84) 56%,
      rgba(10, 5, 7, 0.96) 70%,
      var(--ground) 100%
    ),
    radial-gradient(120% 60% at 50% 100%, rgba(107, 6, 23, 0.55), transparent 70%);
}

#unmute-btn {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  right: 14px;
  z-index: 3;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  background: rgba(10, 5, 7, 0.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--bone);
  font-family: var(--f-body);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#unmute-btn[data-on='true'] {
  border-color: var(--ember);
  color: var(--ember);
}

.link-panel {
  position: relative;
  z-index: 2;
  min-height: 100vh;
  min-height: 100dvh;
  min-height: calc(var(--vh, 1vh) * 100);
  display: flex;
  flex-direction: column;
  /* Bottom-weighted on mobile: keeps her face visible, puts the CTAs where a
     thumb already is, and lets the scrim do the contrast work. */
  justify-content: flex-end;
  align-items: center;
  gap: 0;
  padding: 0 var(--pad) calc(env(safe-area-inset-bottom, 0px) + 30px);
  text-align: center;
}

/* `display: flex` on a class beats the UA's `[hidden] { display: none }`, so
   without this the element stays laid out when the counter suppresses itself
   and a lone pulsing dot floats at the top of the page with no number beside
   it. Every `hidden` toggle in the markup needs its display rule neutralised
   the same way. */
.live[hidden] {
  display: none;
}

.live {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 auto;
  padding-top: calc(env(safe-area-inset-top, 0px) + 18px);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.8);
}
.live i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ember);
  box-shadow: 0 0 8px var(--ember);
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

.name {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(2.7rem, 14vw, 5rem);
  line-height: 0.9;
  letter-spacing: -0.025em;
  margin: 0;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.85);
}

.tagline {
  margin: 12px 0 26px;
  font-size: 0.82rem;
  letter-spacing: 0.19em;
  text-transform: lowercase;
  color: var(--muted);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.9);
}

.links {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 460px;
}

.sub-links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 22px;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: lowercase;
}
.sub-links a {
  color: var(--muted);
  text-decoration: none;
  /* 14px of vertical padding on a ~20px line box clears the 48px tap-target
     floor. The underline is drawn by a pseudo-element rather than the border,
     so the padding can grow the target without pushing the rule away from the
     text. */
  padding: 14px 8px;
  position: relative;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.9);
}
.sub-links a::after {
  content: '';
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 12px;
  height: 1px;
  background: transparent;
  transition: background 0.16s ease;
}
.sub-links a:active,
.sub-links a:hover {
  color: var(--bone);
}
.sub-links a:active::after,
.sub-links a:hover::after {
  background: var(--ember);
}
.sub-links span {
  color: var(--silver);
  opacity: 0.5;
}

/* Tap-burst canvas. A cursor trail is dead weight on a phone, so on touch this
   is what the trail becomes — see script.js, which binds by pointer type
   rather than by screen width. */
#fx {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
}

/* --------------------------------------------------------- sticky CTA ---- */
/* On the long pages the CTA scrolls away and conversion dies with it. This
   pins after roughly a screen of scroll, inside the home-indicator inset. */

.sticky-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  padding: 10px var(--pad) calc(env(safe-area-inset-bottom, 0px) + 10px);
  background: linear-gradient(180deg, rgba(10, 5, 7, 0), rgba(10, 5, 7, 0.94) 42%);
  transform: translateY(140%);
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.sticky-cta.on {
  transform: translateY(0);
  pointer-events: auto;
}
.sticky-cta .btn .face {
  min-height: 56px;
}

/* ------------------------------------------------------------ desktop ---- */

@media (min-width: 769px) {
  .stage {
    display: grid;
    grid-template-columns: 40% 60%;
  }
  .video-panel {
    position: fixed;
    inset: 0 60% 0 0;
  }
  /* Full-height panel, so the scrim only needs to protect the unmute control
     rather than carry text contrast. */
  .scrim {
    background: linear-gradient(
      180deg,
      rgba(10, 5, 7, 0.6) 0%,
      rgba(10, 5, 7, 0) 22%,
      rgba(10, 5, 7, 0) 78%,
      rgba(10, 5, 7, 0.6) 100%
    );
  }
  #unmute-btn {
    top: auto;
    bottom: 20px;
    right: 20px;
  }
  .link-panel {
    grid-column: 2;
    justify-content: center;
    padding: 40px;
  }
  .live {
    position: absolute;
    top: 26px;
    margin: 0;
    padding-top: 0;
  }
  .name {
    text-shadow: none;
  }
  .tagline,
  .sub-links a,
  .live {
    text-shadow: none;
  }
  .sticky-cta {
    display: none; /* the CTA is always in view on a desktop layout */
  }
}

/* ---------------------------------------------------- reduced motion ---- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .drip i {
    opacity: 1;
    transform: none;
  }
  .sticky-cta {
    transition: none;
  }
  #fx {
    display: none;
  }
}

/* === Signature: the trailing ring ===
   A drawn circle that follows the pointer a beat behind and opens when it is
   over something pressable. It is the same language as the buttons: a rule,
   not a fill.

   Position comes from two custom properties written by script.js inside a
   rAF, so only a transform changes per frame. It is hidden until the first
   pointer event, so it never appears parked in a corner. */
.ink-ring {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  border: 1px solid var(--ember);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transform: translate(var(--rx, -100px), var(--ry, -100px)) scale(1);
  transition: opacity 0.25s ease, width 0.22s ease, height 0.22s ease,
    margin 0.22s ease, background-color 0.22s ease;
}

.ink-ring.is-live {
  opacity: 0.9;
}

.ink-ring.is-over {
  width: 56px;
  height: 56px;
  margin: -28px 0 0 -28px;
  background: rgba(255, 106, 31, 0.12);
}

/* No hover to trail on a touch screen, and a lagging ring is exactly the kind
   of thing reduced-motion is asking us not to draw. */
@media (hover: none), (prefers-reduced-motion: reduce) {
  .ink-ring {
    display: none;
  }
}

/* The lander carried 26 words of visible text -- a name, a tagline and two
   button labels -- on a template shared across ~20 sibling domains. Google
   ruled a sibling's homepage "Duplicate, Google chose different canonical"
   on exactly that. This surfaces the per-creator intro that previously only
   rendered on /about, which is the one piece of copy on the page that is
   genuinely this creator's. Kept visually quiet so it does not compete with
   the buttons, which are still the point of the page. */
.lander-lede {
  margin: 18px auto 0;
  max-width: 34rem;
  font-size: 0.86rem;
  line-height: 1.65;
  text-align: center;
  opacity: 0.72;
}
@media (max-width: 480px) {
  .lander-lede { font-size: 0.8rem; }
}
