/* liamrobertrichards.com — one stylesheet for the whole site.
   Dark, quiet, one accent. The system it enforces:
     - ONE accent (gold). Links, rules and dots all borrow it; nothing else gets a colour.
     - Mono ONLY for micro-labels and metadata, never for reading text.
     - Hairline rules instead of cards. Boxes-in-boxes is what makes a personal site look like
       a dashboard template. */

:root {
  --bg: #0a0a0b;
  --ink: #ece9e3;
  --muted: #8d8a83;
  --faint: #5a5852;
  --line: rgba(236, 233, 227, 0.10);
  --line-strong: rgba(236, 233, 227, 0.22);
  --accent: #c9a96a;
  --sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  min-height: 100svh;
}

/* A single warm bloom off the top-left. Cheap, but it stops the page reading as a flat
   #000 rectangle, which is the whole tell of an unstyled dark theme. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(60% 40% at 15% 0%, rgba(201, 169, 106, 0.06), transparent 70%);
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: 720px;
  margin: 0 auto;
  padding: clamp(40px, 8vw, 88px) clamp(22px, 6vw, 32px) 80px;
}

/* ---- nav ---- */
.nav {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: clamp(40px, 8vw, 72px);
}
/* Monogram, not the full name — the name belongs to the hero, and repeating it in the nav is the
   fastest way to make a personal site look padded. */
.nav-home {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--line-strong);
  border-radius: 9px;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--ink);
  text-decoration: none;
  transition: border-color .2s ease, color .2s ease;
}
.nav-home:hover { color: var(--accent); border-color: var(--accent); }
.nav-links { display: flex; gap: 20px; }
.nav-links a {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  text-decoration: none;
}
.nav-links a:hover { color: var(--muted); }

/* ---- hero ---- */
/* Reuses the LinkedIn banner's language: a faint blueprint grid and a gold radar sweep, name once.
   Grid and radar are decorative and sit behind the type; both fade out so nothing competes to read. */
