/* ============================================================================
   Joe Fitzhugh Design Studio
   One stylesheet, hand-written, no framework.

   1.  Theme tokens + palette themes
   2.  Reset
   3.  Type scale
   4.  Header
   5.  Hero
   6.  Curved carousel
   7.  Work grid
   8.  Prose / interior pages
   9.  Footer
   10. Palette switcher
   11. Project sheet (modal)
   12. Motion
   13. Responsive
   ========================================================================== */

/* -- 1. THEME TOKENS ------------------------------------------------------- */
/*
   --paper      page background
   --ink        body text on --paper
   --quiet      muted type: the giant subtitle, captions, secondary rules
   --accent     the one colour that means something; used sparingly
   --sheet      surface of cards and the project modal, always slightly above paper

   The palette switcher rewrites --paper / --quiet / --accent on <html>, so every
   component reads through these four and nothing hardcodes a colour.
*/
:root {
  --paper:  #ffffff;
  --ink:    #363636;
  --quiet:  #d2d2d2;      /* rules, fills, frames — never words */
  --quiet-text: #767676;  /* the same recessive grey, dark enough to read (4.5:1 on paper) */
  --accent: #d6401f;
  --sheet:  #ffffff;
  --shadow: 18, 18, 18;

  /* type scale — 1.25 (major third) off a 17px body */
  --t-micro: 0.647rem;   /* 11px  */
  --t-small: 0.812rem;   /* 13.8  */
  --t-body:  1.0625rem;  /* 17    */
  --t-lead:  1.328rem;   /* 21.25 */
  --t-sub:   1.66rem;    /* 26.6  */
  --t-head:  2.074rem;   /* 33.2  */

  /* display sizes are fluid, not on the scale — they are pictures, not text */
  --t-name:  clamp(2.75rem, 9.4vw, 9.5rem);
  --t-claim: clamp(1.9rem, 5.6vw, 5.4rem);
  --t-huge:  clamp(3.5rem, 15.5vw, 16rem);

  /* spacing scale — 4px base */
  --s1: 0.25rem; --s2: 0.5rem;  --s3: 0.75rem; --s4: 1rem;
  --s5: 1.5rem;  --s6: 2rem;    --s7: 3rem;    --s8: 4rem;
  --s9: 6rem;    --s10: 8rem;   --s11: 12rem;

  --radius:  1rem;
  --radius-lg: 2rem;
  --shell: 90rem;
  --ease: cubic-bezier(.22, .68, .28, 1);
  --ease-out-back: cubic-bezier(.34, 1.4, .5, 1);
  --ease-elastic:  cubic-bezier(.16, 1.36, .36, 1);   /* his card settle */
}

/* Palette themes. Each sets paper/ink/quiet/accent as a set so contrast holds.
   data-theme is written to <html> by the switcher and remembered per visitor. */
