/* =============================================================
   Erin Ha — Portfolio 2026
   Shared styles
   Design source: Figma "Erin Portfolio 2026"
   Canvas: 1920 x 1080 (desktop-first)
   ============================================================= */

/* ---- Design tokens (pulled from the Figma frame) ---- */
:root {
  --canvas-w: 1920;
  --canvas-h: 1080;
  --bg-dark: #0e0e0e;      /* frame background */
  --wood: #372e24;         /* drawer wood tone */
  --accent: #d8c24a;       /* handwritten-name yellow */
  --transition-ms: 600;    /* page transition duration */
}

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

/* Images are served as WebP with a PNG/JPEG fallback via <picture>.
   `display: contents` removes the wrapper from the layout tree so every
   existing rule that targets the <img> (grid items, absolute positioning,
   hover swaps) keeps working exactly as it did before. */
picture { display: contents; }
/* <source> has no UA `display: none` — it is normally unrendered only because
   <picture> does not render its children. `display: contents` lifts that, so
   without this rule each <source> becomes a real flex/grid item and steals a
   cell from the layout. */
picture > source { display: none; }

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--bg-dark);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: #f4f0e6;
}

/* ---- Scaling stage ----
   Everything is laid out inside a fixed 1920x1080 box.
   JS scales this box to fit the viewport, preserving the
   exact Figma coordinates so hotspots line up perfectly. */
.stage-wrap {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-dark);
}

.stage {
  position: relative;
  width: 1920px;
  height: 1080px;
  transform-origin: center center;
  flex: none;
}

/* Full-bleed background image for a page (the flat Figma export) */
.page-bg {
  position: absolute;
  inset: 0;
  width: 1920px;
  height: 1080px;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
}

