:root {
  --gold: #f7c94a;
  --gold-dim: #b4943a;
  --ease: cubic-bezier(0.65, 0, 0.35, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: #fff;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* overflow-x:hidden here would make body a scroll container and
     silently break position:sticky on #work-hero — clip avoids that */
  overflow-x: clip;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

img { display: block; max-width: 100%; }

/* ---------- Per-mat nav ---------- */

.mat-nav {
  position: absolute;
  bottom: 4%;
  right: 3%;
  z-index: 30;
  display: flex;
  gap: 0.9em;
  font-size: 16px;
  color: #fff;
  letter-spacing: -0.05em;
}

.mat-nav .nav-link {
  font-weight: 400;
  transition: opacity 0.15s;
}

.mat-nav .nav-link[data-active="true"] { font-weight: 700; }
.mat-nav .nav-link:hover { opacity: 0.7; }

/* back button: bottom-left, same row as .mat-nav (bottom-right) */
.back-btn {
  position: absolute;
  bottom: 4%;
  left: 3%;
  z-index: 30;
  font-size: 16px;
  color: #fff;
  letter-spacing: -0.05em;
  transition: opacity 0.15s;
}
.back-btn:hover { opacity: 0.7; }
.back-btn[hidden] { display: none; }

/* sub nav (art tab: illustrations/sketches) */
.sub-nav {
  position: absolute;
  right: 3%;
  bottom: 7%;
  display: flex;
  gap: 0.8em;
  font-size: 14px;
  color: #fff;
  letter-spacing: -0.05em;
  z-index: 20;
  transition: opacity 0.25s var(--ease);
}
.sub-nav[hidden] { display: none; }
.sub-nav .nav-link[data-active="true"] { font-weight: 700; }

/* ---------- Shared mat / mat-frame ---------- */

.tab { position: relative; width: 100%; }

/* mat-frame: full white page area that centers the mat card, so the
   whole cutting mat (incl. rounded corners) is always visible */
.mat-frame {
  position: relative;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vh 4vw;
  background: #fff;
  z-index: 5;
  transition: padding 0.5s var(--ease);
}

/* how much of the mat stays visible as the "nav bar" strip once fully
   scroll-locked — 10.4vh reveals down to the 4th cutting-mat grid line
   from the bottom (measured directly off cuttingmat.svg: that line
   sits 11.31% of the mat's own height up from its bottom edge, and the
   mat itself renders at ~92vh whenever the viewport is the limiting
   dimension, so 0.1131 * 92vh ≈ 10.4vh). Keep in sync with the
   matching constant in js/work.js's scrollProgress(). */
.mat-frame--sticky {
  position: sticky;
  top: calc(-100vh + 10.4vh);
}

/* Once fully parked/stuck (js/work.js adds .stuck-flush only at scroll
   progress ~1), only the frame's bottom edge is visible on screen — but
   the frame's own padding-bottom (from the shared .mat-frame rule,
   meant to center the mat while it's still full-size) doesn't go away
   just because it's stuck, so it was leaving a plain white gap between
   the visible green strip and whatever content follows. Dropping it to
   0 and bottom-aligning the mat instead makes the strip's visible edge
   flush against the case study content right below it.
   This must NOT apply for the whole "selected" state (only once truly
   parked) — applying it immediately on selection, before any scrolling,
   pushed the still full-size resting mat down out of the visible area
   instead of leaving it centered like the "stars 34" moment needs. */
.mat-frame--sticky.stuck-flush {
  padding-bottom: 0;
  align-items: flex-end;
}

.mat {
  position: relative;
  width: 100%;
  max-width: calc(92vh * 1.6825);
  aspect-ratio: 1605.69 / 954.18;
  transition: max-width 0.5s var(--ease), aspect-ratio 0.5s var(--ease);
}

/* lets the centered notecard tilt in 3D toward the cursor, same as the
   sketchbook widget's own pointer-tilt and the art landing page's stack */
#work-mat {
  perspective: 1750px;
  perspective-origin: 50% 46%;
}

.mat-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  z-index: 0;
}

.headline {
  position: absolute;
  left: 3%;
  top: 3%;
  transform: none;
  margin: 0;
  font-weight: 700;
  font-size: clamp(2.6rem, 11vw, 11rem);
  letter-spacing: -0.05em;
  color: var(--gold);
  white-space: nowrap;
  z-index: 1;
  transition: color 0.4s var(--ease), opacity 0.4s var(--ease);
  pointer-events: none;
}

