/* ============================================================================
   PawCheck — creator program surfaces (apply form + hub)
   ----------------------------------------------------------------------------
   Loaded AFTER css/site.css and depends on its tokens (--ink, --blue, --card,
   --radius…). It adds only what the marketing site never needed: form controls,
   field validation states, and the small status/stat furniture the hub uses.

   ⚠️ NO COLOUR LITERALS BELOW EXCEPT INSIDE rgba() SHADOWS. Every colour comes
   from a site.css custom property, so the creator pages follow the light/dark
   toggle for free and can never drift from the app's palette the way an
   independently-styled page would. If you need a new colour, add it to
   site.css's token block, not here.
   ========================================================================== */

/* ---- Page frame ----------------------------------------------------------- */
/*  ⚠️ .site-header is `position: fixed` with a 68px inner height (site.css:158),
    so it is OUT OF FLOW and sits on top of whatever is first in <main>. The
    marketing pages get away without an offset because their hero carries its own
    generous top padding; these pages open on an <h1> and would have it sliced in
    half. The 68px is the header, the rest is breathing room. */
.creator-main { padding: calc(68px + 46px) 0 88px; }
.creator-narrow { max-width: 680px; margin: 0 auto; }

.creator-head { text-align: center; margin-bottom: 40px; }
.creator-head h1 {
  font-size: clamp(2.1rem, 5vw, 3.3rem);
  line-height: 1.06;
  letter-spacing: -0.02em;
  margin-bottom: 16px;
}
.creator-head p { color: var(--ink-soft); font-size: 1.12rem; max-width: 520px; margin: 0 auto; }
.creator-head .eyebrow { margin-bottom: 14px; }

/* ---- Hero scene ------------------------------------------------------------
   The paywall's cast, rebuilt in CSS from the same cut-outs the app ships. They
   are laid out on a fixed-aspect stage with percentage positions so the whole
   group scales as one picture instead of reflowing into a row of stickers —
   the overlaps ARE the composition (the rabbit tucks behind the dog, the fish
   sits under the cat's chin), and a flex row would pull them apart.
   ------------------------------------------------------------------------- */
.hero-scene {
  position: relative;
  width: 100%;
  max-width: 620px;
  margin: 0 auto 6px;
  aspect-ratio: 620 / 250;
  pointer-events: none;
}
/*  ⚠️ EVERY POSITIONED CHILD IS SCOPED `.hero-scene .hs-*` ON PURPOSE.
    `.hero-scene img` is (0,1,1) and beats a bare `.hs-s1` at (0,1,0), so the
    shared `bottom: 0` silently won over each sparkle's own `bottom` and dropped
    all three onto the floor behind the animals. Nothing errored and the images
    all loaded — they were simply in the wrong place. Keep the scope. */
.hero-scene img { position: absolute; bottom: 0; }
.hero-scene .hs-dog    { left: 2%;    width: 27%; }
.hero-scene .hs-rabbit { left: 20.5%; width: 12%; }
.hero-scene .hs-phone  { left: 38%;   width: 24%; }
.hero-scene .hs-fish   { left: 60%;   width: 12%; bottom: 2%; }
.hero-scene .hs-cat    { right: 1%;   width: 26%; }

/*  Sparkles drift rather than sit. Slow and small on purpose: the page is a
    form, and motion next to a form competes with it. */
/*  The paywall's sparkles are four-point gold stars drawn in code, NOT the
    `hero_sparkle` asset — that one is the green "safe" check badge, and three
    of those floating over the scene read as three scan results rather than as
    decoration. Redrawn as inline SVG so it inherits the palette token. */