/* ---- Drawer background (empty drawer, objects sit on top) ---- */
.drawer-bg {
  position: absolute;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* ---- Object layers (transparent cutouts placed at Figma coordinates) ----
   Each object is a clickable link sized to its default cutout. It holds two
   stacked images: the default state and the lit hover state. On hover we
   cross-fade default -> hover and lift the object slightly. The hover cutout
   (with its sparkles / glow / label) can be larger than the default, so it is
   centered on the object and allowed to overflow. */
.obj {
  position: absolute;
  display: block;
  cursor: pointer;
  outline: none;
  transition: transform .3s cubic-bezier(.22,1,.36,1);
}
.obj img {
  position: absolute;
  user-select: none;
  -webkit-user-drag: none;
  transition: opacity .28s ease;
}
.obj .default {           /* fills the object box */
  left: 0; top: 0;
  width: 100%; height: 100%;
  opacity: 1;
}
.obj .hover {             /* centered on the object, natural size (set inline) */
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
}
.obj:hover, .obj:focus-visible { transform: translateY(-6px); z-index: 60 !important; }
.obj:hover .default, .obj:focus-visible .default { opacity: 0; }
.obj:hover .hover,   .obj:focus-visible .hover   { opacity: 1; }

/* When focus is lost (e.g. a link opened a new tab), force objects back to
   their default state so none stay stuck in hover. Cleared on next mousemove. */
.stage.no-hover .obj .hover { opacity: 0 !important; }
.stage.no-hover .obj .default { opacity: 1 !important; }
.stage.no-hover .obj { transform: none !important; }

/* Floating label that appears when hovering an object */
.obj .tip {
  position: absolute;
  left: 50%;
  bottom: -30px;
  transform: translate(-50%, 8px);
  padding: 6px 14px;
  background: rgba(14, 14, 14, 0.92);
  color: var(--accent);
  font-size: 20px;
  letter-spacing: .04em;
  border-radius: 999px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity .3s ease, transform .3s ease;
}
.obj:hover .tip,
.obj:focus-visible .tip {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ---- Page transition overlay ---- */
#transition-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-dark);
  z-index: 9999;
  pointer-events: none;
  opacity: 1;            /* starts covering the screen, then fades out */
}

/* ---- Sub-page chrome ---- */
.back-btn {
  position: absolute;
  top: 40px;
  left: 48px;
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 22px;
  border: 1px solid rgba(244, 240, 230, 0.35);
  border-radius: 999px;
  background: rgba(14, 14, 14, 0.4);
  color: #f4f0e6;
  font-size: 18px;
  text-decoration: none;
  backdrop-filter: blur(4px);
  transition: background .3s ease, border-color .3s ease;
}
.back-btn:hover { background: rgba(216,194,74,0.16); border-color: var(--accent); }

/* Placeholder shown until a page's flat export is dropped in */
.awaiting-asset {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  text-align: center;
  color: #9c968a;
  background:
    repeating-linear-gradient(45deg,#1a1a1a,#1a1a1a 24px,#151515 24px,#151515 48px);
}
.awaiting-asset h2 { color:#f4f0e6; font-weight:600; font-size:34px; }
.awaiting-asset code {
  background:#000; color:var(--accent); padding:4px 10px; border-radius:6px; font-size:20px;
}

/* ---- Sub-page (scrollable) layout ----
   Case-study boards are tall, so sub-pages scroll vertically and
   show the flat export at a centered max width. */
body.subpage { overflow-y: auto; overflow-x: hidden; background: var(--bg-dark); }
.subpage-wrap {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.subpage-img {
  display: block;
  width: 100%;
  max-width: 1440px;
  height: auto;
  user-select: none;
  -webkit-user-drag: none;
}
.subpage .awaiting-asset {
  position: relative;
  inset: auto;
  width: 100%;
  max-width: 1440px;
  min-height: 100vh;
  padding: 48px;
}

/* ---- Name logo (handwritten "Erin Ha") on the landing ---- */
.name-logo {
  position: absolute;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
  z-index: 1;
}

/* ---- Custom cursor (hand-drawn arrow + magnifying-glass on hover) ----
   Only on devices with a real pointer; touch devices keep their default. */
@media (hover: hover) and (pointer: fine) {
  html, body, a, .obj, .app-icon, button, [data-cursor] { cursor: none; }
  #cursor {
    position: fixed;
    left: 0; top: 0;
    width: 46px; height: 46px;
    background: url("../assets/cursor-default.png") center / contain no-repeat;
    pointer-events: none;
    z-index: 100000;
    will-change: transform;
    transition: width .15s ease, height .15s ease, opacity .2s ease;
  }
  #cursor.hovering {
    background-image: url("../assets/cursor-hover.png");
    width: 56px; height: 56px;
  }
}

/* ================= Passcode lock (UX/UI page) =================
   Matches Figma "Locked Contents" (2:315): gray paper background, a 560x560
   lock centered at (960,530) in the 1920x1080 stage, Roboto Slab text below. */
#lock-screen {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);   /* translucent overlay over the main page */
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .4s ease, visibility .4s ease;
}
#lock-screen.open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
#lock-screen.hide {
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s ease;
}

/* Lock artwork + passcode dots (positioned inside the 1920x1080 stage) */
.lock-visual { position: absolute; }   /* left/top/size set inline */
.lock-img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
  user-select: none; -webkit-user-drag: none;
}

/* 4 passcode dots sit inside the lock's display bar (measured from the art).
   Empty dots are invisible so the default bar looks blank, as in the design;
   each dot appears as its digit is typed. */
