/* ============================================================
   Ana Malai — Design Tokens
   ============================================================
   The portfolio site has no webfonts, no icon pack, and one
   accent colour. Everything else is monochrome + hairline grid.
   Mirror the source CSS variables exactly; semantic tokens
   layer on top.
   ============================================================ */

:root {
  /* ── Color · base ──────────────────────────────────────── */
  --bg:        #000;     /* page background */
  --fg:        #fff;     /* primary text + links */
  --muted:     #555;     /* tertiary meta, the giant footer mark */
  --muted-2:   #999;     /* body paragraphs in inner pages */
  --muted-3:   #aaa;     /* hover-revealed text */
  --border:    #1a1a1a;  /* THE hairline. Used everywhere. */
  --border-2:  #222;     /* darker tertiary border (control pills) */
  --surface:   #070707;  /* lab-card hover background */
  --surface-2: #111;     /* color picker / modal interior */
  --surface-3: #1a1a1a;  /* button bg / close-btn */

  /* Highlight marks (muted-white canonical) */
  --mark:      rgba(255, 255, 255, 0.55);

  /* Highlight marks (alt tinted palette from `home copy.html`) */
  --mark-yellow: #e6c878;
  --mark-green:  #7ac4a0;
  --mark-blue:   #92b4d8;
  --mark-pink:   #d49a94;
  --mark-yellow-bg: rgba(230, 200, 120, 0.08);
  --mark-green-bg:  rgba(120, 196, 160, 0.08);
  --mark-blue-bg:   rgba(146, 180, 216, 0.08);
  --mark-pink-bg:   rgba(212, 154, 148, 0.08);

  /* Single accent — image-compressor lab tool only */
  --accent-lime:    #d4ff4f;
  --accent-mint:    #9be89b; /* success indicator */
  --accent-error:   #ff6b6b;

  /* ── Type ─────────────────────────────────────────────── */
  --font:      -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', 'DM Mono', Menlo, monospace;

  /* Size scale (px) */
  --t-9:   9px;    /* hairline labels, eyebrows */
  --t-10: 10px;    /* nav meta, footer copy */
  --t-11: 11px;    /* nav links, project meta */
  --t-12: 12px;    /* body small, CV labels */
  --t-13: 13px;    /* body paragraphs */
  --t-14: 14px;    /* hero standfirst */
  --t-15: 15px;    /* lab card title */
  --t-hero-num:    clamp(22px, 2.2vw, 32px);   /* (01) (02) project numbers */
  --t-row-label:   clamp(20px, 2.2vw, 28px);   /* row-label inside case studies */
  --t-page-title:  clamp(28px, 4vw, 52px);     /* "Selected Work" — unified with lab title */
  --t-lab-title:   clamp(28px, 4vw, 52px);     /* "Experiments" — same scale as page title */
  --t-footer:      clamp(64px, 10vw, 140px);   /* "Let's work together." */
  --t-footer-mark: 14.8vw;                     /* stretched "ana" mark */

  /* Weights — almost everything is 400. */
  --w-regular: 400;
  --w-medium:  500;
  --w-bold:    700;

  /* Letter-spacing */
  --ls-tight:  -0.04em;   /* footer display */
  --ls-tight-2:-0.03em;   /* page titles */
  --ls-none:   0;
  --ls-loose:  0.04em;    /* uppercase labels */
  --ls-loose-2:0.08em;    /* link eyebrows */
  --ls-loose-3:0.12em;    /* menu pill */
  --ls-loose-4:0.15em;    /* widest — section meta */

  /* Line-height */
  --lh-display:    0.88;
  --lh-tight:      1.05;
  --lh-snug:       1.4;
  --lh-body:       1.75;
  --lh-body-loose: 1.85;
  --lh-list:       1.9;

  /* ── Spacing ──────────────────────────────────────────── */
  --space-1:   4px;
  --space-2:   6px;
  --space-3:   8px;
  --space-4:  10px;
  --space-5:  14px;
  --space-6:  16px;
  --space-7:  20px;
  --space-8:  26px;   /* home-column gutter */
  --space-9:  28px;   /* canonical page padding `--p` */
  --p:        28px;   /* alias — used in logos/psc inline styles */
  --space-10: 40px;
  --space-11: 60px;

  --col-left:   360px; /* home About column */
  --col-right:  300px; /* home CV column */
  --photodump-margin: 160px;
  --photodump-gap:     24px;

  /* ── Borders & radii ──────────────────────────────────── */
  --hairline:  1px solid var(--border);
  --radius-0:   0;       /* cards, image thumbs */
  --radius-2:   2px;     /* mark background */
  --radius-4:   4px;     /* modal */
  --radius-6:   6px;     /* hue slider */
  --radius-8:   8px;     /* color picker */
  --radius-10: 10px;     /* image trail items */
  --radius-pill: 999px;  /* menu pill, "View Project" overlay, social circles */

  /* ── Shadows ──────────────────────────────────────────── */
  --shadow-pill:    0 2px 16px rgba(0, 0, 0, 0.35);  /* floating Menu */
  --shadow-modal:   0 8px 32px rgba(0, 0, 0, 0.80);  /* color picker */
  --backdrop-blur:  blur(4px);
  --backdrop-blur-strong: blur(16px);

  /* ── Easing & duration ────────────────────────────────── */
  --ease-out-expo:    cubic-bezier(0.16, 1, 0.30, 1);      /* menu panel slide */
  --ease-in-out-hard: cubic-bezier(0.87, 0, 0.13, 1);      /* dot bounce */
  --ease-out-soft:    cubic-bezier(0.25, 0.46, 0.45, 0.94);/* photo reveal */
  --ease-page-fade:   cubic-bezier(0.25, 0.10, 0.25, 1.00);

  --dur-fast:    150ms;
  --dur-base:    220ms;
  --dur-medium:  300ms;
  --dur-slow:    500ms;
  --dur-panel:   850ms;

  /* ── Cursor token (custom-cursor sites still need a fallback) ── */
  /* The site uses `cursor: none` and renders an 8px dot via JS. */

  /* ============================================================
     ── Chrome tokens (v2 — consistency pass) ────────────────────
     Reconciles the four header patterns and two footer patterns
     observed in the codebase (case-study vs lab vs experiment).
     Use these instead of inlining font-sizes/padding into each
     page so headers, footers, and dividers stay aligned.
     ============================================================ */

  /* Header — canonical for ALL inner pages (case study, lab, experiment).
     Old logos.html / psc.html used `padding: 16px var(--p)`; cavalry, lab,
     and experiments use 18px — 18px wins. */
  --header-py:           10px;
  --header-px:           var(--space-9);   /* 28px */
  --header-h:            48px;             /* fixed-height equivalent: 10px + 28px pill + 10px */
  --header-border:       var(--hairline);

  /* Title / breadcrumb pattern. All inner pages share one wordmark size
     ("Ana Malai" / "Home") at 12px / 0.04em. Experiments add a slash + page
     name on the right of it at 11px / 0.06em / muted-2. */
  --t-wordmark:          var(--t-12);      /* 12px */
  --ls-wordmark:         var(--ls-loose);  /* 0.04em */
  --t-breadcrumb:        var(--t-11);      /* 11px */
  --ls-breadcrumb:       0.06em;
  --color-breadcrumb:    var(--muted-2);

  /* Footer — canonical for ALL pages. Old logos.html / psc.html used 13px
     sentence-case "2013 – 2026 © · Built in Spain with Love" — those are
     deprecated. New canonical: 10px uppercase / 0.08em / muted. */
  --footer-py:           14px;
  --footer-px:           var(--space-9);   /* 28px */
  --t-footer-copy:       var(--t-10);      /* 10px */
  --ls-footer-copy:      0.08em;
  --color-footer-copy:   var(--muted);     /* #555 */
  --footer-border:       var(--hairline);

  /* Divider rules. The hairline (1px #1a1a1a) is the only border weight in
     the system. Use it for EVERY section break — never use margin alone.
     Sandwich rule: opening top border → content → closing bottom border.
     Never skip the opening top border (psc.html after first video is broken).
     Image-grid gap inside a case study is 14px (matches cavalry / encryption
     day). Older 2px and 1px gaps in logos.html are deprecated. */
  --gallery-gap:         14px;
  --section-py-tight:    20px;   /* row-left / row-right inner padding */
  --section-py:          var(--space-9); /* 28px — hero / strategy blocks */

  /* ── Experiment panel tokens ─────────────────────────────────
     Canonical for noise-gradient-studio, cavalry-player,
     forge-dynamics-player, and any future lab tool.            */
  --panel-bg:            #050505;
  --panel-border:        1px solid #1e1e1e;
  --panel-radius:        6px;
  --panel-pad:           20px;
  --panel-width:         280px;      /* all tools unified at 280px */
  --panel-gap:           12px;       /* gap between panel rows */

  /* Panel section title: 10px / 0.08em / uppercase / #666 */
  --t-panel-section:     10px;
  --ls-panel-section:    0.08em;
  --color-panel-section: #666;

  /* Panel row label: 9px / 0.08em / uppercase / #555
     Note: cavalry-player mistakenly uses lowercase + 0.04em — retire that. */
  --t-panel-label:       9px;
  --ls-panel-label:      0.08em;
  --color-panel-label:   #555;

  /* Panel value readout (right-aligned next to slider): 10px / #555 */
  --t-panel-val:         10px;
  --color-panel-val:     #555;

  /* Slider track + thumb */
  --slider-track-h:      1px;
  --slider-track-bg:     #333;
  --slider-thumb-size:   10px;      /* white circle */

  /* Color swatch circles */
  --swatch-size:         18px;
  --swatch-border:       1px solid #222;
  --swatch-border-active:1px solid #fff;
}

