/* ==========================================================================
   Louie Sellers: shared styles
   Paper, print grain, top-edge blur, serif + sans, one light blue.
   ========================================================================== */

:root {
  --paper: #f3f0ea;
  --paper-deep: #e9e4da;
  --card: rgba(255, 255, 255, .55);
  --ink: #161514;
  --ink-soft: #5d5a55;
  --ink-faint: #a29d95;
  --rule: rgba(22, 21, 20, .12);
  --blue: #9cc6ec;
  --blue-soft: #d4e9fc;   /* the pen's sky blue family: a pale tint of it */
  --blue-ink: #2066b6;    /* and a deep shade of it, for text and lines (5:1 on the paper) */

  --serif: "Instrument Serif", Georgia, serif;
  --sans: "Inter Tight", system-ui, sans-serif;
  --ease: cubic-bezier(.2, .7, .1, 1);

  --gutter: clamp(20px, 4vw, 48px);
  /* Corner smoothing ≈ 40%: a native superellipse corner (1 = plain round, 2 = full squircle).
     Browsers without corner-shape simply keep the normal radius. */
  --corner: superellipse(1.4);
  --measure: 820px;
  /* One size for every section heading, capped so lines don't orphan a word at full width */
  --h2: clamp(44px, 6.2vw, 88px);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--paper); overflow-x: clip; }   /* no page-wide smooth scrolling: it would also animate the browser putting you back on refresh (links glide instead, js/site.js) */
body {
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 18px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; }
a { color: inherit; }
::selection { background: var(--blue); color: var(--ink); }

.serif { font-family: var(--serif); font-weight: 400; }
em { font-family: var(--serif); font-style: italic; }
.blue { color: var(--blue-ink); }

/* --- Texture + edge ------------------------------------------------------ */