.lock-dots {
  position: absolute;
  left: 49.5%; top: 68.1%;          /* centered on the lock body */
  transform: translate(-50%, -50%);
  width: 30%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.lock-dots .dot {
  width: 13%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: #f4f0e6;
  opacity: 0;
  transform: scale(.5);
  transition: opacity .15s ease, transform .15s ease;
}
.lock-dots .dot.filled { opacity: 1; transform: scale(1); }

.lock-primary,
.lock-hint {
  position: absolute;
  transform: translateX(-50%);
  text-align: center;
  font-family: "Roboto Slab", serif;
  color: #ffffff;
  margin: 0;
}
.lock-primary { font-size: 28px; width: 883px; }
.lock-hint { font-size: 15px; white-space: nowrap; opacity: .9; }
#lock-screen.error .lock-primary { color: #e0553f; }

@keyframes lock-shake {
  0%,100% { transform: translateX(0); }
  20% { transform: translateX(-11px); }
  40% { transform: translateX(9px); }
  60% { transform: translateX(-7px); }
  80% { transform: translateX(5px); }
}
#lock-screen.error .lock-visual { animation: lock-shake .45s; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none; left: -9999px;
}

/* ================= UX/UI app-icon home screen ================= */
#uxui-content {
  min-height: 100vh;
  padding: 104px 6vw 70px;
  background: var(--bg-dark);
}
.phone-home h1 {
  text-align: center;
  color: #f4f0e6;
  font-weight: 600;
  font-size: 32px;
  letter-spacing: .02em;
  margin-bottom: 44px;
}
.app-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 30px 26px;
  max-width: 880px;
  margin: 0 auto;
}
.app-icon {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  display: block;
}
.app-icon img {
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 100%;
  transition: opacity .2s ease, transform .25s cubic-bezier(.22,1,.36,1);
}
.app-icon .ai-hover { opacity: 0; }
.app-icon:hover .ai-default,
.app-icon:focus-visible .ai-default { opacity: 0; }
.app-icon:hover .ai-hover,
.app-icon:focus-visible .ai-hover { opacity: 1; transform: translateX(-50%) translateY(-4px); }

/* ================= Intro: closed drawer -> open ================= */
/* Full-stage click target shown until the drawer is opened */
#open-hit {
  position: absolute;
  inset: 0;
  z-index: 50;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}
/* Menu items aren't clickable until the drawer has opened */
.stage.intro .obj { pointer-events: none; }

/* Open transition — exact easing/duration exported from the Figma prototype
   (drawer node 2:202). The `translate` property is animated so it composes
   cleanly with the objects' hover `transform`. First line is a fallback for
   browsers without linear() easing; the second is the exact prototype curve. */
.stage.opening .drawer-bg,
.stage.opening .name-logo,
.stage.opening .obj {
  transition: translate 1.353687s cubic-bezier(0.22, 1, 0.36, 1);
  transition: translate 1.353687s linear(0, 0.0156, 0.0562, 0.1139, 0.1823, 0.2565, 0.3328, 0.4083, 0.481, 0.5496, 0.613, 0.6708, 0.7228, 0.769, 0.8096, 0.8449, 0.8753, 0.9012, 0.923, 0.9413, 0.9564, 0.9687, 0.9786, 0.9865, 0.9926, 0.9973, 1.0009, 1.0034, 1.0052, 1.0063, 1.0069, 1.0072, 1.0072, 1.007, 1.0066, 1.0061, 1.0056, 1.005, 1.0045, 1.004, 1.0034, 1.003, 1.0025, 1.0021, 1.0018, 1.0015, 1.0012, 1.001, 1.0008, 1.0006, 1.0005);
}
/* Objects are hoverable before the drawer's overshoot fully settles, so keep the
   hover lift (transform) eased during the open transition instead of snapping. */
.stage.opening .obj {
  transition: translate 1.353687s cubic-bezier(0.22, 1, 0.36, 1), transform .3s cubic-bezier(.22,1,.36,1);
  transition: translate 1.353687s linear(0, 0.0156, 0.0562, 0.1139, 0.1823, 0.2565, 0.3328, 0.4083, 0.481, 0.5496, 0.613, 0.6708, 0.7228, 0.769, 0.8096, 0.8449, 0.8753, 0.9012, 0.923, 0.9413, 0.9564, 0.9687, 0.9786, 0.9865, 0.9926, 0.9973, 1.0009, 1.0034, 1.0052, 1.0063, 1.0069, 1.0072, 1.0072, 1.007, 1.0066, 1.0061, 1.0056, 1.005, 1.0045, 1.004, 1.0034, 1.003, 1.0025, 1.0021, 1.0018, 1.0015, 1.0012, 1.001, 1.0008, 1.0006, 1.0005), transform .3s cubic-bezier(.22,1,.36,1);
}