/* ============================================================
   Semantic typography classes
   Use these on real elements to inherit the system instantly.
   ============================================================ */

html, body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-weight: var(--w-regular);
  line-height: var(--lh-body);
}

/* Eyebrow / micro-label — small caps with wide tracking */
.am-eyebrow {
  font-size: var(--t-10);
  letter-spacing: var(--ls-loose-3);
  text-transform: uppercase;
  color: var(--muted);
}

/* Nav meta — slightly larger eyebrow used in headers */
.am-nav-meta {
  font-size: var(--t-11);
  letter-spacing: var(--ls-loose);
  text-transform: uppercase;
  color: var(--fg);
}
.am-nav-meta-muted {
  font-size: var(--t-11);
  letter-spacing: var(--ls-loose);
  text-transform: uppercase;
  color: var(--muted-2);
}

/* Page title */
.am-page-title {
  font-size: var(--t-page-title);
  font-weight: var(--w-regular);
  letter-spacing: var(--ls-tight-2);
  line-height: var(--lh-tight);
  color: var(--fg);
}

/* Lab section title — slightly larger, even tighter */
.am-lab-title {
  font-size: var(--t-lab-title);
  font-weight: var(--w-regular);
  letter-spacing: var(--ls-tight-2);
  line-height: 1;
  color: var(--fg);
}

