/* ============================================================================
   REPS Mockup Harness — device frame + design tokens + type scale
   ----------------------------------------------------------------------------
   Single source of fidelity for every HTML mockup. Import this and your screen
   is "true to an iPhone screen, our font size" BY CONSTRUCTION — no eyeballing,
   no per-session grep-and-pray.

   Every number below is pulled from real REPS source, not invented:
     - Colors        → docs/truth/DESIGN_DECISIONS.md (Core Brand Colors)
     - Type scale    → lib/typography.ts (contentScale / bloomScale / screenTitle)
     - Device target → 390×844 logical pt (iPhone 13/14); 320pt = stress floor
                        (the `mc-answers-never-scroll` adaptive-layout work)
     - 1 logical pt  → 1 CSS px. Do NOT apply devicePixelRatio; RN points map to
                        CSS px 1:1, which is what keeps sizes faithful.

   USAGE
     <link rel="stylesheet" href="../harness/device-harness.css">
     <div class="device">                  (390×844 standard)
     <div class="device device--w320">     (320pt stress floor)
       <div class="status-bar">…</div>
       <div class="screen">  …your screen…  </div>
       <div class="home-indicator"></div>
     </div>

   RULES THE HARNESS ENFORCES (so the critic can't fail you on them)
     - Cream #FFFAF7 default background — never pure white.
     - Coral→Peach gradient ONLY via var(--cta-gradient) on primary CTAs.
     - Lora ONLY on .t-content-* classes. Interaction/training/brand = sans.
       (Serif on a button or a training question is a hard brand violation.)
   ============================================================================ */

/* ---- Fonts -------------------------------------------------------------- */
/* Lora = editorial serif (content zone). Inter = SF-Pro proxy for the
   interaction zone (the app uses system San Francisco on iOS; Inter is the
   closest free browser stand-in and is what reps-web already ships). */
@import url('https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@400;500;600;700&display=swap');

/* ---- Design tokens ------------------------------------------------------ */
:root {
  /* Brand colors (DESIGN_DECISIONS.md — Core Brand Colors) */
  --cream:        #FFFAF7;   /* default app background — never pure white */
  --cream-alt:    #FDFCFB;   /* HomeScreen container variant */
  --coral:        #FF6B6B;
  --peach:        #FF8E53;
  --galaxy:       #040409;   /* ALL 3D / galaxy surfaces (not #000000) */
  --gold:         #D4A24E;   /* reward / achievement accent — never a CTA */
  --gold-bright:  #FFD27D;   /* celebration-only highlight */
  --warm-ink:     #211A14;   /* editorial text on premium surfaces */
  --slate:        #2C3E50;   /* text/primary — app chrome */

  /* Secondary system colors (pulled from real screens) */
  --teal:         #4ECDC4;   /* progress fill, correct accents */
  --teal-deep:    #2D8377;   /* selected-option border / label */
  --teal-ink:     #0D9488;   /* achieved lock / correct dot */
  --ink-muted:    #6B7280;
  --ink-soft:     #8A7F7A;
  --hairline:     #E0D8D3;

  /* The one CTA gradient. Coral→Peach, 135deg. Nowhere else. */
  --cta-gradient: linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%);

  /* Shadows (UI_PATTERNS two-tier system) */
  --shadow-base:   0 2px 8px rgba(0, 0, 0, 0.06);
  --shadow-accent: 0 8px 24px rgba(255, 107, 107, 0.18);
  --shadow-card:   0 2px 12px rgba(0, 0, 0, 0.05);

  /* Radius scale */
  --r-sm: 8px;  --r-md: 12px;  --r-lg: 16px;  --r-xl: 24px;  --r-pill: 999px;

  /* Spacing scale (matches the 4/8 grid the app uses) */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px;

  /* Font stacks */
  --font-content:     'Lora', Georgia, serif;
  --font-interaction: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
}