/* "OPEN!" prompt (placeholder for the hand-drawn Figma Layer 40) */
#open-prompt {
  position: absolute;            /* left/top/width set inline (Figma Layer 40) */
  pointer-events: none;
  user-select: none;
  z-index: 40;
  text-align: center;
  animation: open-bob 1.2s ease-in-out infinite;
}
#open-prompt img { width: 100%; display: block; -webkit-user-drag: none; }
#open-prompt .chev {
  display: block; font-size: 24px; line-height: 1; letter-spacing: 12px;
  color: #f4f0e6; margin-bottom: 2px;
}
#open-prompt .word {
  font-family: "Roboto Slab", serif; font-weight: 500; font-size: 34px;
  letter-spacing: .06em; color: #f4f0e6;
}
@keyframes open-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* ================= UX/UI page (drawer scene + phone) ================= */
#uxui-content { min-height: 100vh; background: #17120d; overflow: hidden; }
/* the scene lives inside the 1920x1080 scaled stage */
#uxui-scene { position: relative; width: 1920px; height: 1080px; }
#uxui-scene .drawer-bg { position: absolute; }

/* Phone (Figma Layer 11). Real art goes in assets/phone.png; a simple phone
   shape shows until then. */
.uxui-phone { position: absolute; }
.uxui-phone img { width: 100%; height: 100%; display: block; -webkit-user-drag: none; }
.uxui-phone.phone-fallback {
  background: #0f0f10;
  border: 16px solid #5b5b5b;
  border-radius: 68px;
  box-shadow: inset 0 0 40px rgba(0,0,0,.6);
}

/* "Erin Ha" name (doubles as a back-to-drawer link). On hover it swaps to the
   back-nav art ("Erin Ha" + a faint "< BACK"); the name stays aligned and the
   BACK hint appears below. */
.back-name { position: absolute; display: block; }
.back-name img {
  position: absolute; left: 0; top: 0;
  -webkit-user-drag: none; transition: opacity .2s ease;
}
.back-name .nm-default { width: 100%; height: 100%; }
.back-name .nm-hover { width: 285px; height: auto; opacity: 0; pointer-events: none; }
.back-name:hover .nm-default, .back-name:focus-visible .nm-default { opacity: 0; }
.back-name:hover .nm-hover, .back-name:focus-visible .nm-hover { opacity: 1; }

/* "UX/UI" label */
.uxui-label {
  position: absolute; margin: 0;
  font-family: "Roboto Slab", serif; font-weight: 700; font-size: 50px;
  color: #fff; white-space: nowrap;
}

/* App icons on the phone screen; label appears under the icon on hover */
.ph-icon { position: absolute; width: 100px; height: 100px; display: block; }
.ph-icon .ai-default {
  width: 100%; height: 100%; object-fit: cover;
  border-radius: 15px; display: block; -webkit-user-drag: none;
  transition: transform .2s cubic-bezier(.22,1,.36,1), opacity .18s ease;
}
/* the "with stroke" hover version sits slightly larger, centered on the icon */
.ph-icon .ai-stroke {
  position: absolute; left: 50%; top: 50%;
  width: 108px; height: 108px;
  transform: translate(-50%, -50%);
  opacity: 0; pointer-events: none; -webkit-user-drag: none;
  transition: opacity .18s ease, transform .2s cubic-bezier(.22,1,.36,1);
}
.ph-icon:hover .ai-default, .ph-icon:focus-visible .ai-default { opacity: 0; transform: translateY(-5px); }
.ph-icon:hover .ai-stroke, .ph-icon:focus-visible .ai-stroke { opacity: 1; transform: translate(-50%, calc(-50% - 5px)); }
.ph-icon .ai-label {
  position: absolute; top: 110px; left: 50%; transform: translateX(-50%);
  font-family: "Roboto Slab", serif; font-weight: 700; font-size: 15px;
  color: #fff; white-space: nowrap; opacity: 0; pointer-events: none;
  transition: opacity .2s ease;
}
.ph-icon:hover .ai-label, .ph-icon:focus-visible .ai-label { opacity: 1; }