/* Hero number ("01/", "(01)") */
.am-hero-num {
  font-size: var(--t-hero-num);
  font-weight: var(--w-regular);
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--fg);
}

/* Row label — section "title" used down the left rail of case studies */
.am-row-label {
  font-size: var(--t-row-label);
  font-weight: var(--w-regular);
  line-height: 1.2;
  color: var(--fg);
}

/* Body text — paragraphs inside about and project pages */
.am-body {
  font-size: var(--t-13);
  line-height: var(--lh-body-loose);
  color: var(--muted-2);
}
.am-body p + p { margin-top: 14px; }
.am-body a {
  color: var(--fg);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: opacity var(--dur-base);
}
.am-body a:hover { opacity: 0.6; }

/* Body small — about column on home */
.am-body-sm {
  font-size: var(--t-12);
  line-height: var(--lh-body);
  color: var(--fg);
}

/* Mono / tabular (lab tools) */
.am-mono {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: 0.04em;
}

/* Display footer mark ("ana" / "Let's work together.") */
.am-footer-display {
  font-size: var(--t-footer);
  font-weight: var(--w-regular);
  letter-spacing: var(--ls-tight);
  line-height: 0.95;
  color: var(--fg);
  text-align: center;
}
.am-footer-mark {
  font-size: var(--t-footer-mark);
  font-weight: var(--w-bold);
  line-height: var(--lh-display);
  color: #222;
  white-space: nowrap;
}

/* ============================================================
   Common components
   ============================================================ */

/* Hairline divider — the entire grid is built from these */
.am-hr {
  border: none;
  border-top: var(--hairline);
}

/* The white "Menu" pill — top-right on inner pages, fixed bottom-right on home */
.am-pill-menu {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px 8px 14px;
  background: #fff;
  color: #000;
  border: none;
  border-radius: var(--radius-pill);
  font-family: var(--font);
  font-size: var(--t-10);
  font-weight: var(--w-medium);
  letter-spacing: var(--ls-loose-3);
  text-transform: uppercase;
  box-shadow: var(--shadow-pill);
  cursor: none;
}

/* Ghost pill button — "Open →" on lab cards */
.am-pill-ghost {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  background: transparent;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-pill);
  font-family: var(--font);
  font-size: var(--t-10);
  letter-spacing: var(--ls-loose-2);
  text-transform: uppercase;
  color: var(--fg);
  cursor: none;
  transition: border-color var(--dur-base), background var(--dur-base), color var(--dur-base);
}
.am-pill-ghost:hover {
  border-color: var(--fg);
  background: var(--fg);
  color: var(--bg);
}

/* Animated-underline link — body links inside list cells */
.am-link {
  position: relative;
  color: var(--fg);
  text-decoration: none;
  display: inline-block;
  width: fit-content;
}
.am-link::after {
  content: '';
  position: absolute;
  bottom: -1px; left: 0;
  width: 0; height: 1px;
  background: var(--fg);
  transition: width var(--dur-medium);
}
.am-link:hover::after { width: 100%; }

/* Social circle — IG / Li / Be / X */
.am-social {
  width: 32px;
  height: 32px;
  border: 1px solid #333;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--t-10);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  transition: border-color var(--dur-base), color var(--dur-base);
}
.am-social:hover {
  border-color: #888;
  color: var(--muted-3);
}

/* Mark — glyph-decode highlight */
mark.am-mark {
  background: transparent;
  color: var(--mark);
  border-radius: var(--radius-2);
  padding: 0 2px;
}

/* ============================================================
   v2 chrome components — canonical header & footer
   ============================================================
   Use these on EVERY inner page (case study, lab, experiment).
   Drop-in replacements for the divergent header / footer-copy
   blocks currently inlined in each html file.
   ============================================================ */