.hero-scene .hs-sparkle {
  position: absolute;
  width: 4.4%;
  height: auto;
  fill: var(--sunshine);
  opacity: 0.85;
  animation: hs-float 4.5s ease-in-out infinite;
}
.hero-scene .hs-s1 { left: 13%;  bottom: 66%; animation-delay: 0s; }
.hero-scene .hs-s2 { left: 47%;  bottom: 86%; animation-delay: 1.4s; width: 3.4%; }
.hero-scene .hs-s3 { right: 14%; bottom: 58%; animation-delay: 2.6s; width: 3.8%; }
@keyframes hs-float {
  0%, 100% { transform: translateY(0) rotate(0deg); opacity: 0.55; }
  50%      { transform: translateY(-9px) rotate(11deg); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-scene .hs-sparkle { animation: none; opacity: 0.8; }
}

/* ---- The three-perk strip ------------------------------------------------- */
.perk-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 36px 0 44px; }
.perk {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px 20px;
  text-align: center;
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.perk:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
/*  The app's own Home-tile pastels, used FLAT exactly as the app uses them.
    Borrowing the palette is what makes this page read as PawCheck rather than
    as a generic signup form wearing PawCheck's logo. */
.perk.tint-mint  { background: var(--mint-tint);     border-color: transparent; }
.perk.tint-sun   { background: var(--sunshine-tint); border-color: transparent; }
.perk.tint-blush { background: var(--blush-tint);    border-color: transparent; }
.perk.tint-lilac { background: var(--lilac-tint);    border-color: transparent; }
.perk .perk-icon { font-size: 2rem; display: block; margin-bottom: 10px; }
.perk h3 { font-size: 1.14rem; font-weight: 1000; margin-bottom: 6px; }
.perk p { color: var(--ink-soft); font-size: 0.92rem; line-height: 1.5; }

/* ---- The "where the money goes" strip -------------------------------------
   Three chips and two arrows. Creators are told a percentage everywhere and
   almost never shown the arithmetic; showing the subtraction is what makes
   $10.20 land as honest rather than as a number we shaved. */
.math-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--card-sunken);
  border-radius: var(--radius-sm);
  padding: 16px 14px;
  margin: 6px 0 4px;
}
.math-strip > span {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--ink);
  white-space: nowrap;
}
.math-strip b { font-weight: 1000; font-size: 1.05rem; }
.math-strip em {
  font-style: normal;
  font-weight: 800;
  font-size: 0.72rem;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}
.math-strip .math-out { color: var(--green-deep); }
.math-strip [aria-hidden] { color: var(--ink-faint); font-size: 1.1rem; align-self: flex-start; margin-top: 3px; }

/* ---- Form ----------------------------------------------------------------- */
.creator-form {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 32px;
  box-shadow: var(--shadow);
}

.field { margin-bottom: 20px; }
.field:last-of-type { margin-bottom: 0; }

.field label {
  display: block;
  font-weight: 800;
  font-size: 0.94rem;
  margin-bottom: 7px;
  color: var(--ink);
}
.field .hint { display: block; font-weight: 700; font-size: 0.82rem; color: var(--ink-faint); margin-top: 6px; }

.field input[type="text"],
.field input[type="email"],
.field input[type="url"],
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  background: var(--card-sunken);
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  padding: 13px 15px;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.field textarea { min-height: 110px; resize: vertical; line-height: 1.5; }
.field select { appearance: none; background-image: none; cursor: pointer; }

.field input::placeholder,
.field textarea::placeholder { color: var(--ink-faint); font-weight: 600; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--blue);
  background: var(--card);
}

/*  Invalid is announced, not merely coloured: the message carries the reason and
    the border is a redundant cue, so this survives a colour-blind reader and a
    forced-colours mode both. */
.field.invalid input,
.field.invalid select,
.field.invalid textarea { border-color: var(--score-red); }
.field-error {
  display: none;
  color: var(--score-red);
  font-size: 0.85rem;
  font-weight: 800;
  margin-top: 7px;
}
.field.invalid .field-error { display: block; }

/*  Consent checkboxes. The whole row is the label, so the tap target is the full
    line rather than a 16px square — these are the three fields most likely to be
    filled on a phone, and a missed tap here reads as "the form is broken". */
.field.check > label {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-weight: 700;
  font-size: 0.94rem;
  line-height: 1.5;
  cursor: pointer;
  margin-bottom: 0;
}
.field.check input[type="checkbox"] {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  accent-color: var(--blue);
  cursor: pointer;
}
.field.check a { color: var(--blue); font-weight: 800; text-decoration: underline; }
.field.check.invalid > label { color: var(--score-red); }

/* Prefix-style input for a handle, so the platform is visible while typing. */
.input-prefix { display: flex; align-items: stretch; }
.input-prefix .prefix {
  display: flex;
  align-items: center;
  padding: 0 4px 0 15px;
  background: var(--card-sunken);
  border: 2px solid transparent;
  border-right: none;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  color: var(--ink-faint);
  font-weight: 800;
}
.input-prefix input { border-radius: 0 var(--radius-sm) var(--radius-sm) 0 !important; }
.input-prefix:focus-within .prefix { border-color: var(--blue); background: var(--card); }