/* ================= Photo & Music pages (drawer scenes) ================= */
#photo-content, #music-content { min-height: 100vh; background: #0e0e0e; overflow: hidden; }
#photo-scene, #music-scene { position: relative; width: 1920px; height: 1080px; }
#photo-scene .drawer-bg, #music-scene .drawer-bg { position: absolute; }

/* Photo stack — placeholder cards (real photos populate later) */
.photo-card {
  position: absolute; width: 720px; height: 480px;
  transform-origin: center center;
  overflow: hidden;
  box-shadow: 0 10px 34px rgba(0,0,0,.4);
}
.photo-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Back cards read as dimmed; the overlay fades as a card is promoted forward */
.photo-card::after {
  content: ""; position: absolute; inset: 0;
  background: rgba(14,14,14,.55); opacity: 0;
  transition: opacity .45s ease; pointer-events: none;
}
.photo-card.dim::after { opacity: 1; }
.photo-shuffle {
  position: absolute; display: block; width: 96px; height: 81px;
  padding: 0; border: 0; background: transparent;
}
.photo-shuffle img { width: 100%; height: 100%; object-fit: contain; display: block; opacity: .85; -webkit-user-drag: none; }
.photo-shuffle:hover img { opacity: 1; }

/* Music — iPod, song text, album-art carousel */
.music-ipod { position: absolute; }
.music-ipod img { width: 100%; height: 100%; display: block; -webkit-user-drag: none; }
.music-title, .music-artist {
  position: absolute; margin: 0; transform: translateX(-50%);
  font-family: "Roboto Slab", serif; color: #fff; text-align: center; white-space: nowrap;
}
.music-title { font-weight: 700; font-size: 26px; }
.music-artist { font-weight: 400; font-size: 16px; }
.album-art {
  position: absolute; overflow: hidden;
  background: linear-gradient(135deg, #3a4a63, #1c2434);   /* placeholder cover */
}
.album-art img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; will-change: transform, opacity;
}
/* Side covers peek from behind the centre: crop toward the middle */
#album-left  img { object-position: right center; }  /* previous → show right edge */
#album-right img { object-position: left center; }   /* next → show left edge */
.album-art.empty { background: none; }