/* ============================================================================
   PRESENTATION BEST-PRACTICES (how a mockup presents to the reviewer)
   ----------------------------------------------------------------------------
   The harness owns "presents well" so no mockup has to re-solve it:
     - right-sizes to the window  → fit.js scales the device to fit (≤ 1:1)
     - centered, never clipped     → .harness-stage centers both axes + scrolls
     - nothing overlaps            → one .fit-device box per device; flex gap
     - works in the gallery iframe → same rules, measured against the iframe
   Markup: <body class="harness-stage"> <div class="fit-device"><div class="device">…
   and include <script src="../harness/fit.js"></script> before </body>.
   ============================================================================ */
* { box-sizing: border-box; }
html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font-interaction);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The gray studio backdrop. Centers the device(s), wraps a row if there are
   several, and scrolls rather than clipping if the fit can't shrink enough. */
/* padding:0 is load-bearing — fit.js owns ALL the breathing room via its own
   adaptive pad. A body padding here would double-count and clip the device. */
body.harness-stage {
  background: #E9E6E2;
  min-height: 100vh;
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: center;
  justify-content: center;
  align-content: center;
  padding: 0;
  overflow: auto;
}

/* fit.js sizes this wrapper to the SCALED visual bounds (device + bezel) so
   layout never overlaps and scrollbars reflect reality. The device is centered
   so the transform (origin: center) lands dead-centre. Keep device as the only child. */