:root[data-theme="bone"]   { --paper:#EDE6D3; --ink:#2A2620; --quiet:#BCB29A; --quiet-text:#6E6449; --accent:#C0561C; --sheet:#F6F1E4; }
:root[data-theme="navy"]   { --paper:#0A1435; --ink:#EDF1FF; --quiet:#3D4C7A; --quiet-text:#9AAAD8; --accent:#FF5A3C; --sheet:#111E48; --shadow: 0,0,0; }
:root[data-theme="pine"]   { --paper:#22301F; --ink:#EFF3E9; --quiet:#4C6047; --quiet-text:#A8BA9E; --accent:#E8B84B; --sheet:#2B3C27; --shadow: 0,0,0; }
:root[data-theme="violet"] { --paper:#2A0A3A; --ink:#F6EBFF; --quiet:#5C3670; --quiet-text:#C4A5D4; --accent:#F0A5FF; --sheet:#37124A; --shadow: 0,0,0; }

/* -- 2. RESET -------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  background: var(--paper);
  transition: background-color .45s var(--ease);
  -webkit-text-size-adjust: 100%;
}
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color .45s var(--ease), color .45s var(--ease);
}
img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }

/* One focus treatment for the whole site. Never removed, always visible on
   both light and dark themes because it uses the accent, not a browser blue. */
:focus-visible {
  outline: 2.5px solid var(--accent);
  outline-offset: 4px;
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

.skip {
  position: absolute; left: var(--s4); top: var(--s4); z-index: 300;
  padding: var(--s3) var(--s5); background: var(--ink); color: var(--paper);
  border-radius: 999px; font-size: var(--t-small); font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* -- 3. TYPE --------------------------------------------------------------- */
/* Display face.
   His is Futura Now Headline Cn XBd, a licensed Monotype cut. This is Futura PT
   Condensed, served from Joe's Adobe Fonts subscription — a different
   digitisation of the same design, and condensed, which the free stand-in it
   replaces could not be. Every ratio below is measured against it.

   Adobe serves these from their CDN and stops if the subscription lapses. The
   stack then falls to a locally installed Futura, then Century Gothic on
   Windows, then whatever system-ui is: the page keeps its shape either way,
   but it stops being Futura. */
:root {
  --font-display: "futura-pt-condensed", "Futura", "Century Gothic", system-ui, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
}
.display, h1, h2 {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 0.9;
  text-transform: uppercase;
  text-wrap: balance;
}
h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
}
.eyebrow {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
}
.quiet { color: var(--quiet-text); }
.accent { color: var(--accent); }

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--s5); }
.measure { max-width: 68ch; }

/* -- 4. HEADER ------------------------------------------------------------- */
/* One fixed 48px disc, top right. No wordmark, no nav bar — the hero already
   carries the identity and the footer carries the navigation. */
/* The only way into the site's one interior page — the portrait, as his is.
   The artwork is already a circle on its own alpha, so nothing here masks it;
   the radius is only a guard against a stray edge pixel. */
.header { position: fixed; top: var(--s4); right: var(--s5); z-index: 90; }
.header__me {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  transition: transform .2s var(--ease);
}
.header__me__img {
  width: 100%; height: 100%;
  border-radius: 50%;
  filter: drop-shadow(0 6px 14px rgba(var(--shadow), .3));
}
.header__me:hover { transform: translateY(-2px) scale(1.09); }
.header__me:active { transform: translateY(-1px) scale(1.02); }

.header__nav { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s2); }

.pill {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 40px; padding: var(--s2) var(--s5);
  border-radius: 999px;
  background: color-mix(in srgb, var(--quiet) 34%, transparent);
  font-size: var(--t-micro); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  transition: background-color .2s var(--ease), transform .2s var(--ease), color .2s var(--ease);
}
.pill:hover { background: color-mix(in srgb, var(--quiet) 62%, transparent); transform: translateY(-2px); }
.pill[aria-current="page"] { background: var(--ink); color: var(--paper); }
.pill--accent { background: var(--accent); color: #fff; }
.pill--accent:hover { background: var(--accent); filter: brightness(1.08); }

/* -- 5. HERO --------------------------------------------------------------- */
.hero {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--s6);
  padding: var(--s8) var(--s5) var(--s7);
  text-align: center;
}
.hero__meta { display: grid; gap: 2px; }
.hero__meta strong { font-size: var(--t-small); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; }
.hero__meta a { font-size: var(--t-small); letter-spacing: .1em; color: var(--quiet-text); text-transform: uppercase; }
.hero__meta a:hover { color: var(--ink); }

/* The wordmark is the name — it already contains the studio name, so no h1 text
   sits beside it. The accessible name lives in alt + a visually hidden h1. */
/* His name spans roughly 40% of the viewport. The lockup carries "design
   studio" as well, so it sits a little wider, but nowhere near full bleed. */
.hero__wordmark { width: min(84vw, 45rem); height: auto; }
.hero__wordmark--cream { display: none; }
:root[data-theme="navy"] .hero__wordmark--ink,
:root[data-theme="pine"] .hero__wordmark--ink,
:root[data-theme="violet"] .hero__wordmark--ink { display: none; }
:root[data-theme="navy"] .hero__wordmark--cream,
:root[data-theme="pine"] .hero__wordmark--cream,
:root[data-theme="violet"] .hero__wordmark--cream { display: block; }

/* fanned card stack.
   His cards are grabbable: JS writes --offsetX/--offsetY as you drag one, and
   --velocity feeds the rotation so a card tilts into the throw and springs
   home on an elastic ease. Rest angles and offsets below are his. */
.fan {
  display: flex; align-items: center; justify-content: center;
  padding-block: var(--s5);
  position: relative;
}
.fan__card {
  aspect-ratio: 1;
  width: clamp(78px, 14vw, 202px);
  border-radius: 16px;
  display: grid;
  touch-action: none;
}
.fan__card:not(:last-child) { margin-right: -6%; }
.fan__card img {
  grid-area: 1/1;
  width: 100%; height: 100%; object-fit: cover;
  border-radius: inherit;
  background: var(--sheet);
  box-shadow: 0 22px 46px -20px rgba(var(--shadow), .40);
  cursor: grab;
  -webkit-user-drag: none; user-select: none;
  translate: calc(var(--offsetX, 0) * 1px) calc(var(--offsetY, 0) * 1px + var(--translateY));
  rotate: calc(var(--rest) - var(--velocity, 0) * .25deg);
  transition: scale .25s var(--ease);
}
.fan__card img:active { cursor: grabbing; }
.fan__card img:hover { scale: 1.06; }
.fan__card:nth-child(1) img { --rest:  2deg; --translateY:  5%; }
.fan__card:nth-child(2) img { --rest: -3deg; --translateY: -6%; }
.fan__card:nth-child(3) img { --rest:  6deg; --translateY:  5%; }
.fan__card:nth-child(4) img { --rest: -2deg; --translateY: -4%; }

.hero__claim {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--t-claim);
  line-height: .9;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-wrap: balance;
  color: var(--quiet-text);
  max-width: 21ch;
}
.hero__clients { display: grid; gap: var(--s2); }
.hero__clients dt { font-size: var(--t-micro); font-weight: 700; letter-spacing: .22em; text-transform: uppercase; }
.hero__clients dd {
  font-size: var(--t-small); letter-spacing: .12em; text-transform: uppercase;
  color: var(--quiet-text); max-width: 46rem;
}

/* -- 6. CURVED CAROUSEL ---------------------------------------------------- */
/*
   The one structural move. Slides sit on the rim of a very large wheel: the
   pivot is pushed far below the viewport with transform-origin, so a small
   rotation per slide traces a wide, shallow arc across the screen.

   JS writes --rot, --lift and --fade per slide from its distance to centre, so
   there is no dependency on CSS cos() and prefers-reduced-motion can flatten
   the whole thing by ignoring them.
*/
.reel {
  position: relative;
  padding-block: var(--s5) var(--s5);
  overflow: clip;
  cursor: grab;
  touch-action: pan-y;
  -webkit-user-select: none; user-select: none;
}
.reel:active { cursor: grabbing; }
.reel__track {
  display: flex; align-items: center;
  gap: 1rem;                       /* his measured gap, to the pixel */
  width: max-content;
  /* No centring pad. The row is wrapped into one set width, so the slide that
     sits in the middle is centred by the scroll offset instead — a left pad
     would put empty space on that side until the first drag. */
  will-change: transform;
}
.reel__slide {
  position: relative;                /* so a hovered slide can sit over its neighbours */
  display: flex; flex-direction: column; align-items: center; gap: var(--s4);
  width: min(30rem, 74vw);
  transform-origin: 50% 70vw;
  rotate: var(--rot, 0deg);
  translate: 0 var(--lift, 0px);
}
/* The reel carries the six client marks, and those are square — as his carousel
   slides are. So the frame is square too. (It used to be a fixed-height box the
   artwork sized itself inside; with square art that box loses its height to
   max-width and the image overflows its own slide.) */
.reel__frame {
  width: 100%;
  aspect-ratio: 1;
  display: grid; place-items: center;
}
.reel__frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: var(--radius);
  box-shadow: 0 30px 70px -34px rgba(var(--shadow), .45);
  -webkit-user-drag: none;
  /* the lift rides on the image, not the slide: JS rewrites the slide's rotate
     and translate every frame to hold it on the arc, and would overwrite it */
  transition: scale .55s var(--ease-elastic), translate .55s var(--ease-elastic),
              box-shadow .45s var(--ease);
}
@media (any-hover: hover) {
  .reel__slide:hover { z-index: 2; }
  .reel__slide:hover .reel__frame img {
    scale: 1.06; translate: 0 -14px;
    box-shadow: 0 52px 96px -34px rgba(var(--shadow), .55);
  }
}
.reel__slide:active .reel__frame img { scale: .99; translate: 0 -3px; transition-duration: .12s; }
.reel__label { opacity: var(--fade, 1); transition: opacity .2s linear; }
.reel__hint {
  display: block; text-align: center; color: var(--quiet-text);
  font-size: var(--t-micro); font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase;
}