/* ── Page header ─────────────────────────────────────────────── */
.am-header {
  position: sticky; top: 0; z-index: 100;
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--header-py) var(--header-px);
  border-bottom: var(--header-border);
  background: var(--bg);
}
.am-header__left {
  display: flex; align-items: baseline; gap: 14px;
  font-size: var(--t-wordmark);
  letter-spacing: var(--ls-wordmark);
  text-transform: uppercase;
}
.am-header__wordmark {
  color: var(--fg);
  text-decoration: none;
  transition: opacity var(--dur-base);
}
.am-header__wordmark:hover { opacity: 0.5; }
/* .am-header__sep + .am-header__crumb appearance is governed by the single
   unified breadcrumb rule below (slash always matches the crumb). */
.am-header__crumb a { color: var(--muted); text-decoration: none; transition: color var(--dur-base); }
.am-header__crumb a:hover { color: var(--fg); }

/* ── Page footer (the one-line copyright strip) ──────────────── */
.am-footer-copy {
  display: flex; justify-content: space-between; align-items: center;
  padding: var(--footer-py) var(--footer-px);
  border-top: var(--footer-border);
  background: var(--bg);
}
.am-footer-copy span {
  font-size: var(--t-footer-copy);
  letter-spacing: var(--ls-footer-copy);
  text-transform: uppercase;
  color: var(--color-footer-copy);
}

/* Variant used on case studies: anchored to the bottom of the viewport.
   Pair with `padding-bottom: 46px` on body to clear page content. */
.am-footer-copy--fixed {
  position: fixed; bottom: 0; left: 0; right: 0;
  z-index: 50;
}

/* ── Section dividers ────────────────────────────────────────── */
/* Every section break is a hairline. NEVER use margin alone. */
.am-section { border-bottom: var(--hairline); }
.am-section__pad { padding: var(--section-py-tight) var(--header-px); }
.am-section__pad--lg { padding: var(--section-py) var(--header-px); }

/* Two-column "row" pattern (label left / body right) used on every
   case study. Always 50/50, always divided by a vertical hairline. */
.am-row {
  display: grid;
  grid-template-columns: 50% 50%;
  border-bottom: var(--hairline);
}
.am-row > * { padding: var(--section-py-tight) var(--header-px); }
.am-row > *:first-child { border-right: var(--hairline); }

/* Image grids — canonical gap is 14px (matches cavalry / encryption-day).
   Older 2px / 1px gaps in logos.html are deprecated. */
.am-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gallery-gap); }
.am-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gallery-gap); }

/* ============================================================
   Case Study — Shared Layout
   Applies to: logos, psc, encryption-day, overture, reserve, cavalry
   Link this file and keep only page-specific overrides in <style>.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  min-height: 100vh;
  cursor: none;
}
body { padding-bottom: 42px; } /* clears fixed footer (14px pad + 12px text + 14px pad + 1px border ≈ 41px) */

/* ── Cursor ── */
#cursor {
  position: fixed; width: 8px; height: 8px; border-radius: 50%;
  background: #fff; pointer-events: none; z-index: 99999;
  transform: translate(-50%, -50%); mix-blend-mode: difference;
  transition: width 0.2s, height 0.2s;
}
#cursor.hover { width: 40px; height: 40px; }

/* ── Header ── */
header {
  position: sticky; top: 0; z-index: 100;
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 28px; border-bottom: 1px solid var(--border); background: var(--bg);
}
.header-left { display: flex; align-items: baseline; gap: 14px; }
/* .wordmark and .site-name are the same element on different pages */
.wordmark, .site-name {
  font-size: 12px; font-weight: 400; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--fg); text-decoration: none;
  transition: opacity 0.2s;
}
.wordmark:hover, .site-name:hover { opacity: 0.5; }
/* ── RULE: the breadcrumb separator "/" ALWAYS matches the crumb after it ──
   The slash (.header-sep / .sep) and the project name (.header-crumb /
   header .page-title) share ONE color + size, so they can never drift apart.
   To restyle the breadcrumb, change the tokens below ONCE — never style the
   slash on its own (that's the mistake we keep making). The wordmark/site-name
   stays brighter (--fg) on purpose; only the slash + crumb are muted and equal. */
.header-sep, .sep, .am-header__sep,
.header-crumb, header .page-title, .am-header__crumb {
  color: var(--color-breadcrumb);
  font-size: var(--t-breadcrumb);
  letter-spacing: var(--ls-breadcrumb);
}
.header-crumb, header .page-title, .am-header__crumb { text-transform: uppercase; }
#am-menu-btn { display: none !important; }
#header-pill {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 16px 8px 14px; background: #fff; color: #000; border: none;
  border-radius: 999px; font-family: var(--font); font-size: 10px; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; cursor: none; overflow: hidden;
  box-shadow: 0 2px 16px rgba(0,0,0,0.35);
}
#header-pill .am-dot { width: 5px; height: 5px; border-radius: 50%; background: #000; flex-shrink: 0; }
#header-pill .am-dot.am-bounce { animation: am-dot-bounce 0.55s cubic-bezier(0.87,0,0.13,1) forwards; }
@keyframes am-dot-bounce {
  0%  { transform: translateY(0); }
  44% { transform: translateY(-20px); }
  45% { transform: translateY(20px); }
  100%{ transform: translateY(0); }
}