/* small "Kari" logo the big headline shrinks/crossfades into once the
   art grid is expanded (same spot, same styling family as .headline) */
.art-logo {
  position: absolute;
  left: 3%;
  top: 2%;
  margin: 0;
  font-weight: 700;
  font-size: 6.2rem;
  letter-spacing: -0.08em;
  color: var(--gold);
  z-index: 1;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
  /* invisible (opacity:0) in the "cover" state, so it shouldn't be
     clickable until it's actually shown post-expand */
  pointer-events: none;
}

/* =========================================================
   WORK TAB
   ========================================================= */

/* short — just enough runway after the notecard finishes parking
   (driven separately by scrollProgress() in js/work.js, tied to the
   sticky hero's own collapse distance) before the case study content
   arrives; it isn't meant to be a long scroll on its own. */
.scroll-spacer { height: 10vh; }
#tab-work[data-state="selected"] .scroll-spacer { display: block; }
#tab-work[data-state="closed"] .scroll-spacer,
#tab-work[data-state="open"] .scroll-spacer { height: 0; }

.case-study {
  position: relative;
  z-index: 1;
  min-height: 40vh;
  background: #fff;
}

/* the sketchbook engine (js/sketchbook.js) mounts here; it renders both
   the closed cover and the open spread inside this one fixed-aspect box */
.sketchbook-mount {
  position: absolute;
  left: 19.1%;
  top: 16.9%;
  width: 61.8%;
  aspect-ratio: 1760 / 1240;
  z-index: 2;
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease), visibility 0s linear 0.5s;
}

/* About's own canvas is narrower/taller (1536/1240, see sketchbook.css's
   matching #about-book .sb-book override) than the shared 1760/1240
   ratio this base rule assumes — left as-is, the mount's own declared
   box stays sized off the OLD wider ratio while its actual content
   (driven by .sb-book's real aspect-ratio) renders taller, so it simply
   overflows the mount's box instead of being a deliberate size. Give it
   its own aspect-ratio to match, and a width recalculated so its
   rendered HEIGHT comes out equal to Work/Art's (61.8% / (1760/1240)),
   re-centered — same book size as the other two, just narrower/taller
   in its own proportions instead of matching their width. */
#about-book {
  width: 53.93%;
  left: 23.04%;
  aspect-ratio: 1536 / 1240;
}

.sketchbook-mount.dropped {
  opacity: 0;
  visibility: hidden;
  transform: translateY(60%);
  pointer-events: none;
}

.notecards {
  position: absolute;
  inset: 0;
  z-index: 3;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s var(--ease) 0.2s;
}
.notecards.show { opacity: 1; }

.notecard {
  position: absolute;
  left: var(--cx);
  top: var(--cy);
  width: var(--w);
  transform: translate(-50%, -50%) rotate(var(--r));
  filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));
  transition: transform 0.6s var(--ease), opacity 0.5s var(--ease), left 0.6s var(--ease), top 0.6s var(--ease), width 0.6s var(--ease);
  /* pointer-events only turns on once the container is actually shown
     (below) — left unconditional, these buttons stay clickable even
     while invisible (opacity:0 doesn't affect pointer-events), and
     since .notecards' z-index:3 beats .sketchbook-mount's z-index:2 at
     their shared ancestor, that invisible hit-box sits ABOVE THE WHOLE
     BOOK regardless of sb-zone's own higher z-index (trapped inside the
     mount's own, lower-priority stacking context) — silently eating
     the click meant to open the closed cover. */
  pointer-events: none;
}
.notecards.show .notecard {
  pointer-events: auto;
}

.notecard img { width: 100%; }

.notecard:not(.notecard--dropped):hover {
  transform: translate(-50%, -50%) rotate(var(--r)) scale(1.04);
}

.notecard--dropped {
  transform: translate(-50%, 140%) rotate(var(--r)) !important;
  opacity: 0;
  pointer-events: none;
}

.notecard--selected {
  left: 50%;
  top: 56%;
  width: 22%;
  transform: translate(-50%, -50%) rotate(0deg) rotateX(var(--card-rx, 0deg)) rotateY(var(--card-ry, 0deg));
  z-index: 6;
}

/* =========================================================
   ART TAB
   ========================================================= */