/* ---- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font: inherit;
  font-weight: 900;
  border-radius: 999px;
  padding: 14px 26px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.16s ease, opacity 0.16s ease;
  text-decoration: none;
}
.btn-primary { background: var(--blue); color: #fff; box-shadow: 0 8px 22px rgba(44, 123, 196, 0.28); }
.btn-primary:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 12px 28px rgba(44, 123, 196, 0.34); }
.btn-quiet { background: var(--card-sunken); color: var(--ink); }
.btn-quiet:hover:not(:disabled) { background: var(--blue-tint); }
.btn-block { width: 100%; }
.btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }
.btn .spinner { display: none; }
.btn.is-busy .spinner { display: inline-block; }
.btn.is-busy .btn-label { opacity: 0.75; }

@keyframes pc-spin { to { transform: rotate(360deg); } }
.spinner {
  width: 15px; height: 15px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: pc-spin 0.7s linear infinite;
}

/* ---- Status panels -------------------------------------------------------- */
/*  Every async surface has all four of these states authored. An "empty" that is
    really a failure is the single most expensive bug in a payouts UI: a creator
    reading $0.00 cannot tell it from "we could not reach the server", and will
    conclude the program does not pay. */
.panel {
  border-radius: var(--radius);
  padding: 26px 28px;
  border: 1px solid var(--line);
  background: var(--card);
}
.panel.tone-good { background: var(--green-tint); border-color: var(--green); }
.panel.tone-warn { background: var(--sunshine-tint); border-color: var(--sunshine); }
.panel.tone-bad  { background: var(--rose-tint); border-color: var(--score-red); }
.panel h2 { font-size: 1.3rem; margin-bottom: 8px; }
.panel p { color: var(--ink-soft); line-height: 1.55; }
.panel p + p { margin-top: 10px; }
.panel .panel-icon { font-size: 2rem; display: block; margin-bottom: 12px; }

.loading-block { text-align: center; padding: 60px 20px; color: var(--ink-soft); font-weight: 700; }
.loading-block .spinner { margin: 0 auto 14px; width: 22px; height: 22px; color: var(--blue); }

[hidden] { display: none !important; }

/* ---- Hub: code + stats ---------------------------------------------------- */
.code-card {
  background: var(--brand-gradient);
  color: #fff;
  border-radius: var(--radius);
  padding: 30px;
  text-align: center;
  box-shadow: var(--shadow-lg);
}
.code-card .code-label { font-size: 0.84rem; font-weight: 800; opacity: 0.82; letter-spacing: 0.06em; text-transform: uppercase; }
.code-card .code-value {
  font-size: clamp(2.2rem, 7vw, 3.2rem);
  font-weight: 1000;
  letter-spacing: 0.08em;
  margin: 8px 0 4px;
  font-variant-ligatures: none;
}
.code-card .code-link { font-size: 0.95rem; font-weight: 700; opacity: 0.9; word-break: break-all; }
.code-card .btn-quiet { background: rgba(255,255,255,0.16); color: #fff; margin-top: 16px; }
.code-card .btn-quiet:hover { background: rgba(255,255,255,0.26); }

.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 26px 0; }
.stat {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 18px;
  text-align: center;
}
.stat .stat-value { font-size: 1.7rem; font-weight: 1000; line-height: 1.1; }
.stat .stat-label { font-size: 0.8rem; font-weight: 800; color: var(--ink-faint); margin-top: 5px; }
/*  A figure we could not measure renders as an em dash, never as 0. */
.stat .stat-value.unknown { color: var(--ink-faint); }

.hub-section { margin-top: 40px; }
.hub-section > h2 { font-size: 1.4rem; margin-bottom: 14px; }

/* ---- Responsive ----------------------------------------------------------- */
@media (max-width: 780px) {
  /*  The scene keeps its proportions but gets taller relative to the page, so
      the cast stays a group rather than five small things in a line. */
  .hero-scene { max-width: 420px; aspect-ratio: 420 / 185; }
  .perk-grid { grid-template-columns: 1fr; }
  .math-strip { gap: 6px; padding: 14px 10px; }
  .math-strip > span { font-size: 0.95rem; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .creator-form { padding: 24px 20px; }
  .creator-main { padding: calc(68px + 28px) 0 64px; }
}

/* ---- Worked-example caption ------------------------------------------------
   The strip states a dollar figure this page cannot verify against the backend,
   so the caption is load-bearing, not decoration: it is what keeps the number
   an example rather than a promise. Do not remove it when the numbers are
   correct — it exists for the day they are not. */
.math-note {
  text-align: center;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-faint);
  margin: 8px 0 4px;
}
.math-strip .ms-arrow { align-self: center; margin-top: 0; }