/* -- 7. WORK GRID ---------------------------------------------------------- */
.band { padding-block: var(--s9); }
.band__head { text-align: center; display: grid; gap: var(--s3); justify-items: center; margin-bottom: var(--s8); }
/* His section titles sit around 60-70px, not full bleed — only the footer
   headline runs edge to edge. */
.band__head h2 { font-size: clamp(1.9rem, 4vw, 3.4rem); }
.band__head p { max-width: 24em; }
.band__head p { color: var(--quiet-text); font-size: var(--t-lead); }

/* Measured off his grid: two columns under 768px, three above, and a gutter
   that opens to 8rem — the cards are small and the air between them is the
   point. The card itself is never cropped to a cell; it is a square mark and
   the cell is square, so nothing is lost. */
.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: min(10vw, 5rem);
  width: 100%; max-width: 1200px;
  margin-inline: auto;
  padding-inline: var(--s5);
}
@media (min-width: 48rem) {
  .grid { grid-template-columns: repeat(3, 1fr); gap: min(10vw, 8rem); padding-inline: var(--s8); }
}

/* His shadow is three stacked layers, all very light: a tight contact shadow,
   a wide soft one, and a long low cast. One box-shadow can't do that falloff. */
.project {
  display: grid; place-items: center; width: 100%;
  --card-shadow:
    0 9px 21px rgba(var(--shadow), .05),
    0 38px 38px rgba(var(--shadow), .045),
    0 85px 51px rgba(var(--shadow), .025);
}
.project__image {
  grid-area: 1 / 1;
  position: relative;
  width: 100%;
  border-radius: var(--radius);
  /* the lift lives here rather than on the art, so the shadow travels with it */
  transition: scale .55s var(--ease-elastic), translate .55s var(--ease-elastic);
}
.project__shadow {
  position: absolute; inset: 0;
  border-radius: inherit;
  background: rgba(var(--shadow), .05);
  box-shadow: var(--card-shadow);
  transition: opacity .8s var(--ease-elastic), box-shadow .45s var(--ease);
}
.project__media {
  position: relative;
  display: block;
  border-radius: inherit;
  line-height: 0;
  transition: scale .8s var(--ease-elastic);
}
.project__media img {
  width: 100%; height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: inherit;
}
/* Cards arrive by springing up to size as the row comes into view. The shared
   .rise fade-and-lift is cancelled here — his cards scale, they don't slide. */