/* Click-wheel hotspots — transparent, round, sit over the iPod wheel */
.wheel-btn {
  position: absolute; margin: 0; padding: 0; border: 0;
  background: transparent; border-radius: 50%; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.wheel-btn:active { transform: scale(0.94); }
.wheel-btn:focus-visible { outline: 2px solid rgba(255,255,255,.6); outline-offset: 2px; }

/* ================= Project case-study pages (Figma-accurate, scrollable) ====
   Each page is a 1920-wide "stage" holding absolutely-positioned screenshots at
   their exact Figma coordinates; JS scales it to the viewport width and sets the
   wrapper height so the page scrolls naturally. */
body.project-page { background: var(--proj-bg, #0e0e0e); overflow-y: auto; overflow-x: hidden; }
.proj-wrap { position: relative; width: 100%; background: var(--proj-bg, #0e0e0e); }
.proj-stage { position: absolute; top: 0; left: 0; width: 1920px; transform-origin: top left; }
.proj-stage .shot {
  position: absolute; object-fit: cover; display: block;
  border-radius: 16px; box-shadow: 0 10px 34px rgba(0,0,0,.4);
  -webkit-user-drag: none;
}
.proj-stage .ptitle {
  position: absolute; margin: 0;
  font-family: "Roboto Slab", serif; font-weight: 700; color: #fff;
  font-size: 50px; line-height: 1.08; text-align: right;
}
.proj-stage .psub {
  position: absolute; margin: 0; right: 111px; text-align: right;
  font-family: "Roboto Slab", serif; font-weight: 700; font-size: 15px;
  color: #fff; text-decoration: underline; white-space: nowrap;
}
.proj-stage .pdesc {
  position: absolute; margin: 0; text-align: center;
  color: #e8e3d8; font-size: 21px; line-height: 1.45;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
/* the back-name on project pages is positioned inside the stage */
.proj-stage .back-name { z-index: 5; }

/* Sticky scroll-to-top FAB (bottom-right) */
.fab-top {
  position: fixed; right: 40px; bottom: 40px; z-index: 70;
  width: 72px; height: 72px; padding: 0; border: 0; background: transparent;
  cursor: pointer; transition: transform .25s cubic-bezier(.22,1,.36,1);
}
.fab-top img { width: 100%; height: 100%; display: block; -webkit-user-drag: none; }
.fab-top:hover { transform: translateY(-4px); }

/* =============================================================
   Graphic Design subpage (long scrolling recreation of node 27:424)
   Fixed 1920-wide stage scaled to viewport width; scrolls vertically.
   ============================================================= */
body.gd { overflow-x: hidden; overflow-y: auto; background: #1f1f1f; }

.gd-viewport { position: relative; width: 100%; overflow: hidden; }
.gd-stage {
  position: relative;
  width: 1920px;
  height: 7120px;
  transform-origin: top left;
  background: #1f1f1f;
}

.gd-splash { position: absolute; user-select: none; }
.gd-splash img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  -webkit-user-drag: none;
  transition: opacity .3s ease;
}
.gd-splash .gd-splash-hover { opacity: 0; }
.gd-splash:hover .gd-splash-default { opacity: 0; }
.gd-splash:hover .gd-splash-hover { opacity: 1; }

.gd-title {
  position: absolute;
  font-family: "Roboto Slab", serif;
  font-weight: 700;
  font-size: 50px;
  line-height: normal;
  color: #fff;
}

.gd-sections { position: absolute; left: 100px; top: 488px; width: 1759px; }
.gd-section { position: relative; }
.gd-section + .gd-section { margin-top: 300px; }

.gd-h {
  position: absolute;
  font-family: "Roboto Slab", serif;
  font-weight: 700;
  font-size: 32px;
  line-height: normal;
  color: #fff;
  opacity: 0.9;
}

.gd-img {
  position: absolute;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
}

.gd-grid { position: absolute; display: grid; }
.gd-cell {
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
}

/* Small viewport helper note (desktop-first design) */
.rotate-note { display:none; }
.rotate-note p { display:none; }   /* hide placeholder text; image carries the message */

/* Show the hand-drawn disclaimer on small portrait screens.
   Rotating the phone to landscape hides it (as the note instructs). */
@media (max-width: 900px) and (orientation: portrait) {
  .rotate-note {
    display:block; position:fixed; inset:0; z-index:10000;
    background:#000 url("../assets/Untitled_Artwork%2033.png") center center / contain no-repeat;
  }
}

/* =============================================================
   About Me (about.html)
   Figma section "About Me" — 11 chalkboard frames, node 143:876.
   The drawer, the name logo and the two chalk arrows are fixed
   furniture; only the board contents slide horizontally.
   ============================================================= */

.about-stage { overflow: hidden; }

/* Drawer. Matches index.html so the fade between pages lines up. */
.ab-board {
  position: absolute;
  left: 224px;
  top: 0;
  width: 1462px;
  height: 1062px;
}

/* Flat wood tone underneath the drawer photo (Figma 137:424) */
.ab-wood {
  position: absolute;
  left: 16px;
  top: 0;
  width: 1440px;
  height: 1015px;
  background: var(--wood);
}

.ab-frame {
  position: absolute;
  left: 0;
  top: 0;
  width: 1462px;
  height: 1062px;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* Handwritten name logo — back to the drawer.
   Styling and the hover swap come from .back-name (shared with music.html
   and photo.html); this only lifts it above the sliding boards. */
.ab-back { z-index: 40; }

/* ---- Sliding boards ----
   Every board is a full-size layer stacked in the same place. Only the
   active one is displayed; GSAP slides the outgoing one off and the
   incoming one in from the opposite edge.

   drawerbackground.png is a photograph with no transparency, so the
   boards can't sit behind it in the z-order — they'd vanish. Instead the
   whole slide track is clipped to the drawer's inner rim, which reads the
   same way: artwork slides out and disappears under the wooden edge
   rather than travelling across it. The polygon follows the rim's slight
   perspective (measured off the 1462x1062 drawer plate). */
.ab-slides {
  position: absolute;
  inset: 0;
  z-index: 10;
  clip-path: polygon(86px 66px, 1384px 62px, 1396px 1004px, 70px 1006px);
}
.ab-slide {
  position: absolute;
  inset: 0;
  display: none;
  will-change: transform;
}
.ab-slide.is-active { display: block; }

/* Chalk artwork sitting on the board */
.ab-art {
  position: absolute;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* Body copy — Figma Roboto Slab 17/1.3 white */
.ab-body {
  position: absolute;
  font-family: "Roboto Slab", Georgia, serif;
  font-weight: 400;
  font-size: 17px;
  line-height: 1.3;
  color: #fff;
  word-break: break-word;
}
.ab-body strong { font-weight: 700; }

/* Photo captions — Roboto Slab Light */
.ab-caption {
  position: absolute;
  font-family: "Roboto Slab", Georgia, serif;
  font-weight: 300;
  line-height: 1.3;
  color: #fff;
  word-break: break-word;
}

/* Centred copy (boards 10 and 11) is positioned from its own centre */
.ab-center {
  transform: translateX(-50%);
  text-align: center;
}

/* ---- Chalk arrows ---- */
.ab-nav {
  position: absolute;
  width: 80px;
  height: 100px;
  z-index: 50;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  opacity: .92;
  transition: opacity .25s ease, transform .25s cubic-bezier(.22,1,.36,1);
}
.ab-nav img {
  width: 100%;
  height: 100%;
  user-select: none;
  -webkit-user-drag: none;
}
.ab-nav:hover,
.ab-nav:focus-visible { opacity: 1; }
.ab-prev:hover, .ab-prev:focus-visible { transform: translateX(-6px); }
.ab-next:hover, .ab-next:focus-visible { transform: translateX(6px); }

/* Hidden at the ends of the sequence, matching About Me 1 in Figma */
.ab-nav[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .ab-nav, .ab-back { transition: none; }
}

/* =============================================================
   Global grain (assets/image 22.png)
   A 3840x2160 film-grain plate: neutral mid-grey with speckles.
   Because the base tone is mid-grey it disappears under
   mix-blend-mode: overlay, leaving only the speckle and a lift in
   contrast. Painted on every page via body::after, so no page needs
   its own markup.

   Sits at z-index 9000 — above the artwork, but below the page
   transition overlay (9999) so fades stay clean black, and below the
   custom cursor (100000) so the cursor never picks up grain.
   ============================================================= */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  background: url("../assets/image%2022.png") center center / cover no-repeat;
  mix-blend-mode: overlay;
  opacity: .55;
}

/* The lock screen and the rotate note are chrome, not artwork — let them
   sit above the grain so their text stays crisp. */
#lock-screen { z-index: 9500; }
.rotate-note { z-index: 10000; }

@media (prefers-reduced-motion: reduce) {
  body::after { opacity: .4; }
}