.fit-device {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- Device frame ------------------------------------------------------- */
/* 430×932 = iPhone Pro Max logical pt — THE device the Canonical Media
   screenshots are captured on (1290×2796 @3x). Mockups must match this so they
   read at the SAME proportion as the real app, not cramped into a smaller frame
   (Mike: "assuming the screen is too small"). 1 logical pt = 1 CSS px. */
.device {
  --safe-top: 59px;       /* Dynamic Island era status bar */
  --safe-bottom: 34px;    /* home indicator zone */
  position: relative;
  width: 430px;
  height: 932px;
  background: var(--cream);
  border-radius: 44px;
  overflow: hidden;
  box-shadow:
    0 0 0 11px #1c1c1e,       /* titanium band */
    0 0 0 13px #2a2a2c,
    0 30px 60px rgba(0, 0, 0, 0.28);
  flex: 0 0 auto;
}
/* 320pt stress floor — answers / layouts must survive this width */
.device--w320 { width: 320px; }

/* Optional: drop the physical bezel for clean exports / embedding */
.device--bare {
  border-radius: 0;
  box-shadow: none;
}

/* ---- Status bar (filled by harness/statusbar.js) ------------------------ */
/* Glyphs sit on the iOS baseline — vertically centred on the Dynamic Island,
   NOT dropped to the bottom of the inset (Mike: "not being too low"). */
.status-bar {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: var(--safe-top);
  padding: 0 24px 0 28px;
  display: flex;
  align-items: center;          /* centre on the island, not flex-end */
  justify-content: space-between;
  font-family: var(--font-interaction);
  color: var(--slate);
  z-index: 50;
  pointer-events: none;
}
/* Glyphs centre on the Dynamic Island via align-items:center on the bar — no
   transform nudge (the old -3px over-corrected and read high). */
.status-bar.on-dark { color: #fff; }
.status-bar__time { font-weight: 600; font-size: 17px; letter-spacing: 0.3px; }
.status-bar__icons { display: flex; align-items: center; gap: 7px; color: inherit; }
.status-bar__icons svg { display: block; }
/* Dynamic Island */
.device::before {
  content: '';
  position: absolute;
  top: 11px; left: 50%;
  transform: translateX(-50%);
  width: 124px; height: 35px;
  background: radial-gradient(120% 120% at 70% 25%, #16161a 0%, #050506 70%);
  border-radius: 20px;
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.06);
  z-index: 60;
}
.device--bare::before { display: none; }

/* ---- Screen (scrollable content area between safe zones) ---------------- */
/* Full-bleed: the screen background fills the ENTIRE device (under the status
   bar and home indicator) — like a real app, no header band. The safe areas are
   PADDING, so normal-flow content clears the glyphs while the bg bleeds behind
   them. NOTE: absolutely-positioned children (e.g. galaxy HUD overlays) anchor
   to the padding-box top (device y=0), NOT below the padding — those screens add
   var(--safe-top) into their own top offsets. */
.screen {
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  overflow-y: auto;
  background: var(--cream);
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
}
.screen.on-galaxy { background: var(--galaxy); }
.screen::-webkit-scrollbar { width: 0; }

/* ---- Home indicator ----------------------------------------------------- */
.home-indicator {
  position: absolute;
  bottom: 8px; left: 50%;
  transform: translateX(-50%);
  width: 140px; height: 5px;
  border-radius: 3px;
  background: rgba(33, 26, 20, 0.32);
  z-index: 50;
}
.home-indicator.on-dark { background: rgba(255, 255, 255, 0.5); }

/* ============================================================================
   TYPE SCALE — every class is a real entry from lib/typography.ts
   CONTENT zone = Lora (.t-content-*).  INTERACTION zone = Inter (.t-ui-*).
   Numbers are fontSize / lineHeight in px, identical to the RN values.
   ============================================================================ */

/* --- Content zone (Lora serif) — reading / editorial / set titles -------- */
.t-content-article  { font-family: var(--font-content); font-weight: 600; font-size: 24px; line-height: 32px; color: var(--slate); }   /* contentScale.articleHeader */
.t-content-banner   { font-family: var(--font-content); font-weight: 600; font-size: 20px; line-height: 28px; color: var(--slate); }   /* contentScale.bannerHeader */
.t-content-headline { font-family: var(--font-content); font-weight: 600; font-size: 18px; line-height: 26px; color: var(--slate); }   /* contentScale.feedHeadline */
.t-content-trending { font-family: var(--font-content); font-weight: 600; font-size: 17px; line-height: 24px; color: var(--slate); }   /* contentScale.trendingTitle */
.t-content-body     { font-family: var(--font-content); font-weight: 400; font-size: 16px; line-height: 26px; color: var(--slate); }   /* contentScale.editorialBody */
.t-content-carousel { font-family: var(--font-content); font-weight: 600; font-size: 13px; line-height: 18px; color: var(--slate); }   /* contentScale.carouselTitle */
.t-bloom-title      { font-family: var(--font-content); font-weight: 600; font-size: 28px; line-height: 38px; color: var(--warm-ink); } /* bloomScale.title */
.t-bloom-body       { font-family: var(--font-content); font-weight: 400; font-size: 18px; line-height: 28px; color: var(--warm-ink); } /* bloomScale.body */

/* --- Interaction zone (Inter sans) — UI / training / brand --------------- */
.t-ui-screen-title  { font-family: var(--font-interaction); font-weight: 700; font-size: 28px; line-height: 34px; color: var(--slate); } /* screenTitle */
.t-ui-question      { font-family: var(--font-interaction); font-weight: 600; font-size: 24px; line-height: 32px; color: var(--slate); } /* QuestionScreen.questionText (SANS — never Lora) */
.t-ui-option        { font-family: var(--font-interaction); font-weight: 400; font-size: 16px; line-height: 21px; color: var(--slate); } /* MultipleChoiceOptions optionText */
.t-ui-label         { font-family: var(--font-interaction); font-weight: 500; font-size: 13px; line-height: 18px; color: var(--ink-soft); }
.t-ui-meta          { font-family: var(--font-interaction); font-weight: 500; font-size: 12px; line-height: 16px; color: var(--ink-soft); }
.t-ui-eyebrow       { font-family: var(--font-interaction); font-weight: 600; font-size: 12px; line-height: 16px; letter-spacing: 1.2px; text-transform: uppercase; }

/* ---- Primary CTA (GradientButton) — the only home of the coral gradient - */
.cta {
  font-family: var(--font-interaction);
  font-weight: 700;
  font-size: 17px;
  color: #fff;
  background: var(--cta-gradient);
  border: none;
  border-radius: var(--r-lg);
  padding: 16px 24px;
  box-shadow: var(--shadow-accent);
  cursor: pointer;
  text-align: center;
  text-decoration: none;   /* CTAs are often <a> — never underline the gradient button */
  width: 100%;
  /* HARNESS FIX (found via T-Bomb ui-critic cycle 2): an <a class="cta"> is
     `display:inline` by default, and `width:100%` has NO effect on an inline
     element — the button silently shrank to its text width and left-aligned
     (measured: a small bottom-left pill instead of the intended full-width
     GradientButton). `.cta` had always been used on a <div>/<button> before
     (block-level by default) so this never surfaced until an <a> consumer
     appeared. Setting display explicitly makes width:100% actually apply
     regardless of which tag a mockup reaches for. */
  display: block;
}

/* ---- Card (UI_PATTERNS two-tier shadow) --------------------------------- */
.card {
  background: #fff;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}


/* ============================================================================
   PHONE DEPLOY OVERRIDE  (funnel-deploy-psi.vercel.app)
   ----------------------------------------------------------------------------
   Appended to a COPY of harness/device-harness.css at deploy time by build.mjs.
   It turns the gallery's device-in-a-bezel presentation into a true full-bleed
   phone experience (edge-to-edge, no titanium frame, fit-in-view, sticky foot)
   for the standalone IG-ad → founding-member funnel.

   This file is the persistent, checked-in home of the override that used to live
   ONLY in the deployed bytes (nowhere on disk). Fix deploy-only layout HERE, then
   re-run build.mjs — never hand-append to the served CSS.
   ============================================================================ */

/* ===== PHONE FULL-BLEED + FIT-IN-VIEW (deploy-only) ===== */
html, body { height: 100%; }
body.harness-stage { background: var(--cream); display: block; gap: 0; padding: 0; overflow: hidden; min-height: 100vh; min-height: 100svh; }
/* CSS BACKSTOP against the gallery fitter (harness/fit.js). The deploy build already
   no-ops fit.js (build.mjs), so this normally has nothing to fight — but if the scaler
   ever runs again (a cached fit.js, a reverted build, a future refactor) it writes an
   inline `transform: scale(<1)` onto .device and inline width/height onto .fit-device.
   An author `!important` rule outranks a NORMAL inline `element.style` value, so these
   pin full-bleed regardless. Losing this = the "too small, floats in the middle" bug. */
.fit-device { display: block; width: 100% !important; height: 100svh !important; transform: none !important; }
.device { --safe-top: max(env(safe-area-inset-top), 14px); --safe-bottom: max(env(safe-area-inset-bottom), 10px);
  width: 100vw !important; height: 100svh !important; border-radius: 0; box-shadow: none;
  transform: none !important; transform-origin: 0 0 !important; }
.device::before, .status-bar, .home-indicator { display: none !important; }
.screen { overflow-y: auto !important; -webkit-overflow-scrolling: touch; display:flex; flex-direction:column; }
.screen > .wrap, .screen > .sci { min-height: 100% !important; padding-top: 8px !important; }
.screen > .wrap { display: flex !important; flex-direction: column !important; }
.confirm:not(.show) { display: none !important; }
.screen > .wrap.is-hidden { display: none !important; }
.prog-row, .prog { margin-bottom: 16px !important; }
.eyebrow { margin-bottom: 10px !important; }
/* roomier vertical rhythm (Mike: less top-loaded, space between Q + answers, taller boxes) */
/* TIGHT title→subtitle gap (Mike r8: 22px was too big) + MODERATE subtitle→answers buffer kept at 16px */
.headline { font-size: 24px !important; line-height: 1.2 !important; margin-bottom: 8px !important; }
.sub { margin-bottom: 16px !important; line-height: 1.5 !important; }
/* no-subtitle question screens (S2): the headline sits directly on the answers — restore a moderate buffer */
.headline + .pills, .headline + .chips, .headline + .grid { margin-top: 10px !important; }
.pills { gap: 12px !important; } .pill { min-height: 56px !important; }
.chips { gap: 12px !important; } .chip { min-height: 56px !important; }
.opt { min-height: 56px !important; margin-bottom: 11px !important; }
/* nudge cream question/content wraps down from the very top for breathing room */
.screen:not(.on-galaxy) > .wrap { padding-top: 3vh !important; }
.question { font-size: 21px !important; line-height: 1.3 !important; margin-bottom: 14px !important; }
.lead { font-size: 22px !important; margin-bottom: 12px !important; }
.safety { gap: 7px !important; margin-bottom: 12px !important; }
.bignum b { font-size: 38px !important; margin-bottom: 0 !important; }
.lowest { margin-top: 8px !important; }
.reveal.show { margin-top: 14px !important; }
/* CTAs are <a> elements — never underline the gradient button (Mike r8: S14/S15 rendered underlined) */
.cta { display: block !important; width: 100% !important; text-decoration: none !important; }
.screen .foot { position: sticky !important; bottom: 0 !important; margin-top: auto !important;
  background: var(--cream) !important; box-shadow: 0 -5px 8px 2px var(--cream) !important; z-index: 6;
  padding-top: 12px !important; padding-bottom: max(env(safe-area-inset-bottom), 14px) !important; }
.screen.on-galaxy .foot { background: var(--galaxy) !important; box-shadow: 0 -5px 8px 2px var(--galaxy) !important; }

/* ===== PREMIUM SELECTION SURFACES (material, two-tier warm shadow, tactile press) ===== */
.pill, .chip, .src, .tile, .ccard {
  background: #fff !important;
  border: 1px solid rgba(33,26,20,0.07) !important;
  box-shadow: 0 1px 2px rgba(33,26,20,0.05), 0 6px 16px rgba(33,26,20,0.06) !important;
  transition: transform .16s cubic-bezier(.2,.8,.2,1), box-shadow .2s ease, border-color .16s ease, background .16s ease !important;
}
.pill:active, .chip:active, .src:active, .tile:active, .ccard:active { transform: scale(.985) !important; box-shadow: 0 1px 2px rgba(33,26,20,0.06) !important; }
.opt { box-shadow: 0 1px 2px rgba(33,26,20,0.05), 0 6px 16px rgba(33,26,20,0.06) !important; }
.chip.sel, .src.sel, .tile.sel, .ccard.sel {
  border-color: rgba(255,107,107,0.5) !important; background: rgba(255,107,107,0.06) !important;
  box-shadow: 0 2px 6px rgba(255,107,107,0.12), 0 10px 22px rgba(255,107,107,0.14) !important;
}
/* the SELECTED pill keeps its coral CTA FILL. The white-bg rule above has no exception for
   .pill.chosen (base .pill.chosen has no !important), so a chosen pill was rendering white text
   on a white box = the answer "DISAPPEARED" on tap (S2). This restores the coral gradient + white text. */
.pill.chosen, .pill.sel {
  background: var(--cta-gradient) !important;
  border-color: transparent !important;
  color: #fff !important;
  box-shadow: 0 6px 18px rgba(255,107,107,0.28) !important;
}
.pill.dim { opacity: 0.4 !important; }
.screen .foot { padding-left: 24px !important; padding-right: 24px !important; }
@keyframes echoFloatG { 0%,100%{ transform: translateY(0) scale(1);} 50%{ transform: translateY(-4px) scale(1.02);} }
.echo:not(.curve-echo){ animation: echoFloatG 3.9s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce){ .echo:not(.curve-echo){ animation: none !important; } }