.grain {
  position: fixed; inset: 0; z-index: 100; pointer-events: none;
  background-image: var(--grain-img, url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"));
  opacity: var(--grain-o, .2);
  mix-blend-mode: var(--grain-blend, multiply);
}

/* Progressive blur at the top only, softening content as it leaves */
.edge { position: fixed; top: 0; left: 0; right: 0; height: var(--edge-h, 18vh); z-index: 90; pointer-events: none; }
.edge > i {
  position: absolute; inset: 0;
  -webkit-mask-image: linear-gradient(to bottom, #000 var(--a), transparent var(--b));
          mask-image: linear-gradient(to bottom, #000 var(--a), transparent var(--b));
  backdrop-filter: blur(var(--r)); -webkit-backdrop-filter: blur(var(--r));
}
.edge > i:nth-child(1) { --r: calc(1px * var(--edge-k, 1));  --a: 40%; --b: 100%; }
.edge > i:nth-child(2) { --r: calc(3px * var(--edge-k, 1));  --a: 25%; --b: 75%; }
.edge > i:nth-child(3) { --r: calc(6px * var(--edge-k, 1));  --a: 10%; --b: 55%; }
.edge > i:nth-child(4) { --r: calc(12px * var(--edge-k, 1)); --a: 0%;  --b: 35%; }
.edge::after {
  content: ""; position: absolute; inset: 0; opacity: .9;
  background: linear-gradient(to bottom, var(--paper) 0%, color-mix(in srgb, var(--paper) 0%, transparent) 70%);
}

/* --- Bottom veil: a hairline of blur along the bottom edge ------------- */

.edge-b { position: fixed; left: 0; right: 0; bottom: 0; height: var(--edge-bh, 16px); z-index: 90; pointer-events: none;
  backdrop-filter: blur(var(--edge-b, 1px)); -webkit-backdrop-filter: blur(var(--edge-b, 1px));
  -webkit-mask-image: linear-gradient(to top, #000 30%, transparent); mask-image: linear-gradient(to top, #000 30%, transparent); }
/* A stronger layer hugging the very bottom, so a taller edge reads as a progressive blur, like the top */
.edge-b::before { content: ""; position: absolute; inset: 0; backdrop-filter: blur(calc(var(--edge-b, 1px) * 2)); -webkit-backdrop-filter: blur(calc(var(--edge-b, 1px) * 2));
  -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 45%); mask-image: linear-gradient(to top, #000 0%, transparent 45%); }

/* --- Smoothed corners on every rounded rectangle (circles and pills stay true) */
.card, .browser, .browser .bar span, .mock .mphoto, .project .shot, .tile,
.b-stage, .panel, .out, .copy, .scale-track, .sq, .spring-stage { corner-shape: var(--corner); }

/* --- Nav ------------------------------------------------------------------ */

.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 95;
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px var(--gutter);
  font-size: 14px;
}
.nav a { text-decoration: none; }
.nav .mark { font-family: "Instrument Serif", Georgia, serif; font-weight: 400; font-variation-settings: normal; font-size: 24px; letter-spacing: -.005em; color: var(--ink); transition: opacity .8s var(--ease), translate .8s var(--ease); }
.nav.hide-mark .mark { opacity: 0; translate: 0 -6px; pointer-events: none; }
/* The links arrive with the name, once you've scrolled past the hero */
.nav ul { transition: opacity .8s var(--ease), translate .8s var(--ease); }
.nav.hide-mark ul { opacity: 0; translate: 0 -6px; pointer-events: none; }
.nav ul { list-style: none; display: flex; gap: clamp(18px, 3vw, 36px); }
.nav ul { position: relative; }
.nav ul a { position: relative; display: inline-block; padding: 7px 13px; margin: -7px -13px; z-index: 1; color: var(--ink-soft); transition: color .3s; }
/* Hover: one soft blue pill that glides between the links on a spring, and slips away when you leave (js/site.js) */
.nav .pill { position: absolute; top: -7px; height: calc(100% + 14px); left: 0; width: 0; border-radius: 999px; background: var(--blue-soft); opacity: 0; scale: .8; pointer-events: none;
  transition: translate .5s cubic-bezier(.3,1.35,.5,1), width .5s cubic-bezier(.3,1.35,.5,1), opacity .25s, scale .4s cubic-bezier(.3,1.5,.5,1); }
.nav .pill.on { opacity: 1; scale: 1; }
.nav .pill.jump { transition: opacity .25s, scale .4s cubic-bezier(.3,1.5,.5,1); }
.nav ul a:hover { color: var(--blue-ink); }

/* --- Shared type ---------------------------------------------------------- */

.kicker {
  font: 500 12px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft);
  display: flex; align-items: center; gap: 12px;
}

.display {
  font-family: var(--serif); font-weight: 400; letter-spacing: -.025em; line-height: .96;
  font-size: var(--h2);
}
.display em { font-style: normal; }
/* Headings stay one voice: no italic/blue split */
h1 em, h2 em, h3 em { font-family: inherit; font-style: normal; color: inherit; }
/* Balanced lines: no single orphaned word on a heading's last line */
h1, h2, h3, .display { text-wrap: balance; }

.prose { width: min(var(--measure), 100% - var(--gutter) * 2); margin: 0 auto; }
.prose p { font-size: clamp(20px, 2.1vw, 25px); line-height: 1.5; max-width: 31em; margin-bottom: 1.1em; text-wrap: pretty; }
.prose p.small { font-size: 18px; color: var(--ink-soft); }

/* Words focus in one after another (--ro); leaving the top, the .edge overlay does the softening */
@property --ro { syntax: "<number>"; inherits: false; initial-value: 0; }
.w {
  display: inline-block;
  opacity: var(--ro);
  filter: blur(calc((1 - var(--ro)) * 12px));   /* each word focuses in */
  translate: 0 calc((1 - var(--ro)) * .3em);
  transition: --ro 1.2s var(--ease) var(--d, 0s);
  will-change: filter, opacity;
}
.in .w { --ro: 1; }
.still .w { transition: none; }

/* Gentle entrance for blocks (opacity + rise, no blur) */
.reveal { opacity: 0; translate: 0 24px; transition: opacity 1.1s var(--ease), translate 1.1s var(--ease); }
.reveal.in { opacity: 1; translate: 0 0; }

/* --- Footer --------------------------------------------------------------- */

.footer {
  width: min(1240px, 100% - var(--gutter) * 2); margin: 0 auto; padding: 36px 0 44px;
  border-top: 1px solid var(--rule);
  display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  font-size: 14px; color: var(--ink-soft);
}
.footer a { text-decoration: none; position: relative; z-index: 0; display: inline-block; padding: 7px 13px; margin: -7px -13px; transition: color .3s; }
/* Same soft blue pill as the nav links */
.footer a::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: 999px; background: var(--blue-soft); opacity: 0; scale: .8;
  transition: opacity .25s, scale .4s cubic-bezier(.3,1.5,.5,1); }
.footer a:hover { color: var(--blue-ink); }
.footer a:hover::before { opacity: 1; scale: 1; }
@media (max-width: 700px) { .footer { flex-direction: column; align-items: center; gap: 12px; text-align: center; } }   /* on a phone: stacked and centred */

/* Photo credits: a quiet grey link by the copyright, to the credits page */
.footer .fine { display: inline-flex; align-items: baseline; gap: 18px; flex-wrap: wrap; justify-content: center; }
.footer .ct-link { color: var(--ink-faint); }
.footer .ct-link:hover { color: var(--ink-soft); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  .reveal { opacity: 1; translate: none; }
}

/* With a bar up in the nav, the nav steps back where they'd collide */
@media (max-width: 1180px) { html:not([data-bars="bottom"]):is(.tune-on, .pen-held) .nav ul { opacity: 0; pointer-events: none; } }
@media (max-width: 860px) { html:not([data-bars="bottom"]):is(.tune-on, .pen-held) .nav .mark { opacity: 0; pointer-events: none; } }

/* Keyboard shortcut keys (the P, the S) only mean something with a keyboard: hidden on touch screens */
@media (hover: none) and (pointer: coarse) { kbd, .key-hint { display: none !important; } }   /* (.key-hint: "· Esc" on buttons) */

/* --- Phones and touch screens: the same look, far less work per frame ------------------------------------------
   Live blurs and full-screen blending are cheap on a laptop and expensive on a phone, where they're redone on every
   scroll frame. So here: the grain lies flat (no blending), the top edge is a plain paper fade (no live blur), and
   words focus in by fading and rising rather than un-blurring */
@media (hover: none), (max-width: 700px) {
  .grain { mix-blend-mode: normal; opacity: calc(var(--grain-o, .2) * .6); }
  .edge > i, .edge-b, .edge-b::before { backdrop-filter: none; -webkit-backdrop-filter: none; }
  .edge-b { display: none; }
  /* The top edge here: one blur layer (not four), frosted with paper, so text passing under the nav goes soft and pale
     rather than sitting sharp under the name. Until the name shows in the nav (home, over the hero) it stays light */
  .edge { height: 120px; }
  .edge > i:nth-child(4) { backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 100%); mask-image: linear-gradient(to bottom, #000 45%, transparent 100%); }
  .edge::after { opacity: 1; background: linear-gradient(to bottom, color-mix(in srgb, var(--paper) 92%, transparent) 0%, color-mix(in srgb, var(--paper) 78%, transparent) 40%, color-mix(in srgb, var(--paper) 35%, transparent) 72%, color-mix(in srgb, var(--paper) 0%, transparent) 100%); }
  .edge > i:nth-child(4), .edge::after { transition: opacity .8s var(--ease); }
  .nav.hide-mark ~ .edge > i:nth-child(4) { opacity: 0; }
  .nav.hide-mark ~ .edge::after { opacity: .55; }
  .w { filter: none; will-change: opacity, translate; }
}