/* ── Hero ── */
.hero {
  display: grid; grid-template-columns: 50% 50%;
  border-bottom: 1px solid var(--border); min-height: 200px;
}
.hero-left { padding: 28px; border-right: 1px solid var(--border); display: flex; align-items: flex-start; }
.hero-num  { font-size: clamp(22px, 2.2vw, 32px); font-weight: 400; letter-spacing: -0.01em; line-height: 1; }
.hero-right { padding: 28px; }
.hero-title { font-size: 14px; font-weight: 400; margin-bottom: 20px; }
/* Hero meta row: desktop stacks role only (tech highlights live in the intro row); mobile shows both side by side */
.hero-meta-row { display: flex; flex-direction: column; gap: 0; }
.hero-meta-row > div:nth-child(2) { display: none; }
.role-label { font-size: 12px; color: var(--muted2, #999); margin-bottom: 6px; display: flex; align-items: center; gap: 6px; }
.role-list  { list-style: none; }
.role-list li { font-size: 13px; line-height: 1.5; }
.collab { font-size: 12px; color: var(--muted2, #999); margin-top: 16px; }
.collab a { color: var(--fg); text-underline-offset: 2px; }

/* ── Gallery ── */
.gallery-wrap { border-bottom: 1px solid var(--border); overflow: hidden; }
.gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.gallery-item { overflow: hidden; background: #000; display: flex; align-items: center; justify-content: center; height: 55vh; }
.gallery-item img { display: block; width: 100%; height: 100%; object-fit: contain; }
.gif-item { background: #000; height: 55vh; display: flex; align-items: center; justify-content: center; }
.gif-item img { display: block; max-width: 100%; max-height: 100%; }

/* ── Section row (label left / body right) ── */
.row { display: grid; grid-template-columns: 50% 50%; border-bottom: 1px solid var(--border); }
.row-left  { padding: 20px 28px; border-right: 1px solid var(--border); }
.row-right { padding: 20px 28px; }
.row-label { font-size: clamp(20px, 2.2vw, 28px); color: var(--fg); line-height: 1.2; }
.body-text { font-size: 13px; line-height: 1.6; color: var(--muted2, #999); }
.body-text p + p { margin-top: 14px; }
.body-text a { color: var(--fg); text-underline-offset: 2px; }
.sub-label { font-size: 12px; color: var(--muted2, #999); margin-bottom: 6px; display: flex; align-items: center; gap: 6px; }
.sub-list  { list-style: none; }
.sub-list li { font-size: 13px; line-height: 1.5; }

/* ── Image grids ── */
.img-grid-3 { display: grid; grid-template-columns: repeat(3,1fr); gap: 14px; }
.img-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.img-cell { overflow: hidden; }
.img-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.img-cell-pad { background: #000; padding: 20px; }
.img-cell-pad img { width: 100%; height: auto; display: block; }
.gif-cell { background: #000; display: flex; align-items: center; justify-content: center; }
.gif-cell img { max-width: 100%; max-height: 100%; display: block; }
.img-full img { width: 100%; display: block; }

/* ── Moods ── */
.moods-section { border-bottom: 1px solid var(--border); }
.moods-section img { width: 100%; display: block; }

/* ── Placeholder ── */
.ph-block { background: #080808; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: center; min-height: 200px; }
.ph-block span { font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: #1e1e1e; }

/* ── Project navigation ── */
.proj-nav { display: flex; justify-content: space-between; align-items: center; height: 110px; padding: 0 28px; }
.proj-nav a { font-size: clamp(13px,1.3vw,16px); letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted2, #999); text-decoration: none; transition: opacity 0.2s; }
.proj-nav a:hover { opacity: 0.4; }

/* ── Footer ── */
#site-footer { border-top: 1px solid var(--border); }
.footer-links { display: flex; justify-content: space-between; padding: 20px 28px; border-bottom: 1px solid var(--border); }
.footer-links a { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg); text-decoration: underline; text-underline-offset: 3px; transition: opacity 0.2s; }
.footer-links a:hover { opacity: 0.4; }
.footer-copy { display: flex; justify-content: space-between; align-items: center; padding: 14px 28px; border-top: 1px solid var(--border); }
.footer-copy span { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
#footer-clock { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
/* logos/psc use a fixed footer variant */
footer { width: 100%; position: fixed; bottom: 0; left: 0; right: 0; background: var(--bg); z-index: 50; }

/* ── Fade-in ── */
@keyframes fadeUp { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }
header     { animation: fadeUp 0.4s ease both; }
.hero      { animation: fadeUp 0.4s ease 0.05s both; }
.gallery-wrap { animation: fadeUp 0.4s ease 0.1s both; }

/* ── Mobile/desktop visibility helpers (used across case studies) ── */
/* hide-mobile: NO base display rule — elements keep their natural display (grid/flex) on desktop */
.show-mobile-only { display: none; }

/* ════════════════════════════════════════════════════════════════
   EXPERIMENT PLAYER COMPONENTS (merged from component library)
   Header bar, close button, colour swatches, and colour picker —
   used by cavalry-player.html & forge-dynamics-player.html.
   ════════════════════════════════════════════════════════════════ */
/* ── Experiment page header ──────────────────────────────────────
   Use class="am-exp-header" on <header> in every experiment player.
   Padding matches the canonical --header-py (10px) so height is
   identical to all other inner pages.                             */
.am-exp-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--header-py, 10px) var(--header-px, 28px);
  border-bottom: var(--header-border, 1px solid #1a1a1a);
  background: var(--bg);
}

/* ── Experiment page header nav — Lab / Experiment name ──────────
   Use on every experiment player page. Replaces all inline nav styles.
   HTML pattern:
     <nav class="am-exp-nav">
       <a href="lab.html" target="_parent">Lab</a>
       <span>/</span>
       <span>Experiment Name</span>
     </nav>                                                          */
.am-exp-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* "Lab" link — full white, links back */
.am-exp-nav a {
  color: var(--fg);
  text-decoration: none;
  transition: opacity var(--dur-base);
}
.am-exp-nav a:hover { opacity: 0.6; }

/* Slash separator — noticeably visible but secondary */
.am-exp-nav span:nth-child(2) { color: #555; }

/* Experiment name — muted */
.am-exp-nav span:nth-child(3) { color: var(--muted-2, #999); }

/* ── Experiment close button (× cross with clockwise rotation) ───
   Used on cavalry-player, forge-dynamics-player, and any future
   experiment page. Wire animation via wireCloseBtn() in site-utils.js. */
.am-close-btn {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--surface-3, #1a1a1a);
  border: none;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.2s;
  position: relative;
}
.am-close-btn:hover { background: #282828; }
/* Cross drawn with pseudo-elements — identical at 0° and 180° so the
   silent reset after the leave animation is completely invisible */
.am-close-btn::before,
.am-close-btn::after {
  content: '';
  position: absolute;
  width: 12px; height: 1.5px;
  background: #fff;
  border-radius: 1px;
}
.am-close-btn::before { transform: rotate(45deg); }
.am-close-btn::after  { transform: rotate(-45deg); }

/* ── Experiment colour grid ──────────────────────────────────────
   Horizontal row of clickable swatch circles used in cavalry-player
   and forge-dynamics-player. Canvas width 280px → wraps at ~15 swatches. */
.am-color-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.color-swatch {
  width: var(--swatch-size, 18px);
  height: var(--swatch-size, 18px);
  border-radius: 50%;
  border: var(--swatch-border, 1px solid #222);
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.15s, transform 0.15s;
}
.color-swatch:hover  { transform: scale(1.15); }
.color-swatch.active { border: var(--swatch-border-active, 1px solid #fff); }

/* ── Custom colour picker popup ──────────────────────────────────
   Shared by cavalry-player and forge-dynamics-player.
   Opened/positioned via openPicker() + positionColorPicker() in each file. */
.am-color-picker {
  position: fixed;
  z-index: 9000;
  background: var(--surface-2, #111);
  border: 1px solid #2a2a2a;
  border-radius: var(--radius-8, 8px);
  padding: 12px;
  width: 208px;
  box-shadow: var(--shadow-modal, 0 8px 32px rgba(0,0,0,0.80));
  display: none;
  flex-direction: column;
  gap: 10px;
}
.am-color-picker.open { display: flex; }

/* SV (saturation–value) canvas area */
.am-cp-sv-wrap {
  position: relative;
  width: 100%;
  border-radius: 4px;
  overflow: hidden;
  cursor: crosshair;
}
.am-cp-sv-canvas {
  display: block;
  width: 100%;
  height: 140px;
  border-radius: 4px;
}
.am-cp-sv-cursor {
  position: absolute;
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
  transform: translate(-50%, -50%);
  pointer-events: none;
  top: 0; left: 0;
}

/* Hue rainbow slider */
.am-cp-hue {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 10px;
  border-radius: 5px;
  background: linear-gradient(to right,
    #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
  outline: none; cursor: pointer;
}
.am-cp-hue::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid rgba(0,0,0,0.3);
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}

/* Bottom row: preview circle + hex input */
.am-cp-bottom {
  display: flex;
  align-items: center;
  gap: 10px;
}
.am-cp-preview {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 1px solid #333;
  flex-shrink: 0;
}
.am-cp-hex {
  flex: 1;
  background: #1a1a1a;
  border: 1px solid #2a2a2a;
  border-radius: 4px;
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  padding: 5px 8px;
  outline: none;
  transition: border-color 0.15s;
}
.am-cp-hex:focus { border-color: #555; }

/* ── Loader ──────────────────────────────────────────────────────
   Canonical full-screen loading indicator: a single pulsing dot
   that cycles through the system rainbow, with an uppercase label
   underneath. Used by lab experiment players and the photo dump.
   HTML pattern:
     <div id="loader" class="am-loader">
       <div class="am-loader-dot"></div>
       <div class="am-loader-text">loading…</div>
     </div>
   Fade out when ready:
     document.getElementById('loader').classList.add('hidden');     */
.am-loader {
  position: fixed; inset: 0;
  z-index: 500;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  background: var(--bg);
  transition: opacity 0.4s ease;
}
.am-loader.hidden { opacity: 0; pointer-events: none; }
.am-loader-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #fff;
  animation: am-loader-pulse 1s ease-in-out infinite,
             am-loader-colors 4.5s linear infinite;
}
.am-loader-text {
  margin-top: 16px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
@keyframes am-loader-pulse {
  0%, 100% { opacity: 0.2; transform: scale(0.8); }
  50%      { opacity: 1;   transform: scale(1); }
}
@keyframes am-loader-colors {
  0%   { background: #ff3b30; }
  14%  { background: #ff9500; }
  28%  { background: #ffd60a; }
  42%  { background: #30d158; }
  56%  { background: #0af5ff; }
  70%  { background: #0a84ff; }
  84%  { background: #bf5af2; }
  100% { background: #ff3b30; }
}

/* ── Responsive ── */
@media (max-width: 900px) {
  .hero, .row { grid-template-columns: 1fr; }
  .hero-left, .row-left { border-right: none; border-bottom: 1px solid var(--border); }
  .img-grid-3 { grid-template-columns: 1fr 1fr; }
}

/* ── Mobile (≤1024px) — applies to all pages using shared CSS ── */
@media (max-width: 1024px) {

  /* ── Global horizontal margin token ── */
  :root { --mobile-px: 16px; --img-gap: 16px; } /* --img-gap: set to 0px to remove all image spacing */

  /* ── Hide custom cursor on touch ── */
  #cursor { display: none !important; }

  /* ── Header ── */
  header { padding-left: var(--mobile-px) !important; padding-right: var(--mobile-px) !important; min-height: 48px; }
  .am-header { min-height: 48px; }
  #header-pill  { display: none !important; }
  #am-menu-btn  { display: flex !important; }

  /* ── Footer ── On mobile the footer flows at the bottom of the document
     rather than being pinned. A fixed footer jumps around / bleeds when
     Chrome's address bar shows/hides; the inline position:fixed on the
     case-study footers needs !important to override. Cover both bare <footer>
     and the id="site-footer" variants. */
  footer,
  #site-footer,
  footer[style*="fixed"],
  #site-footer[style*="fixed"] {
    position: static !important;
    bottom: auto !important;
    left: auto !important;
    right: auto !important;
    z-index: auto !important;
  }


  /* ── Mobile/desktop visibility toggles ── */
  .hide-mobile { display: none !important; }
  .show-mobile-only { display: block !important; }

  /* ── Interleaved mobile sections (text woven between full-width images) ── */
  .mobile-section { border-bottom: 1px solid var(--border); }
  .mobile-section-title {
    /* 28px above (separates from previous full-bleed image) + 28px below
       (12px own padding + 16px paragraph top) — title centered in its space */
    padding: 28px var(--mobile-px) 12px !important;
    font-size: clamp(20px, 5vw, 28px);
  }
  .mobile-body-p {
    font-size: 14px; line-height: 1.5; color: var(--muted-2);
    padding: 16px var(--mobile-px);
    display: block;
  }
  .mobile-full-img { width: 100%; display: block; }
  .mobile-full-img-big { width: 100%; display: block; min-height: 60vw; object-fit: cover; }
  .mobile-2col { display: grid; grid-template-columns: 1fr 1fr; }
  .mobile-2col img { width: 100%; display: block; object-fit: cover; }

  /* ── Hero: hide number, stack layout ── */
  /* Drop the 200px desktop min-height on mobile — with the short meta content it
     would otherwise leave a large empty black void below Role/Tech. */
  .hero { grid-template-columns: 1fr; min-height: 0; }
  .hero-left { display: none; }
  .hero-right { padding: 20px var(--mobile-px) 8px; }
  /* Project name is in the header crumb, so hide the big hero title on mobile */
  .hero-title { display: none; }
  /* Hero meta: role + tech highlights side by side (tech moves up from intro row) */
  .hero-meta-row { display: grid !important; grid-template-columns: 1fr 1fr; gap: 0; margin-top: 4px; }
  .hero-meta-row > div:nth-child(2) { display: block !important; }
  .row-intro .row-left { display: none; }

  /* Cavalry hero experiment GIFs: rendered on black canvases, so a square one
     (the ring) balloons to full width on mobile and shows huge black margins.
     Cap the height and crop to the subject; the wide GIF is shorter than the
     cap so it's left at its natural size. Raise the cap if a subject clips. */
  .cav-exp-img { max-height: 65vw; object-fit: cover; object-position: center; }

  /* ── Rows ── */
  .row { grid-template-columns: 1fr; }
  .row-left  { border-right: none; border-bottom: 1px solid var(--border); padding: 16px var(--mobile-px) !important; }
  .row-right { padding: 16px var(--mobile-px) !important; }

  /* ── RULE: consistent gap between a section title and its first paragraph = 16px ──
     Section-header rows (.row-no-divider) drop the label's bottom padding so the
     only gap is the content's top padding (16px) — matching the interleaved
     .mobile-section-title pattern. */
  .row-no-divider .row-left { padding-bottom: 0 !important; }

  /* ── RULE: mobile typography ──
     Body text 15px (desktop is 13px — mobile reads closer/cramped so it goes up).
     Standard mobile body floor is 16px; 15px keeps it refined. Lists 14px (metadata). */
  .body-text { font-size: 14px; line-height: 1.5; }
  .role-list li, .sub-list li { font-size: 14px; line-height: 1.5; }
  .role-label, .sub-label { font-size: 13px; }

  /* ── Galleries ── */
  .gallery-wrap { padding: 0; }
  .gallery { grid-template-columns: 1fr !important; gap: 0 !important; }
  .gallery-item { height: auto !important; }
  .gallery-item img { width: 100% !important; height: auto !important; object-fit: cover; display: block; }
  .gif-item { height: auto !important; }
  .gif-item img { width: 100% !important; height: auto !important; max-height: none !important; display: block; }

  /* ── 3-col image grids → 1 col ── */
  .img-grid-3,
  [style*="repeat(3"] { grid-template-columns: 1fr !important; grid-template-rows: auto !important; gap: 0 !important; }

  /* ── 2-col grids → 1 col ── */
  [style*="1fr 1fr"],
  [style*="repeat(2"] { grid-template-columns: 1fr !important; grid-template-rows: auto !important; gap: 0 !important; }

  /* Utility: any side-by-side flex/grid block that should stack full-width on mobile.
     Drops the desktop padding/gap so stacked images sit edge to edge (then the
     --img-gap rule adds the consistent 16px between them). */
  .mobile-stack { display: block !important; padding: 0 !important; gap: 0 !important; }
  .mobile-stack > div { flex: none !important; width: 100% !important; }

  /* Utility: drop a block's top/bottom divider lines on mobile (e.g. stacked image
     grids whose borders would otherwise double up between sections). Desktop keeps them. */
  .mobile-no-border { border-top: none !important; border-bottom: none !important; }

  /* ── RULE: images full-bleed AND flush on mobile — no padding at all,
     so stacked images sit edge to edge with no gaps between them ── */
  [style*="background:#000"], [style*="background: #000"] { padding: 0 !important; }
  /* Opt-in: add vertical spacing between stacked images (overrides flush default) */
  div.mobile-spaced { padding: 16px 0 !important; }

  /* ── RULE: 16px column spacing between ALL media, every case study ──
     Single source of truth for image/video spacing across the portfolio.
     Every piece of media + every body paragraph gets a consistent gap below
     it; margin-top is 0 so adjacent margins collapse to ONE gap, making the
     spacing identical between image↔image, image↔video, image↔paragraph, etc.
     Controlled entirely by --img-gap — set it to 0px to make everything flush
     again everywhere at once. Covers <img> AND <video>, standalone media,
     grid cells, and gallery items. */
  .mobile-full-img,
  .gallery-item img, .gif-item img,
  [style*="background:#000"] img, [style*="background:#000"] video,
  [style*="repeat(3"] img, [style*="repeat(3"] video,
  [style*="repeat(2"] img, [style*="repeat(2"] video,
  [style*="1fr 1fr"] img, [style*="1fr 1fr"] video {
    display: block;
    width: 100%;
    margin-top: 0 !important;
    margin-bottom: var(--img-gap) !important;
  }
  .mobile-body-p {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    margin-top: 0 !important;
    margin-bottom: var(--img-gap) !important;
  }

  /* ── Proj-nav: shorter on mobile (110px desktop is too tall) ── */
  .proj-nav { padding: 0 var(--mobile-px); height: 72px; }
  /* Tighten the gap directly above the previous/next project nav on mobile.
     The nav is vertically centred in a fixed height, so its top and bottom
     halves are equal — but the block before it adds its own bottom border,
     padding, margin and a trailing image gap on top of that, making the space
     ABOVE the nav text noticeably larger than the space below it. Strip all of
     that preceding bottom spacing so the nav's own centred half is the only gap
     above, matching the gap below before the footer. */
  *:has(+ .proj-nav) { border-bottom: none !important; padding-bottom: 0 !important; margin-bottom: 0 !important; }
  *:has(+ .proj-nav) img, *:has(+ .proj-nav) video { margin-bottom: 0 !important; }

  /* ── Footer ── */
  footer .footer-copy,
  .footer-copy { padding: 14px var(--mobile-px) !important; }
  #footer-clock { display: none !important; }

  /* On mobile, let the footer flow at the bottom of the document instead of
     being fixed. A fixed bottom:0 footer repaints a beat behind Chrome's
     address-bar show/hide, which makes it jump and briefly reveal the page
     underneath. In-flow footers can't do that. (#site-footer is unique to the
     case-study pages; the experiment players use .footer-copy and are left as-is.) */
  #site-footer {
    position: static !important;
    left: auto !important; right: auto !important; bottom: auto !important;
  }

  /* ── Page header (work, lab) ── */
  .page-header { padding: 20px var(--mobile-px) !important; }

  /* ── Spacer for fixed footer ── */
  .footer-spacer { display: block; }
}