.hero {
  position: relative;
  overflow: hidden;
  margin-bottom: clamp(44px, 8vw, 68px);
  padding: 6px 0 clamp(28px, 6vw, 40px);
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 30px 30px;
  -webkit-mask-image: radial-gradient(120% 100% at 18% 40%, #000 25%, transparent 78%);
          mask-image: radial-gradient(120% 100% at 18% 40%, #000 25%, transparent 78%);
}
.hero-figure {
  position: absolute;
  top: 50%;
  right: clamp(-160px, -8vw, -40px);
  transform: translateY(-50%);
  width: clamp(240px, 42vw, 400px);
  height: clamp(240px, 42vw, 400px);
  color: var(--accent);
  z-index: 0;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 55%);
          mask-image: linear-gradient(90deg, transparent, #000 55%);
}
.hero-figure svg { width: 100%; height: 100%; display: block; }
/* Lift only the text above the grid/radar. Targeting .hero > * here would also match
   .hero-figure and clobber its absolute positioning, collapsing the layout. */
.hero-name, .hero-title, .hero-intro { position: relative; z-index: 1; }
/* On narrow screens the radar sits closer to the type; fade it a touch so text always wins. */
@media (max-width: 560px) { .hero-figure { opacity: 0.62; } }
.hero-name {
  font-size: clamp(2rem, 6.5vw, 2.8rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.12;
  margin: 0 0 14px;
}
.hero-title {
  font-family: var(--mono);
  font-size: clamp(11px, 2.6vw, 12.5px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 16px;
}
.hero-title .dot { color: var(--accent); margin: 0 2px; }
.hero-intro {
  font-size: clamp(1rem, 3.4vw, 1.14rem);
  color: var(--muted);
  margin: 0;
  max-width: 48ch;
}

/* ---- product logo ---- */
/* The ref sits on the same gold plate as the app icon, so the portfolio, the product site and the
   thing you download all read as one object. crispEdges on the SVG keeps the pixels hard. */
.logo {
  display: inline-block;
  background: #e8b931;
  border-radius: 14px;
  line-height: 0;
  overflow: hidden;
  margin-bottom: 20px;
}
.logo svg { display: block; width: 84px; height: 84px; }

/* ---- sections ---- */
section { margin-bottom: clamp(44px, 8vw, 64px); }
.label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--faint);
  margin: 0 0 20px;
}

h2 {
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0 0 12px;
}
h3 {
  font-size: 1.02rem;
  font-weight: 600;
  margin: 28px 0 6px;
}
p { margin: 0 0 16px; color: var(--muted); max-width: 62ch; }
p.lede { color: var(--ink); font-size: 1.1rem; max-width: 54ch; }
strong { color: var(--ink); font-weight: 600; }

/* ---- project rows ---- */
.project { padding: 22px 0; border-top: 1px solid var(--line); }
.project:last-child { border-bottom: 1px solid var(--line); }

/* Featured row carries the app icon so the flagship reads at a glance. Same gold plate as the
   product site, so the icon on the portfolio and the icon you download match. */
.project.featured { display: flex; align-items: flex-start; gap: 16px; }
.project.featured .project-body { flex: 1; min-width: 0; }
.logo-sm {
  flex: none;
  display: inline-block;
  width: 48px;
  height: 48px;
  background: #e8b931;
  border-radius: 11px;
  line-height: 0;
  overflow: hidden;
}
.logo-sm svg { display: block; width: 48px; height: 48px; }
.project-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.project-name { font-size: 1.18rem; font-weight: 600; margin: 0; }
.project-name a { color: var(--ink); text-decoration: none; }
.project-name a:hover { color: var(--accent); }
.project-meta {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--muted);
  white-space: nowrap;
}
.project-meta .dot { color: var(--accent); }
.project-desc { margin: 8px 0 0; }
.project-links { margin-top: 12px; display: flex; gap: 20px; flex-wrap: wrap; }

/* ---- links ---- */
a.u {
  display: inline-block;
  font-size: 0.92rem;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 1px;
  transition: border-color .2s ease, color .2s ease;
}
a.u:hover { border-color: var(--accent); color: var(--accent); }

.contact a { margin-right: 24px; margin-bottom: 10px; }

/* ---- numbered how-it-works ---- */
ol.steps { margin: 0 0 16px; padding: 0; list-style: none; counter-reset: step; }
ol.steps li {
  counter-increment: step;
  position: relative;
  padding-left: 34px;
  margin-bottom: 12px;
  color: var(--muted);
  max-width: 60ch;
}
ol.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.9;
  color: var(--accent);
}

ul.plain { margin: 0 0 16px; padding: 0; list-style: none; }
ul.plain li {
  position: relative;
  padding-left: 18px;
  margin-bottom: 8px;
  color: var(--muted);
  max-width: 60ch;
}
ul.plain li::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--faint);
}

/* ---- tech chips ---- */
.stack { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.stack li {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 5px 9px;
}

/* ---- call to action ---- */
.cta {
  display: inline-block;
  margin-top: 4px;
  padding: 12px 22px;
  background: var(--ink);
  color: #0c0b0a;
  border-radius: 6px;
  font-size: 0.94rem;
  font-weight: 600;
  text-decoration: none;
  transition: opacity .2s ease;
}
.cta:hover { opacity: 0.88; }

/* ---- footer ---- */
footer {
  margin-top: clamp(48px, 9vw, 80px);
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--faint);
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
footer a { color: var(--faint); text-decoration: none; }
footer a:hover { color: var(--muted); }

/* Contact is icons, not a spelled-out address — an email in plain text on a public page is just
   a gift to scrapers. GitHub, LinkedIn, and an @ that opens mail. */
.footer-icons { display: flex; align-items: center; gap: 16px; }
.footer-icons a { display: inline-flex; color: var(--faint); transition: color .2s ease; }
.footer-icons a:hover { color: var(--accent); }
.footer-icons svg { width: 20px; height: 20px; display: block; }

/* ---- entrance ---- */
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(10px); animation: rise .7s cubic-bezier(.22,1,.36,1) forwards; }
  .r2 { animation-delay: .07s; }
  .r3 { animation-delay: .14s; }
  .r4 { animation-delay: .21s; }
  .r5 { animation-delay: .28s; }
  .r6 { animation-delay: .35s; }
  @keyframes rise { to { opacity: 1; transform: none; } }
}

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