/* frontend/assets/brand/fractal.css — WO#155 Slice D shared tokens,
   primitives, type scale, motion. Design authority: fractal-design-system.md.

   HARD RULES (§6): no sphere/orb/ball anywhere (rings ok as low-opacity
   texture); no stock raster or 3D renders (CSS only — gradients, flat
   fills, real DOM); Clash Display licence UNVERIFIED (WO#155 A3) — --disp
   is the single swap point if Kyle says no.

   CONTRAST TIERS (§2.1): --overlay = pure --text only, no text2/text3.
   --amber = display-only, >=24px, never body/small text. --amber-l as a
   FILL is decorative-only; as small link/label TEXT on a dark tier it's
   fine. --glass/--glass2/--accent-tab carry --glass-ink, never white.
   --red/--orange are badge fills with --glass-ink ink, never colored text
   at small sizes, always paired with an icon or word. */

@import url('https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&family=Barlow+Condensed:wght@600;700&display=swap');
@import url('https://api.fontshare.com/v2/css?f[]=clash-display@500,600&display=swap');

:root{
  --sidebar-w:220px;

  /* Fractal Matter, deepened to carry text. Ratios are white-on-surface. */
  --base:#0C3446;              /* 13.16:1 */
  --card:#114760;              /* 10.03:1 */
  --card2:#3E2B6E;             /* 11.83:1 — purple wave as elevated surface */
  --overlay:#2D69B6;           /*  5.52:1 — PURE WHITE TEXT ONLY, see tiers above */

  /* Fractal accents. #2397CA is 3.31:1 — display type only, never <24px. */
  --amber:#2397CA;
  --amber-l:#80D6F2;
  --amber-dim:rgba(35,151,202,.14);
  --accent-bright:#80D6F2;     /* 1.64:1 — decorative only, never under text */
  --accent-tab:#F3ACFF;        /* carries #1A1A1A ink at 10.07:1 */
  --violet:#C697DA;
  --purple:#7558BE;            /* 5.39:1 */
  --purple-dim:rgba(117,88,190,.16);
  --indigo:#C697DA;

  /* Semantic — unchanged hues. Badge-fill + dark ink only, see tiers above. */
  --green:#A9DA5F;
  --red:#EC6A5A;
  --orange:#FB923C;

  --border:rgba(128,214,242,.22);
  --border2:rgba(128,214,242,.40);

  --text:#FFFFFF;
  --text2:rgba(255,255,255,.85);
  --text3:rgba(255,255,255,.70);

  --shadow:0 1px 6px rgba(3,26,36,.4);
  --shadow-md:0 4px 24px rgba(3,26,36,.5);

  /* Fractal light surfaces. Deliberately NOT named --ink: the alias block
     below already binds --ink to --card. */
  --glass:#C5D6DB;
  --glass2:#B0D3D5;
  --glass-ink:#1A1A1A;

  /* Hero-only type-role tokens (fractal-design-system.md §3). */
  --disp:'Clash Display', ui-serif, Georgia, serif;
  --body-f:'Hanken Grotesk', system-ui, -apple-system, sans-serif;
  --nums:'Barlow Condensed', system-ui, sans-serif;

  /* Backward-compat aliases for JS-generated HTML — DO NOT RENAME OR REMOVE.
     Some of these are string literals inside JS templates on other pages. */
  --surface:var(--base);--white:var(--card);--ink:var(--card);
  --teal:var(--amber);--teal-l:var(--amber-l);--teal-dim:var(--amber-dim);
  --text1:var(--text);--bg2:var(--card2);--bg3:var(--overlay);
  --ink2:var(--card2);
}

/* ── TYPE SCALE ── §3. -1% tracking by default; the CTA outlier (-3%) lives
   in .f-pill, not here. f-h1/f-h2 sizes: declared off this slice's two
   heading contexts, not in §3's scale table verbatim — not measured. */
.f-display{font-family:var(--disp);font-weight:500;font-size:clamp(32px,4.6vw,56px);letter-spacing:-0.01em;line-height:1.1}
.f-h1{font-family:var(--disp);font-weight:500;font-size:clamp(26px,3vw,38px);letter-spacing:-0.01em;line-height:1.15}
.f-h2{font-family:var(--disp);font-weight:500;font-size:24px;letter-spacing:-0.01em;line-height:1.25}
.f-body{font-family:var(--body-f);font-size:15px;letter-spacing:-0.01em;line-height:1.6}
.f-caption{font-family:var(--body-f);font-size:12px;letter-spacing:-0.01em;line-height:1.5}
.f-numeral{font-family:var(--nums);font-weight:700;font-size:clamp(28px,3vw,40px);letter-spacing:-0.01em;line-height:1}