/* expanded state: the background pins to the viewport (so it stays put
   while the gallery scrolls over it) and scales up ~1.3x to read as a
   full-screen backdrop instead of a bordered card. */
#tab-art[data-state="expanded"] #art-frame {
  position: fixed;
  inset: 0;
  z-index: 1;
}
.mat--art {
  transition: transform 0.7s var(--ease);
  /* lets the scattered stack tilt in 3D toward the cursor, same as the
     sketchbook widget's own pointer-tilt (js/sketchbook.js tiltTo) */
  perspective: 1750px;
  perspective-origin: 50% 46%;
}
#tab-art[data-state="expanded"] .mat--art { transform: scale(1.3); }

#tab-art[data-state="expanded"] .headline { opacity: 0; }
#tab-art[data-state="expanded"] .art-logo { opacity: 1; pointer-events: auto; cursor: pointer; }

.art-scatter {
  position: absolute;
  inset: 0;
  z-index: 2;
  transform: rotateX(var(--art-rx, 0deg)) rotateY(var(--art-ry, 0deg));
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}
/* faster, direct-feeling response while actually tracking the cursor;
   the slower 0.5s above is for the opacity/scale state changes instead */
#tab-art[data-state="cover"] .art-scatter {
  transition: opacity 0.5s var(--ease), transform 0.15s ease-out;
}

.scatter-img {
  position: absolute;
  width: 29%;
  height: auto;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.35);
  transform: translate(-50%, -50%) rotate(var(--r, 0deg));
  transition: left 0.35s var(--ease), top 0.35s var(--ease), transform 0.35s var(--ease);
}
.scatter-img[data-slot="0"] { left: 53.7%; top: 53.2%; --r: 10.28deg; z-index: 1; }
.scatter-img[data-slot="1"] { left: 53.6%; top: 60.6%; --r: 1.52deg; z-index: 2; }
.scatter-img[data-slot="2"] { left: 55.5%; top: 62.5%; --r: 1.52deg; z-index: 3; }

/* Hovering the cover or any of the peeking images nudges all three
   further out from behind the cover, continuing the same direction
   each is already offset in — a preview hint that clicking spreads
   them out into the full gallery grid. :has() scopes this to actually
   hovering the stack itself, not just anywhere in .art-scatter (which
   is inset:0 over the whole mat). */
#tab-art[data-state="cover"] .art-scatter:has(.art-cover:hover, .scatter-img:hover) .scatter-img[data-slot="0"] {
  left: 56%;
  top: 49%;
  --r: 12deg;
}
#tab-art[data-state="cover"] .art-scatter:has(.art-cover:hover, .scatter-img:hover) .scatter-img[data-slot="1"] {
  left: 57%;
  top: 64%;
  --r: 0deg;
}
#tab-art[data-state="cover"] .art-scatter:has(.art-cover:hover, .scatter-img:hover) .scatter-img[data-slot="2"] {
  left: 60%;
  top: 68%;
  --r: 4deg;
}

.art-cover {
  position: absolute;
  left: 50%;
  top: 57.5%;
  width: 30.2%;
  transform: translate(-50%, -50%);
  z-index: 4;
  box-shadow: inset 4px 6px 3px rgba(255, 255, 255, 0.3), inset -7px -8px 4px rgba(0, 0, 0, 0.25), 0 6px 18px rgba(0, 0, 0, 0.4);
  /* matches the notebook-spine convention used elsewhere (sb-full in
     css/sketchbook.css): only the outer/right edge is rounded. Doubled
     alongside the flip-book cover's own baked-in radius (26px -> 52px)
     so this pre-click preview reads as consistently rounded as the
     enlarged view it leads into. */
  border-radius: 0 3.6% 3.6% 0;
  overflow: hidden;
  transition: transform 0.6s var(--ease);
}
.art-cover img { border-radius: inherit; }

/* the cover keeps this same rounding once it's moved into the grid as
   a bare <img> (see makeImg() in js/art.js) — that move leaves the
   .art-cover wrapper (and its border-radius) behind */
.art-cover-thumb { border-radius: 0 3.6% 3.6% 0; }

/* normal document flow (not absolute) so its real content height makes
   the page scrollable while the background stays fixed behind it — see
   #art-frame above. Zero-height + clipped until expanded so the hidden
   grid can't make the "cover" state scrollable. */