.project.rise { opacity: 1; transform: none; }
.project.rise .project__image { transition: none; }
.project.rise .project__media { scale: .7; }
.project.rise .project__shadow { opacity: 0; }
.project.rise.in .project__image { transition: scale .55s var(--ease-elastic), translate .55s var(--ease-elastic); }
.project.rise.in .project__media { scale: 1; }
.project.rise.in .project__shadow { opacity: 1; }

/* Hover picks the card up: it rises, grows, and the cast shadow lengthens and
   softens underneath as if it had moved away from the page. His is a flat 1.01
   with no lift, which reads as nothing at this card size. */
@media (any-hover: hover) {
  .project:hover .project__image { scale: 1.06; translate: 0 -14px; }
  .project:hover .project__shadow {
    box-shadow:
      0 14px 26px rgba(var(--shadow), .07),
      0 46px 48px rgba(var(--shadow), .06),
      0 100px 64px rgba(var(--shadow), .035);
  }
}
.project:active .project__image { scale: .99; translate: 0 -3px; transition-duration: .12s; }
.project:focus-visible { outline: none; }
.project:focus-visible .project__image { outline: 3px solid var(--accent); outline-offset: 10px; border-radius: var(--radius); }

/* -- 8. PROSE / INTERIOR --------------------------------------------------- */
.prose { display: grid; gap: var(--s5); }
.prose p { max-width: 68ch; }
.prose p + p { margin-top: 0; }
.prose h3 { font-size: var(--t-sub); }
.prose a:not(.pill) { text-decoration: underline; text-underline-offset: .18em; text-decoration-thickness: 1.5px; }
.prose a:not(.pill):hover { color: var(--accent); }

.split { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--s8); align-items: start; }

.rule { border: 0; border-top: 1px solid color-mix(in srgb, var(--quiet) 60%, transparent); margin-block: var(--s7); }

.facts { display: grid; gap: 0; }
.facts div {
  display: grid; grid-template-columns: 1fr auto; gap: var(--s4);
  padding-block: var(--s3);
  border-bottom: 1px solid color-mix(in srgb, var(--quiet) 55%, transparent);
  font-size: var(--t-small);
}
.facts dt { color: var(--quiet-text); letter-spacing: .06em; text-transform: uppercase; font-size: var(--t-micro); font-weight: 700; }
.facts dd { font-weight: 600; text-align: right; }

.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5); }
.card {
  padding: var(--s6);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--quiet) 18%, transparent);
  display: grid; gap: var(--s3); align-content: start;
}
.card h3 { font-size: var(--t-sub); }
.card p { font-size: var(--t-small); color: color-mix(in srgb, var(--ink) 78%, var(--paper)); }
.card__n { font-family: var(--font-display); font-weight: 800; font-size: var(--t-head); color: var(--accent); line-height: 1; }

/* forms */
.field { display: grid; gap: var(--s2); margin-bottom: var(--s5); }
.field label { font-size: var(--t-micro); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.field input, .field textarea, .field select {
  font: inherit; font-size: var(--t-body);
  padding: var(--s3) var(--s4);
  border-radius: var(--radius);
  border: 1.5px solid color-mix(in srgb, var(--quiet) 80%, transparent);
  background: var(--sheet); color: var(--ink);
  transition: border-color .2s var(--ease);
}
.field input:hover, .field textarea:hover, .field select:hover { border-color: var(--quiet); }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--accent); }
.field textarea { min-height: 9rem; resize: vertical; }
.field__err { font-size: var(--t-small); color: var(--accent); font-weight: 600; }
.field[data-invalid] input, .field[data-invalid] textarea { border-color: var(--accent); }


/* -- 8b. PRICING ----------------------------------------------------------- */
.offer {
  margin-top: var(--s4); padding: var(--s3) var(--s5);
  border-radius: 999px; background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent); font-size: var(--t-small); font-weight: 700;
  letter-spacing: .06em;
}
.tiers { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s5); align-items: start; }
.tier {
  display: grid; gap: var(--s3); align-content: start;
  padding: var(--s6);
  border-radius: var(--radius);
  border: 1.5px solid color-mix(in srgb, var(--quiet) 70%, transparent);
  background: var(--sheet);
}
.tier--pop { border-color: var(--accent); border-width: 2px; }
.tier h3 { font-size: var(--t-sub); }
.tier__price { font-family: var(--font-display); font-weight: 800; font-size: var(--t-head); line-height: 1; }
.tier__term { font-size: var(--t-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--quiet-text); }
.tier__list { display: grid; gap: var(--s2); margin-block: var(--s3); font-size: var(--t-small); }
.tier__list li { padding-left: var(--s5); position: relative; line-height: 1.45; }
.tier__list li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 8px; height: 8px; border-radius: 2px; background: var(--accent);
}
.tier .pill { justify-self: start; margin-top: var(--s2); }

