/* ---------- fonts ---------- */
/* Self-hosted (assets/fonts, from Google Fonts, all under the SIL Open Font License), so first
   paint doesn't wait on connecting to two more servers. Only the styles the site uses: Archivo
   600, Roboto 400 and IBM Plex Mono 400, in Latin and Latin Extended; a browser only fetches
   the second when a page uses one of its characters. Each page preloads the two the first
   screen needs (Archivo and Plex Mono, latin). */
@font-face{ font-family:'Archivo'; font-style:normal; font-weight:600; font-display:swap;
  src:url(../fonts/archivo-600-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'Archivo'; font-style:normal; font-weight:600; font-display:swap;
  src:url(../fonts/archivo-600-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'Roboto'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/roboto-400-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'Roboto'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/roboto-400-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'IBM Plex Mono'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/ibm-plex-mono-400-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'IBM Plex Mono'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/ibm-plex-mono-400-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

:root{
  --bg: #0e0f11;
  --bg-alt: #131417;
  --panel: #15171a;
  --ink: #e9ebee;
  --ink-dim: #9aa5b1;
  --ink-faint: #79828c;
  --line: rgba(255,255,255,0.09);
  --line-bright: rgba(255,255,255,0.18);
  --hero-bg: var(--bg);
  --grid-rgb: 255,255,255;
  --grid-mask-solid-stop: 35%;
  --grid-mask-fade-color: rgba(0,0,0,0.35);
  --grid-mask-end-stop: 100%;
  --split-red: #FC1B39;
  --split-cyan: #22B7FC;
  --split-blend-mode: screen;
  --split-opacity-scale: 1;
  --split-offset-scale: 1;
  --model-color: #ffffff;
  --hero-pieces-color: #c9ccd1; /* a step off the logo so the pieces read as separate */
  --header-solid: rgba(14,15,17,0.85);
  --header-gradient: linear-gradient(to bottom, rgba(14,15,17,0.9), rgba(14,15,17,0));
  --backdrop: rgba(5,6,8,0.78);
  --mono: 'IBM Plex Mono', monospace;
  --sans: 'Roboto', sans-serif;
  --disp: 'Archivo', sans-serif;
}

html[data-theme="light"]{
  --model-color: #37393b;
  --hero-pieces-color: #5f6266;
  --bg: #f5f3ef;
  --bg-alt: #ebe7e1;
  --panel: #fffdfa;
  --ink: #17191c;
  --ink-dim: #59616a;
  --ink-faint: #686f77;
  --line: rgba(23,25,28,0.14);
  --line-bright: rgba(23,25,28,0.26);
  --hero-bg: var(--bg);
  --grid-rgb: 23,25,28;
  --split-red: #F5637A;
  --split-cyan: #5CBEF2;
  --split-blend-mode: multiply;
  --split-opacity-scale: 0.65;
  --split-offset-scale: 0.65;
  --header-solid: rgba(245,243,239,0.88);
  --header-gradient: linear-gradient(to bottom, rgba(245,243,239,0.94), rgba(245,243,239,0));
  --backdrop: rgba(23,25,28,0.55);
}

*{ box-sizing:border-box; }
/* Read by screen readers, invisible on screen. */
.sr-only{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
  border:0;
}
html{ scroll-behavior:smooth; background:var(--bg); }
body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--sans);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
}

a{ color:inherit; }
img,svg{ display:block; max-width:100%; }
a:focus-visible,
button:focus-visible{
  outline:2px solid var(--ink);
  outline-offset:3px;
}

::selection{ background:var(--ink); color:var(--bg); }

#grid-canvas{
  position:fixed;
  inset:0;
  z-index:0;
  width:100%;
  height:100%;
  pointer-events:none;
  mask-image:radial-gradient(ellipse at 30% 20%, #000 var(--grid-mask-solid-stop), var(--grid-mask-fade-color) var(--grid-mask-end-stop));
  -webkit-mask-image:radial-gradient(ellipse at 30% 20%, #000 var(--grid-mask-solid-stop), var(--grid-mask-fade-color) var(--grid-mask-end-stop));
}

/* ---------- header ---------- */
/* body > only: the portfolio detail dialog has its own <header>, which must not become this fixed bar. */
body > header{
  position:fixed; top:0; left:0; right:0; z-index:50;
  display:flex; align-items:center; justify-content:space-between;
  padding:22px clamp(20px,5vw,56px);
  font-family:var(--mono);
  font-size:13px;
  letter-spacing:0.02em;
  background:var(--header-gradient);
  border-bottom:1px solid transparent;
}
body > header.scrolled{
  background:var(--header-solid);
  border-bottom-color:var(--line);
}
header .logo{
  text-decoration:none;
  display:flex;
  align-items:center;
  height:32px;
}
header .logo img{
  width:auto;
  height:28px;
  max-width:180px;
  object-fit:contain;
}
header .logo .logo-light{ display:none; }
html[data-theme="light"] header .logo .logo-dark{ display:none; }
html[data-theme="light"] header .logo .logo-light{ display:block; }
.header-actions{ display:flex; align-items:center; gap:clamp(16px,3vw,34px); }
.header-nav{ display:flex; gap:clamp(16px,3vw,34px); }
.header-nav a{
  color:var(--ink-dim);
  text-decoration:none;
  transition:color 0.2s ease;
}
.header-nav a:hover{ color:var(--ink); }
.theme-toggle{
  width:32px; height:32px; padding:0;
  display:grid; place-items:center;
  color:var(--ink-dim);
  background:transparent;
  border:1px solid var(--line-bright);
  border-radius:50%;
  cursor:pointer;
  transition:color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.theme-toggle:hover{ color:var(--ink); border-color:var(--ink); transform:rotate(12deg); }
.theme-toggle svg{ width:15px; height:15px; }
.theme-toggle .sun{ display:none; }
html[data-theme="light"] .theme-toggle .moon{ display:none; }
html[data-theme="light"] .theme-toggle .sun{ display:block; }
.theme-toggle:hover .moon{ display:none; }
.theme-toggle:hover .sun{ display:block; }
html[data-theme="light"] .theme-toggle:hover .moon{ display:block; }
html[data-theme="light"] .theme-toggle:hover .sun{ display:none; }

/* ---------- hero ---------- */
.hero{
  position:relative; z-index:2;
  min-height:100vh;
  display:flex; flex-direction:column; justify-content:flex-start;
  /* Text sits top-left, in the open space beside the logo's upper-left arm. */
  --hero-text-top:clamp(96px, 14vh, 150px);
  padding:var(--hero-text-top) clamp(20px,5vw,56px) 0;
  background:var(--hero-bg);
  border-bottom:1px solid var(--line);
}
.hero-model{
  position:absolute;
  inset:0;
  z-index:0;
  width:100%;
  height:100%;
  pointer-events:none;
}
.hero-eyebrow,
.hero h1{ position:relative; z-index:1; }
.hero-eyebrow{
  font-family:var(--mono);
  font-size:13px;
  color:var(--ink-dim);
  margin:0 0 22px;
  display:flex; align-items:center; gap:10px;
}
.hero h1{
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(2.4rem, 6vw, 5.2rem);
  line-height:1.02;
  letter-spacing:-0.02em;
  margin:0;
  max-width:16ch;
}
.theme-toggle:active{ transform:scale(0.92); }
a:active{ opacity:0.72; }

.hero-scroll-cue{
  position:absolute; left:clamp(20px,5vw,56px); bottom:36px; z-index:1;
  font-family:var(--mono); font-size:12px; color:var(--ink-faint);
  display:flex; align-items:center; gap:10px;
}
.hero-scroll-cue .line{ width:26px; height:1px; background:var(--ink-faint); }

/* ---------- services (sticky morph) ---------- */
.services-wrap{
  position:relative; z-index:1;
  height:406vh; /* fallback height; JavaScript sizes this from the service count */
  margin-top:-100vh;
}
/* The section starts behind the hero, so #work marks where the first service is fully in view. */
.services-anchor{
  position:absolute;
  top:100vh; left:0;
  width:1px; height:1px;
}
/* Three columns: the icon (a quarter of the screen), then the text and the project
   previews at equal widths. */
.services-sticky{
  position:sticky; top:0;
  height:100vh;
  display:grid;
  grid-template-columns:25vw minmax(0,1fr) minmax(0,1fr);
  border-bottom:1px solid var(--line);
  --progress-left:clamp(10px,2vw,24px);
  --progress-width:28px;
  --shape-pad:clamp(24px,3vw,48px);
  --col-pad:clamp(20px,3vw,48px);
  /* The text block's widest; the reel's position depends on it (see .preview-col). */
  --panel-max:560px;
}
.services-progress{
  position:absolute;
  z-index:3;
  top:50%; left:var(--progress-left);
  width:var(--progress-width); height:min(56vh,520px);
  min-height:260px;
  transform:translateY(-50%);
}
.services-progress-steps{
  position:relative;
  height:100%;
  display:flex;
  flex-direction:column;
  align-items:center;
}
.services-progress-item{
  width:100%;
  min-height:0;
  display:flex;
  flex:1;
  flex-direction:column;
  align-items:center;
}
.services-progress-segment{
  position:relative;
  width:1px;
  min-height:12px;
  flex:1;
  margin-top:4px;
  background:var(--line-bright);
}
.services-progress-segment-fill{
  position:absolute;
  top:0; left:-1px;
  width:3px; height:0;
  background:var(--ink);
  transition:height 0.15s linear;
}
.services-progress-step{
  padding:2px 3px;
  background:var(--bg);
  color:var(--ink-faint);
  font-family:var(--mono);
  font-size:9px;
  line-height:1.2;
  transition:color 0.2s ease;
}
.services-progress-step.active{ color:var(--ink); }
/* The stage is centered between the progress bar's right edge and the text column. */
.shape-col{
  min-width:0;
  display:flex; flex-direction:column;
  justify-content:center;
  padding:0 0 0 calc(var(--progress-left) + var(--progress-width));
  position:relative;
}
.shape-stage{
  width:min(340px, calc(25vw - var(--progress-left) - var(--progress-width) - 2 * var(--shape-pad)));
  max-width:100%;
  aspect-ratio:1/1;
  margin:0 auto;
}
.shape-stage canvas{ width:100%; height:100%; display:block; }

.text-col{
  min-width:0;
  display:flex; align-items:center;
  padding:0 var(--col-pad);
  position:relative;
}
/* Every panel sits in the same grid cell with the same top edge, so the group is as tall as
   the tallest panel and centered as one. Sharing a top keeps the lines of consecutive
   services on the same heights, so during a transition each incoming line rises into the
   slot an outgoing line is leaving instead of landing between them. */
.panels{ position:relative; width:100%; max-width:var(--panel-max); display:grid; }
.panel{
  grid-area:1 / 1;
  align-self:start;
  min-width:0;
  opacity:0;
  pointer-events:none;
}
/* A service holds still until the scroll crosses into the next one, then switches with a
   short timed transition (classes set by services.js). The current heading's red/cyan
   channels drift apart as it fades; 40% of the way into that, the next heading's channels
   fade in apart and drift together into place. Alongside each heading, the tag, paragraph
   and list zip out above / in from below their lines letter by letter (zip-text.js); the
   bullets and the mobile link, which aren't split into letters, fade. */
.panel.is-active,
.panel.is-leaving{ opacity:1; }
.panel.is-active{ pointer-events:auto; }
.panel .panel-portfolio-link,
.panel li::before{ opacity:0; transition:opacity 0.5s ease; }
.panel.is-active .panel-portfolio-link,
.panel.is-active li::before{ opacity:1; transition-delay:0.32s; }
/* Leave: 0.8s. Enter: starts 0.32s in (40% through the leave) and runs 0.8s. Keep
   LEAVE_TIME and ENTER_TIME in services.js in step. */
.panel.is-leaving h2{ animation:channel-out 0.8s cubic-bezier(0.4,0,0.6,1) forwards; }
.panel.is-leaving h2 .split-base{ animation:base-out 0.8s ease forwards; }
.panel.is-entering h2{ animation:channel-in 0.8s cubic-bezier(0.25,0.6,0.3,1) 0.32s backwards; }
.panel.is-entering h2 .split-base{ animation:base-in 0.8s ease 0.32s backwards; }
/* Zipper timing. --zip-letter is how long each letter takes to slide; --zip-total is how
   long a whole block takes, kept equal to the heading's 0.8s. Letters start one after
   another in reading order (--zip, 0 to 1, set per letter by zip-text.js), spread over
   whatever time is left: --zip-total minus --zip-letter. A shorter --zip-letter means fewer
   letters in motion at once, so they read as individual letters rather than a moving line. */
.panel{
  --zip-letter:0.4s;
  --zip-total:0.8s;
  /* Mask height per letter, in em: enough for the ascenders and descenders of Roboto and
     IBM Plex Mono. Lower clips glyph tops and tails; higher lets letters show in the gap. */
  --zip-mask:1.3;
  /* Line height of the zipped text, shared by the text and its letter masks. */
  --text-line:1.6;
}
.panel p,
.panel li{ line-height:var(--text-line); }
.panel.is-leaving .zip-glyph{
  animation:zip-out var(--zip-letter) cubic-bezier(0.5,0,0.75,0)
    calc(var(--zip, 0) * (var(--zip-total) - var(--zip-letter))) forwards;
}
.panel.is-entering .zip-glyph{
  animation:zip-in var(--zip-letter) cubic-bezier(0.25,1,0.5,1)
    calc(0.32s + var(--zip, 0) * (var(--zip-total) - var(--zip-letter))) backwards;
}
@keyframes zip-out{ to{ transform:translateY(-100%); } }
@keyframes zip-in{ from{ transform:translateY(100%); } }

/* Registered so the channel offset and strength can animate; unregistered they'd jump. */
@property --channel-split{ syntax:'<length>'; inherits:true; initial-value:0px; }
@property --channel-opacity{ syntax:'<number>'; inherits:true; initial-value:0; }
/* Channels travel 8px and peak at 0.7 opacity. */
@keyframes channel-out{
  0%{ --channel-split:0px; --channel-opacity:0.7; }
  100%{ --channel-split:8px; --channel-opacity:0; }
}
@keyframes base-out{
  0%{ opacity:1; }
  55%, 100%{ opacity:0; }
}
@keyframes channel-in{
  0%{ --channel-split:8px; --channel-opacity:0; }
  55%{ --channel-opacity:0.7; }
  100%{ --channel-split:0px; --channel-opacity:0; }
}
@keyframes base-in{
  0%, 45%{ opacity:0; }
  100%{ opacity:1; }
}
/* Instant swaps with reduced motion, and on small screens, where the transitions made
   scrolling stutter on phones. Keep the breakpoint in step with MOBILE_QUERY in services.js. */
@media (prefers-reduced-motion: reduce), (max-width: 860px){
  .panel .panel-portfolio-link,
  .panel li::before{ transition:none; }
  .panel.is-leaving{ opacity:0; }
  .panel.is-entering h2,
  .panel.is-entering h2 .split-base,
  .panel.is-leaving h2,
  .panel.is-leaving h2 .split-base,
  .panel .zip-glyph{ animation:none; }
  /* Skip the blended red/cyan copies the transition would otherwise create for nothing.
     (.panels raises these above the rules that create them, further down.) */
  .panels .panel.is-entering .split-letter::before,
  .panels .panel.is-entering .split-letter::after,
  .panels .panel.is-leaving .split-letter::before,
  .panels .panel.is-leaving .split-letter::after{ content:none; }
}
.panel .tag{
  font-family:var(--mono);
  font-size:12px;
  color:var(--ink-dim);
  margin-bottom:16px;
}
.panel h2{
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(1.7rem,3vw,2.5rem);
  line-height:1.15;
  letter-spacing:-0.01em;
  margin:0 0 18px;
}
.split-word{ position:relative; display:inline-block; white-space:nowrap; }
/* Zipper text (zip-text.js): each letter is a one-line-tall clipping box, so its glyph can
   slide in from below or out above its own line. */
.zip-word{ display:inline-block; white-space:nowrap; vertical-align:top; }
.zip-letter{
  display:inline-block;
  overflow:hidden;
  vertical-align:top;
  /* The mask is only as tall as the glyphs (--zip-mask, in em), not the whole line, so a
     letter appears and disappears right at its own edge instead of sliding through the gap
     between lines. The rest of the line height (--text-line) becomes margin above and below,
     which keeps every glyph exactly where plain text would put it. */
  line-height:var(--zip-mask);
  margin:calc((var(--text-line, 1.6) - var(--zip-mask)) * 0.5em) 0;
}
.zip-glyph{ display:inline-block; }
.split-base{ position:relative; z-index:1; }
.split-letter{ position:absolute; }
/* The copies only exist while a letter is split by the pointer, or during a services step
   transition, so resting letters add no blended layers. */
.split-letter.is-split::before,
.split-letter.is-split::after,
.panel.is-entering .split-letter::before,
.panel.is-entering .split-letter::after,
.panel.is-leaving .split-letter::before,
.panel.is-leaving .split-letter::after{
  content:attr(data-letter);
  position:absolute;
  top:0; left:0;
  z-index:0;
  color:var(--split-color);
  line-height:inherit;
  white-space:pre;
  opacity:calc(max(var(--split-opacity, 0), var(--channel-opacity, 0)) * var(--split-opacity-scale));
  pointer-events:none;
  user-select:none;
  mix-blend-mode:var(--split-blend-mode);
}
.split-letter::before{
  --split-color:var(--split-red);
  transform:translateX(calc((var(--split-red-x, 0px) - var(--channel-split, 0px)) * var(--split-offset-scale)));
}
.split-letter::after{
  --split-color:var(--split-cyan);
  transform:translateX(calc((var(--split-cyan-x, 0px) + var(--channel-split, 0px)) * var(--split-offset-scale)));
}
.panel p{
  color:var(--ink-dim);
  font-size:1.02rem;
  max-width:48ch;
  margin:0 0 14px;
}
.panel ul{
  margin:18px 0 0; padding:0; list-style:none;
  display:grid; gap:8px;
}
.panel ul li{
  font-family:var(--mono);
  font-size:12.5px;
  color:var(--ink-faint);
  display:flex; gap:10px; align-items:baseline;
}
.panel ul li::before{ content:"·"; color:var(--ink-dim); }

/* Shown in place of the previews on small screens. */
.panel-portfolio-link{
  display:none;
  margin-top:22px;
  font-family:var(--mono);
  font-size:12.5px;
  color:var(--ink);
  text-decoration:none;
  border-bottom:1px solid var(--line-bright);
  padding-bottom:4px;
  transition:border-color 0.2s ease;
}
.panel-portfolio-link::after{ content:" →"; }
.panel-portfolio-link:hover{ border-bottom-color:var(--ink); }

.preview-col{
  min-width:0;
  display:flex; align-items:center; justify-content:center;
  padding:0 var(--col-pad);
  position:relative;
  /* The text stops at --panel-max, leaving empty space at the end of its column that grows
     with the screen. Shifting this column left by half of that space (plus half a column
     padding) centres the reel between the text and the screen edge, with equal gaps either
     side. Percentages here are of the grid column's width, the same as the text column's. */
  left:calc(-0.5 * (var(--col-pad) + max(0px, 100% - 2 * var(--col-pad) - var(--panel-max))));
}
/* The reels' 16:9 frame: as wide as the column, and short enough to fit the screen height with
   room for the header. */
.reel-frame{
  position:relative;
  width:min(100%, calc(68vh * 16 / 9));
  aspect-ratio:16/9;
  overflow:hidden;
  border:1px solid var(--line);
  /* Carousel timing: how long the push takes, and its easing. */
  --tile-slide:0.5s;
  --tile-ease:cubic-bezier(0.65,0,0.35,1);
  /* Hover: the label slides in from the left edge while the video zooms slightly and a
     gradient in the panel colour fades up behind the label. The gradient covers this share
     of the frame, at this strength at the bottom edge. */
  --tile-hover-time:0.6s;
  --tile-hover-zoom:1.06;
  --tile-shade-height:40%;
  --tile-shade-strength:85%;
  /* The crossfade from one clip to the next. */
  --reel-fade:0.6s;
}
.reel{
  position:absolute;
  inset:0;
  display:block;
  color:var(--ink);
  text-decoration:none;
  opacity:0;
  pointer-events:none;
}
/* The reel is a link filling the frame; the inner layer carries the video and label (and the
   background, so two reels mid-transition don't cover each other). */
.reel-inner{ position:absolute; inset:0; overflow:hidden; background:var(--panel); }
.reel-inner.is-placeholder{
  background:
    linear-gradient(160deg, transparent calc(50% - 0.5px), var(--line) calc(50% - 0.5px), var(--line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
    var(--bg-alt);
}
/* A service with no reel yet shows a line of text in the frame (SERVICES[].placeholder). */
.reel-inner.has-text{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:10px;
  padding:0 clamp(16px,3vw,40px);
  text-align:center;
  background:var(--bg-alt);
}
.reel-placeholder-title{
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(1.3rem,2.2vw,2rem);
  letter-spacing:-0.01em;
  line-height:1.15;
}
.reel-placeholder-note{
  font-family:var(--mono);
  font-size:12px;
  color:var(--ink-faint);
}
/* Each reel stacks two videos that take turns playing its clips (services.js); the current one
   fades in over the other. --reel-fade mirrors CLIP_FADE_TIME in services.js. */
.reel video{
  position:absolute;
  inset:0;
  display:block;
  width:100%; height:100%;
  object-fit:cover;
  opacity:0;
  transition:transform var(--tile-hover-time) cubic-bezier(0.2,0.7,0.2,1),
    opacity var(--reel-fade) linear;
}
.reel video.is-current{ opacity:1; }
/* Switching services works like a carousel: the frame stays put while the outgoing and
   incoming reels slide through it together, edge to edge, so the next one pushes the current
   one out. Scrolling down pushes left to right, scrolling back up right to left: services.js
   sets --slide-dir (1 or -1) on #serviceReels for each switch. */
.reel.is-active,
.reel.is-leaving{ opacity:1; }
.reel.is-active{ pointer-events:auto; }
.reel.is-leaving .reel-inner{ animation:tile-out var(--tile-slide) var(--tile-ease) forwards; }
.reel.is-entering .reel-inner{ animation:tile-in var(--tile-slide) var(--tile-ease) backwards; }
@keyframes tile-out{ to{ transform:translateX(calc(var(--slide-dir, 1) * 100%)); } }
@keyframes tile-in{ from{ transform:translateX(calc(var(--slide-dir, 1) * -100%)); } }
.reel-inner::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:0;
  height:var(--tile-shade-height);
  background:linear-gradient(to top,
    color-mix(in srgb, var(--panel) var(--tile-shade-strength), transparent),
    transparent);
  pointer-events:none;
}
.reel-label{
  position:absolute;
  left:0; bottom:0;
  z-index:1;
  padding:clamp(12px,1.4vw,20px);
  font-family:var(--mono);
  font-size:13px;
  white-space:nowrap;
}
.reel-label::after{ content:" →"; }
/* Only on devices that can hover (and for keyboard focus); elsewhere the label just shows. */
@media (hover: hover){
  .reel-inner::after{
    opacity:0;
    transform:translateY(25%);
    transition:opacity var(--tile-hover-time) ease,
      transform var(--tile-hover-time) cubic-bezier(0.2,0.7,0.2,1);
  }
  .reel-label{
    transform:translateX(-100%);
    transition:transform var(--tile-hover-time) cubic-bezier(0.2,0.7,0.2,1);
  }
  .reel:hover .reel-inner::after,
  .reel:focus-visible .reel-inner::after{ opacity:1; transform:none; }
  .reel:hover .reel-label,
  .reel:focus-visible .reel-label{ transform:none; }
  .reel:hover video,
  .reel:focus-visible video{ transform:scale(var(--tile-hover-zoom)); }
}
@media (prefers-reduced-motion: reduce){
  .reel.is-leaving{ opacity:0; }
  .reel.is-leaving .reel-inner,
  .reel.is-entering .reel-inner{ animation:none; }
  .reel video,
  .reel-label,
  .reel-inner::after{ transition:none; }
}

/* ---------- about ---------- */
/* Laid out like the services section: a left column a quarter of the screen wide with the
   model, then the text, with an empty quarter on the right to balance the model's column.
   The model sits on the same vertical line as the service icons (centered right of where
   the services progress bar would be). */
.about{
  position:relative; z-index:2;
  margin-top:0;
  padding:clamp(90px,14vh,150px) 25vw clamp(90px,14vh,150px) 0;
  display:grid;
  grid-template-columns:25vw minmax(0,1fr);
  border-bottom:1px solid var(--line);
  align-items:center;
  --progress-left:clamp(10px,2vw,24px);
  --progress-width:28px;
  --shape-pad:clamp(24px,3vw,48px);
  --col-pad:clamp(20px,3vw,48px);
}
.about > *{ position:relative; z-index:1; }
.about-figure{
  min-width:0;
  display:flex;
  justify-content:center;
  padding-left:calc(var(--progress-left) + var(--progress-width));
}
.about-stage{
  width:min(340px, calc(25vw - var(--progress-left) - var(--progress-width) - 2 * var(--shape-pad)));
  max-width:100%;
  aspect-ratio:1/1;
}
.about-stage canvas{ width:100%; height:100%; display:block; }
.about-text{ min-width:0; padding-left:var(--col-pad); }
.section-label{
  font-family:var(--mono);
  font-size:13px;
  color:var(--ink-dim);
  margin:0 0 20px;
}
.about h2{
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(1.8rem,3.4vw,2.7rem);
  letter-spacing:-0.01em;
  margin:0 0 22px;
}
.about p{ color:var(--ink-dim); margin:0 0 16px; }
.about-stats{
  margin-top:32px;
  /* One row however many stats there are. */
  display:grid; grid-auto-flow:column; grid-auto-columns:auto;
  justify-content:start;
  gap:clamp(20px,4vw,50px);
}
.about-stats div b{
  display:block; font-family:var(--disp); font-size:1.8rem; font-weight:600;
}
.about-stats div span{
  display:block;
  margin-top:4px;
  font-family:var(--mono); font-size:11.5px; line-height:1.35; color:var(--ink-faint);
}

/* ---------- contact ---------- */
.contact{
  position:relative; z-index:1;
  padding:clamp(100px,16vh,170px) clamp(20px,5vw,56px) 90px;
}
.contact h2{
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(2.1rem,5vw,3.6rem);
  letter-spacing:-0.02em;
  max-width:14ch;
  margin:0 0 30px;
}
.contact-grid{
  display:grid;
  grid-template-columns: 1.2fr 1fr;
  gap:clamp(30px,6vw,80px);
  margin-top:50px;
}
.contact-email{
  font-family:var(--disp);
  font-size:clamp(1.4rem,3vw,2.1rem);
  text-decoration:none;
  border-bottom:1px solid var(--line-bright);
  padding-bottom:8px;
  display:inline-block;
  transition:border-color 0.2s ease, color 0.2s ease;
}
.contact-email:hover{ color:var(--ink); border-bottom-color:var(--ink); }
.contact-intro{ color:var(--ink-dim); max-width:44ch; margin-top:22px; }
.contact-list{ list-style:none; margin:0; padding:0; display:grid; gap:16px; }
.contact-list li{ display:flex; justify-content:space-between; border-bottom:1px solid var(--line); padding-bottom:14px; }
.contact-list .k{ font-family:var(--mono); font-size:12px; color:var(--ink-faint); }
.contact-list .v{ text-decoration:none; font-size:14px; }
.contact-list .v:hover{ text-decoration:underline; }

/* ---------- portfolio page ---------- */
.portfolio{
  position:relative; z-index:1;
  min-height:100vh;
  padding:clamp(110px,16vh,160px) clamp(20px,5vw,56px) 90px;
}
.portfolio-title{
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(2.1rem,5vw,3.6rem);
  letter-spacing:-0.02em;
  line-height:1.05;
  margin:0 0 36px;
}
/* ---------- portfolio: intro ---------- */
/* Until the project data has rendered, the index keeps its space but stays invisible, so the
   featured grid appearing above it doesn't visibly push it down (a layout shift). */
.portfolio.is-loading .pf-index{ visibility:hidden; }
.pf-intro{ margin:0 0 clamp(48px,8vh,88px); }
.pf-intro .portfolio-title{ margin-bottom:20px; }
.pf-lede{ margin:0 0 12px; max-width:52ch; color:var(--ink-dim); font-size:1.08rem; }
.pf-clients{ margin:0; max-width:70ch; font-family:var(--mono); font-size:12.5px; color:var(--ink-faint); }

/* Small labels: "Concept" on self-initiated work, and the detail view's category tags. */
.pf-tag{
  display:inline-block;
  padding:2px 7px;
  font-family:var(--mono);
  font-size:10.5px;
  font-weight:400;
  line-height:1.4;
  letter-spacing:0;
  white-space:nowrap;
  color:var(--ink);
  background:var(--panel);
  border:1px solid var(--line-bright);
}
.pf-tag--quiet{ color:var(--ink-dim); background:transparent; }

/* ---------- portfolio: featured ---------- */
/* Three columns of fixed-height rows: a wide card spans two columns, a tall one two rows, an
   extra-tall one three (the full height of a grid of three rows), and dense packing fills the
   gaps they leave. Each card is its image with a caption under it. */
.pf-featured{ margin:0 0 clamp(64px,10vh,110px); }
.pf-featured-grid{
  display:grid;
  grid-template-columns:repeat(3, minmax(0,1fr));
  grid-auto-rows:clamp(220px,22vw,340px);
  grid-auto-flow:dense;
  gap:clamp(18px,2vw,28px) clamp(14px,1.6vw,24px);
}
.pf-card{
  display:flex; flex-direction:column; gap:12px;
  min-width:0;
  color:inherit;
  text-decoration:none;
}
.pf-card--wide{ grid-column:span 2; }
.pf-card--tall{ grid-row:span 2; }
.pf-card--extra-tall{ grid-row:span 3; }
.pf-card-media{
  position:relative;
  flex:1;
  min-height:0;
  overflow:hidden;
  background:var(--bg-alt);
  border:1px solid var(--line);
}
.pf-card-media img,
.pf-card-media video{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  transition:transform 0.6s cubic-bezier(0.2,0.7,0.2,1), opacity 0.3s ease;
}
/* The loop fades in over the still once it's actually playing. */
.pf-card-media video{ opacity:0; }
.pf-card-media.is-playing video{ opacity:1; }
a.pf-card:hover .pf-card-media img,
a.pf-card:hover .pf-card-media video{ transform:scale(1.03); }
.pf-card-title{
  display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px;
  margin:0;
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(1.05rem,1.4vw,1.25rem);
  line-height:1.2;
}
.pf-card-meta{ margin:0; font-family:var(--mono); font-size:12px; color:var(--ink-faint); }

/* ---------- portfolio: index ---------- */
/* The column header and every row share one grid: year, client, project, role, pillar, icon. */
.pf-index{
  /* px, not em: the header's smaller type would otherwise narrow its first column. */
  --pf-cols:64px minmax(0,1.1fr) minmax(0,1.5fr) minmax(0,1.3fr) minmax(0,0.8fr) 20px;
  --pf-col-gap:clamp(14px,2vw,28px);
  --pf-row-pad:10px;
}
.pf-index-head{
  display:flex; flex-wrap:wrap; align-items:center;
  gap:14px 24px;
  margin:0 0 28px;
}
.pf-index-head .section-label{ margin:0; font-weight:400; }
.pf-filters{ display:flex; flex-wrap:wrap; gap:8px; }
.pf-filter{
  padding:7px 14px;
  font-family:var(--mono);
  font-size:12.5px;
  color:var(--ink-dim);
  background:transparent;
  border:1px solid var(--line-bright);
  border-radius:999px;
  cursor:pointer;
  transition:color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}
.pf-filter:hover{ color:var(--ink); border-color:var(--ink); }
.pf-filter[aria-pressed="true"]{ color:var(--bg); background:var(--ink); border-color:var(--ink); }
.pf-count{ margin:0 0 0 auto; font-family:var(--mono); font-size:12px; color:var(--ink-faint); }

.pf-index-cols{
  display:grid;
  grid-template-columns:var(--pf-cols);
  column-gap:var(--pf-col-gap);
  padding:0 var(--pf-row-pad) 10px;
  border-bottom:1px solid var(--line-bright);
  font-family:var(--mono);
  font-size:11.5px;
  color:var(--ink-faint);
}
.pf-sort{
  padding:0;
  font:inherit;
  color:inherit;
  text-align:left;
  background:none;
  border:0;
  cursor:pointer;
  transition:color 0.2s ease;
}
.pf-sort:hover,
.pf-sort[aria-pressed="true"]{ color:var(--ink); }
.pf-sort[data-dir="asc"]::after{ content:" ↑"; }
.pf-sort[data-dir="desc"]::after{ content:" ↓"; }

.pf-index-list{ margin:0; padding:0; list-style:none; }
.pf-row{ border-bottom:1px solid var(--line); }
.pf-row-inner{
  display:grid;
  grid-template-columns:var(--pf-cols);
  column-gap:var(--pf-col-gap);
  align-items:baseline;
  padding:clamp(16px,2.4vh,22px) var(--pf-row-pad);
  color:var(--ink-dim);
  text-decoration:none;
  transition:color 0.25s ease;
}
.pf-row-inner > *{ min-width:0; transition:transform 0.35s cubic-bezier(0.2,0.7,0.2,1), color 0.25s ease; }
a.pf-row-inner:focus-visible{ outline-offset:-2px; }
/* Hover and focus: the row brightens and its text steps right. */
a.pf-row-inner:hover,
a.pf-row-inner:focus-visible{ color:var(--ink); }
a.pf-row-inner:hover > *,
a.pf-row-inner:focus-visible > *{ transform:translateX(6px); }
a.pf-row-inner:hover .pf-col-role,
a.pf-row-inner:hover .pf-col-pillar,
a.pf-row-inner:hover .pf-col-action,
a.pf-row-inner:focus-visible .pf-col-role,
a.pf-row-inner:focus-visible .pf-col-pillar,
a.pf-row-inner:focus-visible .pf-col-action{ color:var(--ink-dim); }
.pf-col-year{ font-family:var(--mono); font-size:12.5px; }
.pf-col-client{ font-size:0.98rem; }
.pf-col-title{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 10px;
  font-family:var(--disp);
  font-weight:600;
  font-size:1.05rem;
  line-height:1.3;
  color:var(--ink);
}
.pf-col-role,
.pf-col-pillar{ font-family:var(--mono); font-size:12px; color:var(--ink-faint); }
.pf-col-action{ align-self:center; color:var(--ink-faint); }
.pf-col-action svg{ display:block; width:18px; height:18px; }

.pf-empty,
.pf-error{ max-width:52ch; padding:clamp(24px,6vh,60px) 0; color:var(--ink-dim); }
.pf-empty p,
.pf-error p{ margin:0 0 14px; }
.pf-empty a,
.pf-error a{
  font-family:var(--mono);
  font-size:12.5px;
  color:var(--ink);
  text-decoration:none;
  border-bottom:1px solid var(--line-bright);
  padding-bottom:4px;
}
.pf-empty a::after,
.pf-error a::after{ content:" →"; }
.pf-empty a:hover,
.pf-error a:hover{ border-bottom-color:var(--ink); }

/* ---------- portfolio: detail view ---------- */
.pf-detail{
  width:min(1100px, calc(100vw - 32px));
  max-width:none;
  max-height:calc(100vh - 32px);
  padding:0;
  overflow:auto;
  color:var(--ink);
  background:var(--bg);
  border:1px solid var(--line-bright);
}
.pf-detail.is-lightbox{ width:min(1400px, calc(100vw - 32px)); }
.pf-detail::backdrop{ background:var(--backdrop); }
.pf-detail-body{ position:relative; padding:clamp(20px,3vw,40px); }
.pf-detail-close{
  position:absolute;
  top:clamp(14px,2vw,26px); right:clamp(14px,2vw,26px);
  width:36px; height:36px;
  display:grid; place-items:center;
  padding:0;
  color:var(--ink-dim);
  background:var(--bg);
  border:1px solid var(--line-bright);
  border-radius:50%;
  cursor:pointer;
  transition:color 0.2s ease, border-color 0.2s ease;
}
.pf-detail-close:hover{ color:var(--ink); border-color:var(--ink); }
.pf-detail-close svg{ width:16px; height:16px; }
.pf-detail-header{ padding-right:52px; margin:0 0 clamp(18px,3vh,28px); }
.pf-detail-title{
  margin:0;
  font-family:var(--disp);
  font-weight:600;
  font-size:clamp(1.5rem,3vw,2.4rem);
  line-height:1.1;
  letter-spacing:-0.01em;
}
.pf-detail-meta{ margin:10px 0 0; font-family:var(--mono); font-size:12.5px; color:var(--ink-dim); }
.pf-detail-tags{ display:flex; flex-wrap:wrap; gap:8px; margin-top:14px; }
.pf-detail-content{ display:grid; gap:clamp(18px,3vh,28px); }
.pf-detail-summary{ margin:0; max-width:65ch; color:var(--ink-dim); }
.pf-detail-credits{
  display:grid; grid-template-columns:auto 1fr; gap:6px 20px;
  margin:0;
  font-family:var(--mono); font-size:12.5px;
}
.pf-detail-credits dt{ color:var(--ink-faint); }
.pf-detail-credits dd{ margin:0; color:var(--ink-dim); }
.pf-detail-link{
  color:var(--ink);
  text-decoration:none;
  border-bottom:1px solid var(--line-bright);
  overflow-wrap:anywhere;
  transition:border-color 0.2s ease;
}
.pf-detail-link::after{ content:" ↗"; }
.pf-detail-link:hover{ border-bottom-color:var(--ink); }
.pf-detail-video,
.pf-detail-embed,
.pf-detail-image{ display:block; width:100%; background:var(--bg-alt); }
.pf-detail-video,
.pf-detail-embed{ aspect-ratio:16/9; }
.pf-detail-embed iframe{ display:block; width:100%; height:100%; border:0; }
/* An interactive scene (media.embed): the frame, then a bar with the full screen control. In
   full screen the frame fills the screen whatever its aspect ratio. */
.pf-detail-interactive{ display:grid; gap:10px; }
.pf-detail-embed--interactive:fullscreen{ aspect-ratio:auto; width:100%; height:100%; max-height:none; }
.pf-detail-interactive-bar{
  display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between; gap:8px 20px;
  font-family:var(--mono); font-size:12.5px; color:var(--ink-faint);
}
.pf-detail-full{
  padding:0; background:none; border:0; border-bottom:1px solid var(--line-bright);
  font:inherit; color:var(--ink-dim); cursor:pointer;
  text-decoration:none;
  transition:color 0.2s ease, border-color 0.2s ease;
}
.pf-detail-full--tab::after{ content:" ↗"; }
.pf-detail-full:hover{ color:var(--ink); border-bottom-color:var(--ink); }
.is-lightbox .pf-detail-video,
.is-lightbox .pf-detail-image{ max-height:calc(100vh - 200px); object-fit:contain; }
/* Breakdown images two to a row. Each keeps its own shape (rows line up at the top), and an
   odd one out at the end spans the full width rather than leaving a gap beside it. */
.pf-detail-gallery{
  display:grid;
  grid-template-columns:repeat(2, minmax(0,1fr));
  gap:clamp(10px,1.5vw,16px);
  align-items:start;
}
.pf-detail-gallery .pf-detail-image:last-child:nth-child(odd){ grid-column:1 / -1; }

/* While the detail view is open the page behind it doesn't scroll. The scrollbar's width
   (--scrollbar-comp, set by portfolio-detail.js) is given back so nothing shifts sideways. */
html.is-scroll-locked{ overflow:hidden; }
html.is-scroll-locked body{ padding-right:var(--scrollbar-comp, 0px); }
html.is-scroll-locked body > header{ right:var(--scrollbar-comp, 0px); }
html.is-scroll-locked #grid-canvas{ width:calc(100% - var(--scrollbar-comp, 0px)); }

@media (prefers-reduced-motion: reduce){
  .pf-card-media img,
  .pf-row-inner > *{ transition:none; }
  a.pf-card:hover .pf-card-media img,
  a.pf-row-inner:hover > *,
  a.pf-row-inner:focus-visible > *{ transform:none; }
}

/* Two columns on tablets; a wide card then fills a row. */
@media (max-width: 1023px){
  .pf-featured-grid{ grid-template-columns:repeat(2, minmax(0,1fr)); grid-auto-rows:clamp(200px,30vw,300px); }
  /* With two columns the grid gets taller, so three rows would leave a gap beside it. */
  .pf-card--extra-tall{ grid-row:span 2; }
}
@media (max-width: 719px){
  /* One full-width card after another, all the same shape. */
  .pf-featured-grid{ grid-template-columns:minmax(0,1fr); grid-auto-rows:auto; }
  .pf-card--wide,
  .pf-card--tall,
  .pf-card--extra-tall{ grid-column:auto; grid-row:auto; }
  .pf-card-media{ flex:none; aspect-ratio:16/10; }
  .pf-count{ margin-left:0; width:100%; }
  /* Breakdown images go back to one per row. */
  .pf-detail-gallery{ grid-template-columns:minmax(0,1fr); }
  /* Taller on phones, so there's room to look around in portrait. */
  .pf-detail-embed--interactive{ aspect-ratio:4/5; max-height:calc(100svh - 160px); }

  /* Rows fold into two lines: "Client — Project", then "Year · Role · Pillar". */
  .pf-index-cols{ display:none; }
  .pf-row-inner{
    position:relative;
    display:flex; flex-wrap:wrap; align-items:baseline;
    gap:4px 0;
    padding-right:calc(var(--pf-row-pad) + 28px);
  }
  .pf-row-inner > :empty{ display:none; }
  .pf-col-client{ order:1; margin-right:0.45em; color:var(--ink); }
  .pf-col-client::after{ content:" —"; color:var(--ink-faint); }
  .pf-col-title{ order:2; }
  .pf-row-inner::after{ content:""; order:3; flex-basis:100%; }
  .pf-col-year{ order:4; font-size:11.5px; color:var(--ink-faint); }
  .pf-col-role{ order:5; font-size:11.5px; }
  .pf-col-pillar{ order:6; font-size:11.5px; }
  .pf-col-action{ position:absolute; right:var(--pf-row-pad); top:50%; margin-top:-9px; }
  /* Separators end the item before them, so a wrapped line never starts with one. */
  .pf-col-year:has(~ .pf-col-role:not(:empty), ~ .pf-col-pillar:not(:empty))::after,
  .pf-col-role:has(~ .pf-col-pillar:not(:empty))::after{ content:"·"; margin:0 0.6em; }
}

footer{
  position:relative; z-index:1;
  padding:26px clamp(20px,5vw,56px);
  border-top:1px solid var(--line);
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:10px;
  font-family:var(--mono); font-size:11.5px; color:var(--ink-faint);
}

@media (max-width: 860px){
  /* Stacked: the icon row (a quarter of the screen height) above the text, below the fixed
     header (22px padding top and bottom around a 32px row), and right of the progress bar. */
  .services-sticky{
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:25vh minmax(0,1fr);
    padding:76px 0 0 calc(var(--progress-left) + var(--progress-width));
  }
  .shape-col{ padding:0; justify-content:center; }
  .shape-stage{ width:auto; height:100%; max-width:100%; }
  .text-col{ padding:16px clamp(20px,5vw,40px) 0 12px; align-items:flex-start; }
  /* Tighter type so a whole step fits on short phones. */
  .panel .tag{ margin-bottom:10px; }
  .panel h2{ margin-bottom:12px; }
  .panel p{ font-size:0.95rem; --text-line:1.55; }
  .panel ul{ margin-top:12px; gap:4px; }
  .panel-portfolio-link{ margin-top:16px; }
  .preview-col{ display:none; }
  .panel-portfolio-link{ display:inline-block; }
  .services-wrap{ height:366vh; }
  /* Stacked, like the services on mobile: the model row a quarter of the screen tall. */
  .about{ grid-template-columns:minmax(0,1fr); padding-left:clamp(20px,5vw,40px); padding-right:clamp(20px,5vw,40px); }
  .about-figure{ height:25vh; padding-left:0; margin-bottom:24px; }
  .about-stage{ width:auto; height:100%; }
  .about-text{ padding-left:0; }
  /* Still one row, in equal columns; the labels are already split over two lines. */
  .about-stats{ grid-auto-columns:minmax(0,1fr); gap:12px; }
  .contact-grid{ grid-template-columns:1fr; }
}

/* Short phones (an iPhone SE is 667px tall): the services section is pinned to one screen,
   so a smaller icon row and tighter type keep a whole service, list and link included, in
   view. Taller phones and desktop are unaffected. */
@media (max-width: 860px) and (max-height: 700px){
  .services-sticky{ grid-template-rows:18vh minmax(0,1fr); }
  .text-col{ padding-top:10px; }
  .panel .tag{ margin-bottom:6px; }
  .panel h2{ font-size:1.5rem; margin-bottom:10px; }
  .panel p{ font-size:0.9rem; --text-line:1.5; margin-bottom:10px; }
  .panel ul{ margin-top:8px; gap:2px; }
  .panel-portfolio-link{ margin-top:12px; }
}

/* The narrowest phones (320–360px): a smaller stat row, so its longest words still fit. */
@media (max-width: 360px){
  .about-stats div b{ font-size:1.45rem; }
  .about-stats div span{ font-size:10px; }
}