.art-grid {
  position: relative;
  z-index: 2;
  display: flex;
  gap: 1.1vw;
  max-width: min(1100px, 90vw);
  margin: 0 auto;
  /* padding lives only in the expanded rule below — height:0 does NOT
     override padding, so unconditional padding here would still force
     ~216px of real (scrollable, partially visible) box height even while
     "collapsed" */
  padding: 0;
  height: 0;
  overflow: hidden;
  pointer-events: none;
}

/* one masonry column — exactly three, always; each image inside keeps
   its own natural aspect ratio (no cropping), and the same gap value is
   used both between columns and between images stacked in a column, so
   spacing reads as consistent in every direction */
.art-col {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  gap: 1.1vw;
  min-width: 0;
}

.art-grid img {
  width: 100%;
  height: auto;
  display: block;
  cursor: zoom-in;
  /* filter:drop-shadow instead of box-shadow — box-shadow has to be
     repainted on the CPU every frame of the transition, and that cost
     scales with the image's ON-SCREEN area, so taller images (more
     rendered pixels for the shadow to cover) visibly stuttered while
     small ones didn't, even after capping every source image to the
     same resolution. drop-shadow can ride along on the same GPU layer
     as the transform instead, so the cost stops depending on how big
     the image is currently rendered at. */
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.3));
  transition: transform 0.3s var(--ease), filter 0.3s var(--ease);
  will-change: transform;
}

.art-grid img:hover {
  transform: scale(1.04);
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.4));
}

/* ---------- lightbox: click a gallery image to enlarge ---------- */
.art-lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.85);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s var(--ease);
}
.art-lightbox.open { opacity: 1; pointer-events: auto; }
.art-lightbox-frame {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 88vw;
  max-height: 88vh;
  cursor: zoom-out;
}
.art-lightbox img {
  max-width: 88vw;
  max-height: 76vh;
  width: auto;
  height: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}
.art-lightbox-caption {
  margin-top: 1.1em;
  text-align: center;
  color: #fff;
}
.art-lightbox-title {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.art-lightbox-title:empty { display: none; }
.art-lightbox-meta {
  margin: 0.25em 0 0;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.6);
}
.art-lightbox-meta:empty { display: none; }

/* prev/next between grid artworks, styled like the sketchbook engine's
   own .sb-arrow chevrons (same polyline/stroke) so the two lightboxes'
   navigation reads as one consistent pattern, just pinned to the
   viewport edges here instead of flanking the book inline. */
.art-lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.55);
  cursor: pointer;
  padding: 12px;
  transition: color 0.2s;
  z-index: 2;
}
.art-lightbox-arrow:hover { color: #fff; }
.art-lightbox-arrow:disabled { opacity: 0.25; cursor: default; }
.art-lightbox-arrow.left { left: 2vw; }
.art-lightbox-arrow.right { right: 2vw; }

/* ---------- flippable sketchbook overlay for the "sketchbook" grid
   tile — big and centered like the plain lightbox, but hosts the same
   flipbook widget the landing pages use instead of a static image ---------- */
.art-book-lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.85);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s var(--ease);
}
.art-book-lightbox.open { opacity: 1; pointer-events: auto; }
.art-book-lightbox-frame {
  width: min(80vw, 1200px);
}
/* overrides .sketchbook-mount's absolute positioning, which assumes
   it's placed inside a .mat — here it just fills its own frame */
#art-book-mount {
  position: relative;
  left: auto;
  top: auto;
  width: 100%;
  aspect-ratio: 1760 / 1240;
  /* .sb-arrow's color comes from these (sketchbook.css), tuned for the
     light cutting-mat background elsewhere — against this lightbox's
     dark overlay they'd be nearly invisible, so lighten them just for
     this instance. */
  --ink: #fff;
  --ink-soft: rgba(255, 255, 255, 0.75);
  --ink-faint: rgba(255, 255, 255, 0.45);
}
/* Page-turn navigation here should only ever be an explicit chevron
   click — .sb-arrow is hidden site-wide (below) since work/about's
   single-spread books have nothing to page through, but the art book's
   real 25 pages make a visible prev/next actually useful. Needs
   !important to outrank that site-wide rule, which also uses it. */
#art-book-lightbox .sb-arrow { display: inline-flex !important; }
.art-book-lightbox-close {
  position: absolute;
  top: 24px;
  right: 32px;
  color: #fff;
  font-size: 2.2rem;
  line-height: 1;
  z-index: 2;
  transition: opacity 0.15s;
}
.art-book-lightbox-close:hover { opacity: 0.7; }