.notebox {
  margin-top: var(--s7); padding: var(--s6);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--quiet) 20%, transparent);
  display: grid; gap: var(--s4); font-size: var(--t-small); line-height: 1.6;
}

.rate { width: 100%; border-collapse: collapse; font-size: var(--t-small); min-width: 42rem; }
.rate th, .rate td { text-align: left; padding: var(--s3) var(--s4); vertical-align: top; }
.rate thead th {
  font-size: var(--t-micro); letter-spacing: .16em; text-transform: uppercase;
  color: var(--quiet-text); border-bottom: 1.5px solid color-mix(in srgb, var(--quiet) 80%, transparent);
}
.rate tbody tr { border-bottom: 1px solid color-mix(in srgb, var(--quiet) 50%, transparent); }
.rate tbody th { font-weight: 700; width: 22%; }
.rate td:nth-child(2) { color: color-mix(in srgb, var(--ink) 78%, var(--paper)); }
.rate__price { white-space: nowrap; font-weight: 700; text-align: right !important; }

.builder { align-items: start; }
.optset { border: 0; display: grid; gap: var(--s2); margin-bottom: var(--s6); }
.optset legend { margin-bottom: var(--s3); }
.opt {
  display: flex; gap: var(--s3); align-items: flex-start;
  padding: var(--s3) var(--s4);
  border-radius: var(--radius);
  border: 1.5px solid color-mix(in srgb, var(--quiet) 60%, transparent);
  cursor: pointer;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.opt:hover { border-color: var(--quiet); background: color-mix(in srgb, var(--quiet) 14%, transparent); }
.opt:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.opt:has(input:focus-visible) { outline: 2.5px solid var(--accent); outline-offset: 3px; }
.opt input { margin-top: .3em; accent-color: var(--accent); width: 18px; height: 18px; flex: none; }
.opt span { display: grid; gap: 2px; }
.opt b { font-size: var(--t-small); }
.opt em { font-style: normal; font-size: var(--t-micro); color: var(--quiet-text); letter-spacing: .02em; }

.summary {
  position: sticky; top: var(--s5);
  padding: var(--s6); border-radius: var(--radius);
  background: color-mix(in srgb, var(--quiet) 20%, transparent);
  display: grid; gap: var(--s3); align-content: start;
}
.summary__count { font-family: var(--font-display); font-weight: 800; font-size: var(--t-sub); }
.summary__list { display: grid; gap: var(--s2); font-size: var(--t-small); }
.summary__list li { padding-left: var(--s4); position: relative; }
.summary__list li:not(.quiet)::before { content: "\2014"; position: absolute; left: 0; color: var(--accent); }
.summary .pill { justify-self: start; }

@media (max-width: 62rem) {
  .tiers { grid-template-columns: repeat(2, 1fr); }
  .summary { position: static; }
}
@media (max-width: 40rem) {
  .tiers { grid-template-columns: 1fr; }
}


/* -- 8c. ABOUT ------------------------------------------------------------- */
/* Narrow centred column, everything in display caps: the first paragraph in ink,
   the rest dropping back to the recessive grey. */
/* overflow-x: clip contains the project pops, which are absolutely positioned
   well outside the 42rem reading column and would otherwise widen the page. */
/*
   Sized off his about page. Two steps on his scale carry the whole thing:
   h2 (the "About" title, the bio paragraphs, the News and Projects headings)
   and h1 (the project names). Both run at line-height .82-.9, which is what
   makes his blocks read as slabs rather than as paragraphs.
*/
:root {
  --t-a-h1: clamp(4.125rem, 8.6vw, 6.25rem);    /* his --font-h1, exactly */
  --t-a-h2: clamp(2.5rem, 5.2vw, 4rem);         /* his --font-h2, exactly */
  --news-max: 860px;                            /* his --max-width */
}
/* overflow-x: clip contains the project pops, which are absolutely positioned
   well outside the reading column and would otherwise widen the page. */
.about { display: flex; flex-direction: column; align-items: center; gap: 6rem; padding-block: 5rem; overflow-x: clip; }
.about__block { display: flex; flex-direction: column; align-items: center; gap: 3rem; width: 100%; text-align: center; }

/* the bio: title and paragraphs are one size, his gap is .82em */
.about__block--bio { gap: .82em; }
.about__block--bio h1,
.about__bio p {
  font-family: var(--font-display); font-weight: 800; text-transform: uppercase;
  font-size: var(--t-a-h2); line-height: .82; letter-spacing: -.02em;
  max-width: 10em;   /* his measure, exactly */
}
.about__bio { display: flex; flex-direction: column; align-items: center; gap: .8em; }

/* Every paragraph sits back at a quarter strength; the one being read comes
   forward. At the top of the page that is the first one, and it steps down as
   you scroll — the block reads itself. */
.about__bio p { opacity: .25; transition: opacity .4s var(--ease); }
.about__bio p.lit { opacity: 1; }

.about__block h2 { font-size: var(--t-a-h2); line-height: .82; letter-spacing: -.02em; margin-bottom: .12em; }

/* news: his two-up grid of 1fr/2fr cards, and his big card type */
.newsgrid { display: grid; grid-template-columns: 1fr; gap: 1rem; width: 100%; max-width: var(--news-max); }
@media (min-width: 41.25rem) { .newsgrid { grid-template-columns: repeat(2, 1fr); } }
.newscard {
  display: grid;
  /* minmax(0,…) or the body track's min-content — long URLs set at 28px —
     overruns its 2fr share and squeezes the thumb down to nothing. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 1rem;
  align-items: start;
  border-radius: 1rem; padding: .5rem;
  text-align: left; position: relative;
  transition: scale .8s var(--ease-elastic), rotate .8s var(--ease-elastic);
}
.newscard:hover { rotate: var(--card-rot, 1deg); scale: 1.05; z-index: 1; }
.newscard:active { rotate: 0deg; scale: .98; }
.newscard__thumb { display: block; width: 100%; aspect-ratio: 1; border-radius: .5rem; overflow: hidden; }
.newscard__thumb img { width: 100%; height: 100%; object-fit: cover; }
.newscard__body {
  display: flex; flex-direction: column; justify-content: space-between;
  height: 100%; padding: .4rem .4rem .7rem 0;
}
.newscard__kind, .newscard__title {
  font-family: var(--font-display); font-weight: 800;
  font-size: 1.75rem; line-height: .85; letter-spacing: -.04em;
  text-transform: uppercase;
}
.newscard__kind { opacity: .6; }
/* His card titles are short words; two of mine are long URLs. <wbr> after each
   dot in the markup gives the line breaker somewhere sensible to go, so they
   split at "careers." rather than mid-word. */
.newscard__title { overflow-wrap: break-word; }

/* projects: his big list, a quarter strength until you reach for one */
.about__block--projects { gap: 3rem; }
.projlist { display: flex; flex-direction: column; align-items: center; width: 100%; }
.projlist a {
  display: inline-block;
  font-family: var(--font-display); font-weight: 800; text-transform: uppercase;
  font-size: var(--t-a-h1); line-height: .9; letter-spacing: -.02em;
  opacity: .25;
  transform-origin: center;
  transition: opacity .15s var(--ease), scale .8s var(--ease-elastic);
}
.projlist a:hover, .projlist a:focus-visible { opacity: 1; scale: 1 1.1; }

/* Hovering a project name throws a few pieces of its work out around it. */
.projlist li { position: relative; display: grid; justify-items: center; }
.projlist .pop {
  position: absolute; top: 50%; left: 50%;
  width: clamp(110px, 13vw, 190px); aspect-ratio: 1;
  margin: calc(clamp(110px, 13vw, 190px) / -2);
  border-radius: 1rem; overflow: hidden;
  box-shadow: 0 18px 40px -16px rgba(var(--shadow), .45);
  pointer-events: none;
  opacity: 0; scale: .4;
  translate: var(--px, 0) var(--py, 0);
  rotate: var(--pr, 0deg);
  transition: opacity .3s var(--ease), scale .5s var(--ease-out-back);
  z-index: 2;
}
.projlist .pop img { width: 100%; height: 100%; object-fit: cover; }
.projlist li:hover .pop,
.projlist li:focus-within .pop { opacity: 1; scale: 1; }
.projlist li:hover .pop:nth-of-type(2),
.projlist li:focus-within .pop:nth-of-type(2) { transition-delay: .05s; }
.projlist li:hover .pop:nth-of-type(3),
.projlist li:focus-within .pop:nth-of-type(3) { transition-delay: .1s; }
@media (max-width: 62rem) { .projlist .pop { display: none; } }

/* footer navigation — the nav bar moved here when the header became a single disc */

@media (max-width: 40rem) {
  .about { gap: var(--s8); }
}

/* -- 9. FOOTER ------------------------------------------------------------- */
/*
   His footer is a fixed, full-height panel that the page slides off to reveal,
   not a band at the end of the document. The phantom above it is what reserves
   that height in the flow; the footer itself never scrolls, so the last screen
   of the site is uncovered rather than scrolled to.

   main has to be opaque and above it, or the panel shows through the page.
*/
.footer__reveal { min-height: 100dvh; }
.footer {
  position: fixed; left: 0; bottom: 0; z-index: 0;
  width: 100%; min-height: 100dvh;
  container-type: inline-size;          /* so the headline can size off its own width */
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-end;
  gap: var(--s6);
  padding: var(--s8) 0;                 /* no side padding: the headline runs to the edges */
  text-align: center;
  background: color-mix(in srgb, var(--quiet) 85%, transparent);
}
/* Sized off the footer's own width, so CONTACT runs edge to edge at every
   viewport instead of stopping short on wide screens. His ratio is 33cqi
   against Futura Now Headline Condensed. On Futura PT Condensed his 33 lands
   at .997 of the viewport — near enough to prove the faces match, but his
   -.05em optical shift then clips 10px off the C, so this trims to 32.4.
   Against the free stand-in it took 21.37 to fill the same width. */
.footer__huge {
  font-size: 32.4cqi;
  line-height: .8;
  letter-spacing: -.04em;
  margin-left: -.05em;
  color: var(--paper);
  pointer-events: none; -webkit-user-select: none; user-select: none;
  transform: scaleY(var(--stretch, 1));
  transform-origin: bottom;
}
.footer__huge span { display: block; position: relative; top: -.1em; }

.footer__links { padding-inline: var(--s5); display: flex; flex-direction: column; align-items: center; gap: var(--s4); }
.footer__list { display: flex; flex-direction: column; align-items: center; gap: .2rem; }
.footer__list a {
  display: block;
  font-size: var(--t-small); font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  transform-origin: bottom;
  transition: color .15s var(--ease), transform .8s var(--ease-elastic);
}
.footer__list a:hover { color: var(--paper); transform: scaleY(1.2); }
/* His copyright line is ghosted into the ground like the headline. The headline
   can carry that — it is 290px of decoration and duplicates nothing. This line
   is information, so it stays on the readable side of the same idea. */
.footer__fine {
  padding-inline: var(--s5);
  font-size: var(--t-micro); letter-spacing: .18em; text-transform: uppercase;
  color: color-mix(in srgb, var(--ink) 80%, transparent);
}

/* main rides over the fixed panel, and has to fill the screen even on a short
   page (404, a two-plate project) or the panel shows below the fold on load. */
main { position: relative; z-index: 1; background: var(--paper); min-height: 100dvh; }

/* -- 10. PALETTE SWITCHER -------------------------------------------------- */
.palette { position: fixed; right: var(--s5); bottom: var(--s5); z-index: 120; display: flex; flex-direction: column-reverse; align-items: center; gap: var(--s3); }
.palette__toggle {
  width: 52px; height: 52px; border-radius: 999px;
  display: grid; place-items: center;
  background: var(--sheet); color: var(--ink);
  box-shadow: 0 10px 30px -8px rgba(var(--shadow), .38);
  border: 1.5px solid color-mix(in srgb, var(--quiet) 60%, transparent);
  transition: transform .2s var(--ease);
}
.palette__toggle:hover { transform: translateY(-2px) scale(1.04); }
.palette__toggle svg { width: 24px; height: 24px; }
.palette__list {
  display: grid; gap: var(--s2);
  padding: 0; margin: 0; border: 0;
}
.palette__list[hidden] { display: none; }
.palette__swatch {
  width: 40px; height: 40px; border-radius: 999px;
  border: 2px solid color-mix(in srgb, var(--quiet) 70%, transparent);
  box-shadow: 0 6px 18px -6px rgba(var(--shadow), .4);
  transition: transform .2s var(--ease-out-back), border-color .2s var(--ease);
  animation: swatch-in .32s var(--ease-out-back) backwards;
}
.palette__swatch:hover { transform: scale(1.12); }
.palette__swatch[aria-pressed="true"] { border-color: var(--ink); transform: scale(1.1); }
@keyframes swatch-in { from { opacity: 0; transform: translateY(10px) scale(.7); } }

/* -- 11. PROJECT SHEET (modal) --------------------------------------------- */
/*
   Project pages are real URLs. From the index, JS fetches one and paints it into
   this sheet, pushing history so back closes it. Without JS the link is an
   ordinary navigation to the same page, which renders standalone.
*/
.sheet-scrim {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(var(--shadow), .55);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  padding: var(--s4);
  display: grid;
  animation: scrim-in .3s var(--ease);
}
.sheet-scrim[hidden] { display: none; }
@keyframes scrim-in { from { opacity: 0; } }

.sheet {
  position: relative;
  background: var(--sheet); color: var(--ink);
  border-radius: var(--radius-lg);
  overflow: hidden auto;
  overscroll-behavior: contain;
  animation: sheet-in .42s var(--ease-out-back);
}
@keyframes sheet-in { from { opacity: 0; transform: translateY(3%) scale(.985); } }

.sheet__close {
  position: sticky; top: var(--s5); z-index: 5;
  margin-inline-start: auto; margin-inline-end: var(--s5);
  width: 52px; height: 52px; border-radius: 999px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--quiet) 40%, var(--sheet));
  box-shadow: 0 8px 24px -10px rgba(var(--shadow), .4);
  transition: transform .2s var(--ease), background-color .2s var(--ease);
}
.sheet__close:hover { transform: scale(1.07); background: color-mix(in srgb, var(--quiet) 72%, var(--sheet)); }
.sheet__close svg { width: 22px; height: 22px; }

