/* ==========================================================================
   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) */
  --bar-grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' 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>");   /* the pen and Inspector bars' grain */

  --serif: "Gambarino", 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) */
html.landing body { visibility: hidden; }
html.pre-blur :is(h1, h2, h3, .triad > span)[data-blur] { visibility: hidden; }   /* (until site.js has split them into words; set in each page's head) */   /* (arriving at a section from another page: shown once it's in place, 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; }
/* No grey box flashed over links and buttons when they're tapped: each has its own press or focus state */
html { -webkit-tap-highlight-color: transparent; }
::selection { background: var(--blue-soft); color: var(--ink); }   /* the Contact pill's pale blue, the text staying 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);
}
/* On a desktop the grain is in the paper: it covers the whole page and scrolls with it. (A phone keeps it fixed to the
   screen, one screen's worth to draw rather than the whole page; see below) */
@media (hover: hover) and (min-width: 701px) {
  body { position: relative; }
  .grain { position: absolute; }
}

/* Progressive blur at the top only, softening content as it leaves. At the very top it's off (--edge-t, js/site.js),
   so nothing at the top of the page starts out soft; it eases in over the first stretch of scroll */
.edge { position: fixed; top: 0; left: 0; right: 0; height: var(--edge-h, 160px); 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(calc(var(--r) * var(--edge-t, 1))); -webkit-backdrop-filter: blur(calc(var(--r) * var(--edge-t, 1)));
}
.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: calc(.9 * var(--edge-t, 1));
  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: var(--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); }
@media (hover: hover) { .nav ul a:hover { color: var(--blue-ink); } }   /* (a phone would keep it blue after a tap) */

/* --- 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; }
/* Fine print, not navigation: no pill, the grey just turns the blue the email address turns on hover */
.footer .ct-link { color: var(--ink-faint); padding: 0; margin: 0; transition: color .3s; }
.footer .ct-link::before { content: none; }
.footer .ct-link:hover { color: var(--blue-ink); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  .reveal { opacity: 1; translate: 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: var(--edge-h, 105px); }
  .edge > i:nth-child(4) { backdrop-filter: blur(calc(10px * var(--edge-t, 1))); -webkit-backdrop-filter: blur(calc(10px * var(--edge-t, 1)));
    -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 100%); mask-image: linear-gradient(to bottom, #000 45%, transparent 100%); }
  .edge::after { opacity: var(--edge-t, 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: calc(.55 * var(--edge-t, 1)); }
  .w { filter: none; will-change: opacity, translate; }
}