#tab-art[data-state="expanded"] .art-scatter {
  opacity: 0;
  transform: scale(1.1);
  pointer-events: none;
}

#tab-art[data-state="expanded"] .art-grid {
  height: auto;
  overflow: visible;
  pointer-events: auto;
  padding: 14vh 0 10vh;
}

#tab-art[data-state="expanded"] .sub-nav { opacity: 1; }

/* "check out my studies!" prompt at the bottom of the illustrations
   grid — nudges visitors toward the sketches/studies sub-nav section */
.art-cta {
  position: relative;
  z-index: 2;
  display: block;
  margin: -6vh auto 8vh;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--gold);
  text-align: center;
  transition: opacity 0.15s;
}
.art-cta:hover { opacity: 0.7; }
.art-cta[hidden] { display: none; }

/* nav/back/sub-nav for the art tab live outside .mat (see index.html) so
   they stay above the fixed background and the scrolling gallery, always
   reachable regardless of scroll position or expanded state */
.art-fixed-nav { position: fixed; z-index: 40; }

/* the outside/fixed main nav only takes over once expanded (mat is a
   fixed full-screen background at that point, so viewport-relative
   positioning matches); before that, the inside-mat copy above keeps the
   cover state's nav pixel-consistent with work/about. */
.art-fixed-nav.mat-nav { display: none; }
#tab-art[data-state="expanded"] .mat--art > .mat-nav { display: none; }
#tab-art[data-state="expanded"] .art-fixed-nav.mat-nav { display: flex; }

/* =========================================================
   ABOUT TAB
   ========================================================= */

/* #about-book intentionally has no position override anymore — it uses
   the same left/top/width as .sketchbook-mount's base rule (matching
   work's landing layout exactly), just like the user asked */

.polaroid-trigger {
  position: absolute;
  left: 53.1%;
  top: 16.9%;
  width: 27.8%;
  height: 73.3%;
  z-index: 5;
  cursor: pointer;
}
#tab-about[data-state="closed"] .polaroid-trigger { display: none; }

.polaroids {
  position: absolute;
  right: 27%;
  top: 53.5%;
  width: 13.5%;
  transform: translateY(-50%);
  z-index: 4;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s var(--ease);
}

#tab-about[data-state="open"] .polaroids {
  opacity: 1;
  pointer-events: auto;
}

.polaroid {
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%;
  transform: translateY(-50%) rotate(var(--r)) translate(var(--ox), var(--oy));
  /* box-shadow follows the IMG's full bounding box regardless of
     transparency, but these source photos have a soft alpha feather
     (~10-40px) around the actual visible polaroid edge — so a
     box-shadow left a visible transparent gap between the real edge
     and where the shadow started. filter:drop-shadow instead follows
     the actual alpha shape of the image content, same fix already used
     for .notecard below. */
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.3));
  transition: transform 0.6s var(--ease), left 0.6s var(--ease), top 0.6s var(--ease);
}

/* Slot 0 is always the top/front card. Cycling which photo currently
   occupies which slot (about.js reassigns data-i on click) is what
   makes clicking the stack look like flipping through it — the actual
   position/rotation per slot never changes, only which <img> is in it,
   and the existing transform/left/top transition on .polaroid animates
   that move. */
.polaroid[data-i="0"] { --r: -8deg; --ox: -6%; --oy: -30%; z-index: 4; }
.polaroid[data-i="1"] { --r: 5deg; --ox: 8%; --oy: -8%; z-index: 3; }
.polaroid[data-i="2"] { --r: -4deg; --ox: -4%; --oy: 14%; z-index: 2; }
.polaroid[data-i="3"] { --r: 7deg; --ox: 6%; --oy: 34%; z-index: 1; }

/* ---------- small screens: scale everything down gracefully ---------- */

@media (max-width: 640px) {
  .mat-nav { font-size: 13px; gap: 0.6em; }
  .sketchbook-mount { width: 84%; }
  .notecard { width: calc(var(--w) * 1.5); }
  .polaroids { width: 26%; }
}

/* ---------- sketchbook engine chrome: hidden site-wide ---------- */
.sb-arrow, .sb-tools, .sb-hint { display: none !important; }
.sb-wrap { gap: 0 !important; }