.sheet__body { padding: 0 clamp(1rem, 5vw, 5rem) clamp(3rem, 7vw, 6rem); }

/* a project's own layout — used identically inside the sheet and standalone */
.proj__head { text-align: center; display: grid; gap: var(--s4); justify-items: center; padding-block: var(--s6) var(--s8); }
.proj__head h1 { font-size: var(--t-claim); }
.proj__tags { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
.proj__tag {
  font-size: var(--t-micro); font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  padding: var(--s2) var(--s4); border-radius: 999px;
  background: color-mix(in srgb, var(--quiet) 34%, transparent);
}
.proj__notes {
  max-width: 46rem; margin: var(--s8) auto 0;
  display: grid; gap: var(--s4); text-align: center;
}
.proj__notes p { color: color-mix(in srgb, var(--ink) 78%, var(--paper)); }
.proj__intro { color: color-mix(in srgb, var(--ink) 90%, var(--paper)); font-size: var(--t-lead); max-width: 54ch; }

/* His project sheets are a plain two-column grid — some rows full width, no
   captions, one gutter throughout. Where he can run every cell square because
   all his work is square, this work isn't: flyers are tall, screenshots are
   wide. So each cell carries its own piece's proportions and nothing is
   cropped. Wide pieces take both columns, which produces his alternating
   half/half/full rhythm from the work itself rather than from nth-child. */
.plates {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(.5rem, 1.4vw, 1rem);   /* his gutter */
  align-items: start;
  width: 100%; max-width: 62rem; margin-inline: auto;
}
.plate { grid-column: span 1; }
.plate--full { grid-column: 1 / -1; }
/* a half-width piece with no partner left in the run sits centred rather than
   hanging off the left edge */
.plate--solo { grid-column: 1 / -1; justify-self: center; width: min(100%, 31rem); }
.plate figure {
  margin: 0;
  aspect-ratio: var(--ar, 1);
  border-radius: var(--radius);
  overflow: hidden;
  background: color-mix(in srgb, var(--quiet) 20%, transparent);
}
.plate img, .plate video {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.plate video { background: rgba(var(--shadow), .9); }

/* one piece, on its own: sized to the viewport rather than to the column */
.plates--single { grid-template-columns: 1fr; }
.plates--single .plate--solo { width: auto; }
.plates--single .plate figure { max-height: min(78vh, 60rem); width: auto; margin-inline: auto; }
.plates--single .plate img { width: auto; height: 100%; max-width: 100%; }

/* project page furniture */
.shell--proj { padding-block: var(--s6) var(--s9); }
.proj__back { margin-bottom: var(--s5); }
.proj__more { margin-top: var(--s8); text-align: center; }

body.is-locked { overflow: hidden; }

/* -- 12. MOTION ------------------------------------------------------------ */
.rise { opacity: 0; transform: translateY(26px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.rise.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .rise { opacity: 1; transform: none; }
  /* flatten the arc: the reel becomes a plain horizontal strip */
  .reel__slide { rotate: 0deg !important; translate: 0 0 !important; }
  .reel__label { opacity: 1 !important; }
  .fan__card img { translate: none !important; rotate: 0deg !important; scale: 1 !important; }
  .fan__card:not(:last-child) { margin-right: 0 !important; }
  .fan { gap: var(--s3); flex-wrap: wrap; }
}

/* -- 13. RESPONSIVE -------------------------------------------------------- */
@media (max-width: 62rem) {
  .split { grid-template-columns: 1fr; gap: var(--s6); }
  .cards { grid-template-columns: repeat(2, 1fr); }
  .reel__slide { transform-origin: 50% 120vw; }
}
@media (max-width: 40rem) {
  :root { --t-body: 1.0625rem; }
  .header { padding: var(--s4) var(--s4) 0; flex-wrap: wrap; justify-content: center; gap: var(--s3); }
  .hero { padding: var(--s6) var(--s4) var(--s8); }
  .shell { padding-inline: var(--s4); }
  .cards { grid-template-columns: 1fr; }
  .grid { gap: clamp(2rem, 9vw, 4rem); }
  .plates { grid-template-columns: 1fr; }
  .plate, .plate--full { grid-column: 1 / -1; }
  .pill { padding-inline: var(--s4); letter-spacing: .12em; }
  .palette { right: var(--s4); bottom: var(--s4); }
  .fan__card:not(:last-child) { margin-right: -14%; }
  .sheet-scrim { padding: var(--s2); }
  .band { padding-block: var(--s8); }
}