/* ── FOUR PRIMITIVES ── §4 */
.f-pill{
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:999px;border:none;cursor:pointer;
  background:var(--accent-tab);color:var(--glass-ink);
  font-family:var(--body-f);font-weight:600;font-size:15px;
  letter-spacing:-0.03em;padding:13px 28px;
  transition:transform .15s ease,background .15s ease;
}
.f-pill:hover{background:#f7c0ff}
.f-pill:active{transform:scale(.99)}

.f-glass{
  background:var(--glass);color:var(--glass-ink);
  border:1px solid var(--border);border-radius:14px;
  box-shadow:var(--shadow-md);
}
/* Rest rotation per-instance via --rest-rot (default: hero's shipped
   -5.88deg, invented, no source-frame figure — §4/§5). */
.f-glass--tilt{transform:rotate(var(--rest-rot, -5.88deg))}

.f-proof{
  background:rgba(255,255,255,.08);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border:1px solid var(--border);border-left:3px solid var(--accent-tab);
  border-radius:10px;color:var(--text);
}

.f-dark{background:var(--card);color:var(--text);border-radius:14px}

/* ── SHARED FIELD ── */
.f-field{
  width:100%;padding:11px 14px;border:1.5px solid var(--border2);
  border-radius:10px;font-size:14px;font-family:var(--body-f);
  color:var(--text);background:var(--card);outline:none;
  transition:border-color .15s,box-shadow .15s;
}
.f-field::placeholder{color:var(--text3)}
.f-field:focus{border-color:var(--amber);box-shadow:0 0 0 3px rgba(35,151,202,.2)}

/* ── PAGE GROUND ── verbatim from index.html .hero / .hero-grain (WO#155 B2) */
/* 2026-09-10 fix: position/size suffixes are only valid inside the `background`
   shorthand, not `background-image` -- browsers dropped the whole declaration and
   the gradient field never rendered. Colour goes on the final layer. */
.f-ground{
  background:
    linear-gradient(112deg, rgba(35,151,202,0) 44%, rgba(128,214,242,.16) 100%) 0 0/100% 66% no-repeat,
    radial-gradient(ellipse at 20% 100%, rgba(126,88,190,.16) 0%, transparent 55%) var(--base);
}
.f-grain{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='250' height='250'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='250' height='250' filter='url(%23g)'/%3E%3C/svg%3E");
  opacity:0.14;mix-blend-mode:overlay;
}

/* ── MOTION ── §5. Base CSS is always the end state; animations fill
   backwards only, so no element's final look depends on one completing.
   Keyframe names/easings verbatim from index.html's hero (WO#155 B2) — one
   vocabulary site-wide. Durations fixed per class; pages vary only --d
   (delay), per §5's own rule. All timings invented, not measured. */
@keyframes bwh-rise  { from { opacity:0; transform:translateY(var(--rise, 24px)); } to { opacity:1; transform:translateY(0); } }
@keyframes bwh-card  { from { opacity:0; transform:translate(var(--sx, 120px), var(--sy, 0px)) rotate(var(--sr, -30deg)); } to { opacity:1; transform:translate(0,0) rotate(var(--rest-rot, 0deg)); } }
@keyframes bwh-drop  { from { opacity:0; transform:translateY(-20px); } to { opacity:1; transform:translateY(0); } }
@keyframes bwh-slide { from { opacity:0; transform:translateX(40px); } to { opacity:var(--o, 1); transform:translateX(0); } }

.m-rise{animation:bwh-rise 500ms ease-out backwards;animation-delay:var(--d, 0ms)}
.m-card{animation:bwh-card 900ms cubic-bezier(.22,1,.36,1) backwards;animation-delay:var(--d, 0ms)}
.m-drop{animation:bwh-drop 500ms ease-out backwards;animation-delay:var(--d, 0ms)}
.m-slide{animation:bwh-slide 800ms cubic-bezier(.22,1,.36,1) backwards;animation-delay:var(--d, 0ms)}

@media (prefers-reduced-motion: reduce) {
  .m-rise,.m-card,.m-drop,.m-slide { animation: none !important }
}
