/* Jayson Lee — portfolio
   Layout: fixed-width sticky sidebar + warm content area on desktop/tablet;
   header with a Projects dropdown on phones. */
:root {
  --bg: #fdf9f7;          /* warm content background */
  --surface: #ffffff;     /* sidebar, dropdown, phone background */
  --ink: #111111;         /* primary text */
  --muted: #777370;       /* meta lines, captions */
  --line: #eeeae8;        /* dividers and borders */
  --hover: #f0f0f0;       /* open button / hover fill */
  --soft: #c9c4c1;        /* underlines, dashed outlines */
  --border: #e4e4e4;      /* button and dropdown borders */
  --focus: #143ef7;       /* keyboard focus ring */
  --shadow: rgba(0, 0, 0, .08);
  --font: "Geist", "Noto Sans KR", system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --radius: 12px;
  --sidebar: 210px;
  color-scheme: light;
}
/* Dark mode: follows the device setting unless the visitor picks one with the toggle */
:root[data-theme="dark"] {
  --bg: #121110; --surface: #191817; --ink: #f1eeec; --muted: #9b9693;
  --line: #2b2927; --hover: #262422; --soft: #4b4744; --border: #34312f;
  --focus: #7d98ff; --shadow: rgba(0, 0, 0, .45);
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #121110; --surface: #191817; --ink: #f1eeec; --muted: #9b9693;
    --line: #2b2927; --hover: #262422; --soft: #4b4744; --border: #34312f;
    --focus: #7d98ff; --shadow: rgba(0, 0, 0, .45);
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 4px; }

/* ---------- Shell ---------- */
.shell { display: grid; grid-template-columns: var(--sidebar) minmax(0, 1fr); min-height: 100vh; }

.sidebar {
  position: sticky; top: 0; height: 100vh;
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding: 36px 28px;
  display: flex; flex-direction: column; gap: 36px;
}
.name { font-weight: 500; font-size: 15px; line-height: 1.3; letter-spacing: 0.01em; }
.name .ko { display: block; font-weight: 400; }
.side-links { display: flex; flex-direction: column; gap: 10px; font-size: 15px; }
.side-links a { color: var(--ink); transition: color .15s; }
/* Hover wave on nav links (adapted from the Text_03 component): letters nudge to the
   right one after another with a slight spring overshoot, then settle back on leave. */
.wave { display: inline-block; white-space: nowrap; }
.wave span {
  display: inline-block; transform-origin: 50% 70%;
  transition: transform .35s cubic-bezier(.34, 1.56, .64, 1);
}
a:hover > .wave span, a:focus-visible > .wave span {
  transform: translateX(4px);
  transition-delay: calc(var(--i) * 30ms);
}
/* The name waves straight through from JAYSON LEE into the Korean line. */
.name:hover .wave span, .name:focus-visible .wave span { transform: translateX(4px); transition-delay: calc(var(--i) * 30ms); }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.side-links a[aria-current="page"] { font-weight: 500; }

.main { position: relative; padding: 40px 44px 96px 44px; min-width: 0; }

/* Phone header (hidden on larger screens) */
.topbar { display: none; }

/* ---------- Home grid ---------- */
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px 20px; max-width: 1240px; margin: 0 auto; }
.card { display: flex; flex-direction: column; gap: 12px; }
.card-img { aspect-ratio: 3 / 2; width: 100%; border-radius: var(--radius); overflow: hidden; background: var(--line); }
.card-img img { width: 100%; height: 100%; object-fit: cover; transition: transform .9s cubic-bezier(.22, .61, .36, 1); }
.card:hover .card-img img, .card:hover .card-video { transform: scale(1.01); }
.card-img { position: relative; }
.card-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0; pointer-events: none;
  transition: opacity .5s ease-out, transform .9s cubic-bezier(.22, .61, .36, 1);
}
.card.is-playing .card-video { opacity: 1; transition: opacity .8s cubic-bezier(.22, .61, .36, 1), transform .9s cubic-bezier(.22, .61, .36, 1); }
/* Wordmark shown over a hover video (e.g. "MOV"), with a light scrim for legibility */
.card-label {
  position: absolute; inset: 0; display: grid; place-items: center;
  color: #fff; font-weight: 700; font-size: clamp(56px, 8vw, 112px);
  letter-spacing: -0.045em; line-height: 1;
  background: rgba(0, 0, 0, .28);
  opacity: 0; transform: translateY(4px); pointer-events: none;
  transition: opacity .5s ease-out, transform .5s ease-out;
}
.card.is-playing .card-label {
  opacity: 1; transform: none;
  transition: opacity .8s cubic-bezier(.22, .61, .36, 1) .1s, transform .8s cubic-bezier(.22, .61, .36, 1) .1s;
}
/* Token card: the art is a 16:9 stage centred in the 3:2 card (cropped like the
   other images), with the logo laid over it as SVG letters at the same spot as in
   the original artwork. On hover each letter hops in turn, left to right. */
.tk-stage {
  position: absolute; top: 0; left: 50%; height: 100%; aspect-ratio: 16 / 9;
  transform: translateX(-50%);
  transition: transform .9s cubic-bezier(.22, .61, .36, 1);
}
.card:hover .tk-stage { transform: translateX(-50%) scale(1.01); }
.card:hover .card-img .tk-stage img { transform: none; }
.tk-stage img { width: 100%; height: 100%; object-fit: cover; }
.tk-logo { position: absolute; left: 18.04%; top: 31.16%; width: 63.84%; height: auto; overflow: visible; }
.tk-letter { fill: #fff; transform-box: fill-box; transform-origin: 50% 100%; }
.card:hover .tk-letter, .card:focus-visible .tk-letter, .card.is-playing .tk-letter {
  animation: tk-hop .75s cubic-bezier(.3, .7, .4, 1) both;
  animation-delay: calc(var(--i) * 70ms);
}
@keyframes tk-hop {
  0%   { transform: translateY(0) scale(1, 1); }
  18%  { transform: translateY(2%) scale(1.06, .92); }
  45%  { transform: translateY(-16%) scale(.95, 1.07); }
  70%  { transform: translateY(0) scale(1.07, .93); }
  85%  { transform: translateY(-3%) scale(.98, 1.02); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* Edge glow on home cards (adapted from the GlowCard component).
   The light lives only on the card's rounded border: a ring masked to the border,
   brightest on the side facing the pointer (cards.js sets --ga, the angle from the
   card's centre to the pointer), fading to a faint line around the rest of the edge.
   A soft shadow in the same colour follows the card's own rounded shape. */
.card-img[data-glow] {
  --glow-border: 2px;
  --glow-base: 220;
  --glow-spread: 0;
  --glow-hue: calc(var(--glow-base) + var(--xp, .5) * var(--glow-spread));
  --glow: hsl(var(--glow-hue) 100% 62%);
  --glow-soft: hsl(var(--glow-hue) 100% 62% / .18);
  overflow: visible; background: none;
}
.card-media {
  position: absolute; inset: 0; border-radius: var(--radius); overflow: hidden; background: var(--line); z-index: 1;
  transition: box-shadow .4s ease-out;
}
.card-img[data-glow]::before {
  content: ""; position: absolute; z-index: 2; pointer-events: none;
  inset: calc(var(--glow-border) * -1);
  border: var(--glow-border) solid transparent;
  border-radius: calc(var(--radius) + var(--glow-border));
  background: conic-gradient(from calc((var(--ga, 0) - 90) * 1deg),
    var(--glow-soft) 0deg, var(--glow) 90deg, var(--glow-soft) 180deg, var(--glow-soft) 360deg) border-box;
  -webkit-mask: linear-gradient(transparent, transparent) padding-box, linear-gradient(#fff, #fff) border-box;
  -webkit-mask-composite: source-in;
  mask: linear-gradient(transparent, transparent) padding-box, linear-gradient(#fff, #fff) border-box;
  mask-composite: intersect;
  opacity: 0; transition: opacity .35s ease-out;
}
.card-img.glow-near::before { opacity: 1; }
.card-img.glow-near .card-media { box-shadow: 0 0 24px -4px hsl(var(--glow-hue) 100% 60% / .35), 0 14px 48px -10px hsl(var(--glow-hue) 100% 55% / .7); }

.card h2 { margin: 0; font-size: 16px; font-weight: 500; line-height: 1.3; }
.card p { margin: 3px 0 0; font-size: 13px; color: var(--muted); }

/* Back link on every page except the homepage. Sits above the content on smaller
   screens, and moves into the empty left margin when there's room for it. */
.back-link {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 28px;
  font-size: 14px; color: var(--muted); transition: color .2s;
}
.back-link svg { transition: transform .35s cubic-bezier(.34, 1.56, .64, 1); }
.back-link:hover, .back-link:focus-visible { color: var(--ink); }
.back-link:hover svg, .back-link:focus-visible svg { transform: translateX(-4px); }
@media (min-width: 1360px) {
  .main { position: relative; }
  /* Only case studies have a centred column with a free margin to sit in */
  .main:has(> .case) .back-link { position: absolute; top: 40px; left: 44px; margin: 0; }
}

/* ---------- Case study ---------- */
.case { max-width: 873px; margin: 0 auto; display: flex; flex-direction: column; gap: 72px; }
/* Spec row: three equal columns so every case study lines up the same way */
.meta { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 32px; font-size: 15px; }
.meta p { margin: 0; }
.hero { display: flex; flex-direction: column; gap: 12px; }
.hero img, .hero video { display: block; border-radius: var(--radius); width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: #1a1a6e; }
.caption { font-size: 13px; color: var(--muted); font-style: italic; margin: 0; }
.caption-plain { font-size: 13px; color: var(--muted); }
.lede { font-style: italic; margin: 0; max-width: none; }
.section { display: flex; flex-direction: column; gap: 16px; }
.section h2 { margin: 0 0 4px; font-size: 24px; font-weight: 500; line-height: 1.3; text-wrap: balance; }
.section p, .section ol, .section ul { margin: 0; max-width: 68ch; }
.section ol { padding-left: 1.3em; display: flex; flex-direction: column; gap: 6px; }
.section .card h2 { font-size: 16px; margin: 0; }
.section .card p { margin: 3px 0 0; }
.dashes { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.dashes li { position: relative; padding-left: 1.2em; }
.dashes li::before { content: "–"; position: absolute; left: 0; }
.inline { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--soft); }
.inline:hover { text-decoration-color: var(--ink); }
figure { margin: 4px 0 0; display: flex; flex-direction: column; gap: 8px; }
figure img { border-radius: 8px; }
.todo { color: #c62828; }
.placeholder {
  border: 1px dashed var(--soft); border-radius: var(--radius); background: rgba(0,0,0,.02);
  min-height: 240px; display: grid; place-items: center; padding: 24px; text-align: center;
  font-size: 13px; color: var(--muted);
}

/* Embedded film or walkthrough (YouTube / Vimeo), kept at 16:9 */
.embed { position: relative; width: 100%; aspect-ratio: 16 / 9; border-radius: var(--radius); overflow: hidden; background: #111; }
.embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* A tall photo beside a 16:9 video, sized so both end up the same height */
.media-row { display: grid; grid-template-columns: minmax(0, 0.316fr) minmax(0, 1fr); gap: 12px; align-items: stretch; }
.media-row img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius); }
/* Feature list: short heading + one line each */
.features { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; margin: 8px 0; }
.features h3 { margin: 0 0 6px; font-size: 16px; font-weight: 500; }
.features p { font-size: 15px; color: var(--muted); }
/* Tall images sit at a readable size instead of filling the column */
figure.portrait { max-width: 420px; }
.print figure.portrait { max-width: none; }
.print .stack { display: flex; flex-direction: column; gap: 12px; justify-content: center; }
.print { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.print figure { margin: 0; }
.print .wide { grid-column: 1 / -1; }
.print img { display: block; width: 100%; height: auto; border-radius: var(--radius); }
.swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.swatch { display: flex; flex-direction: column; gap: 8px; font-size: 14px; }
.swatch i { display: block; height: 110px; border-radius: 8px; }
.swatch small { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }

/* ---------- Simple pages ---------- */
.simple { display: flex; flex-direction: column; gap: 20px; font-size: 16px; }
.simple p { margin: 0; }
.simple a { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line); }
.simple a:hover { text-decoration-color: var(--ink); }

/* ---------- Dropdown ---------- */
.menu { position: relative; }
.menu-btn {
  font: inherit; font-size: 17px; font-weight: 500; color: var(--ink);
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 14px 10px 16px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--border); cursor: pointer;
}
.menu-btn svg { transition: transform .2s; }
.menu-btn[aria-expanded="true"] { background: var(--hover); border-color: var(--hover); }
.menu-btn[aria-expanded="true"] svg { transform: rotate(180deg); }
.menu-list {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 10;
  min-width: 170px; padding: 6px 16px; margin: 0; list-style: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 1px 2px var(--shadow), 0 4px 12px var(--shadow), 0 12px 28px var(--shadow);
}
.menu-list[hidden] { display: none; }
.menu-list li + li { border-top: 1px solid var(--line); }
.menu-list a { display: block; padding: 12px 0; font-size: 17px; }
.menu-list a:hover { color: var(--muted); }

/* ---------- Tablet ---------- */
@media (max-width: 1199.98px) {
  body { background: var(--surface); }
  .main { padding: 40px 32px 80px 40px; }
  .grid { grid-template-columns: minmax(0, 1fr); gap: 28px; }
}

/* ---------- Phone ---------- */
@media (max-width: 809.98px) {
  .shell { display: block; }
  .sidebar { display: none; }
  .topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    padding: 28px 24px 0;
  }
  .main { padding: 32px 24px 64px; }
  .grid { gap: 32px; }
  .card h2 { font-size: 19px; font-weight: 400; }
  .card p { font-size: 15px; }
  .case { gap: 48px; }
  .meta { grid-template-columns: 1fr; gap: 8px; font-size: 13px; color: var(--muted); }
  /* Lighter reading on phones: smaller type, shorter lines of text */
  .case { font-size: 15px; line-height: 1.5; }
  .lede { font-size: 15px; }
  .section { gap: 12px; }
  .section h2 { font-size: 20px; }
  .swatch i { height: 72px; }
  /* Extra paragraphs fold away behind "Read more" (added by nav.js) */
  .section.is-folded .more { display: none; }
  .read-more {
    align-self: flex-start; font: inherit; font-size: 14px; color: var(--muted);
    background: none; border: 0; padding: 0; cursor: pointer;
    text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--soft);
  }
  .swatches { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .print { grid-template-columns: 1fr; }
  .features { grid-template-columns: 1fr; gap: 16px; }
  .media-row { grid-template-columns: 1fr; }
  .media-row img { height: auto; max-height: 480px; }
}

.read-more { display: none; }
/* Words that depend on layout, e.g. "left/right" vs "top/bottom" when images stack */
.on-narrow { display: none; }
@media (max-width: 809.98px) { .on-wide { display: none; } .on-narrow { display: inline; } }
@media (max-width: 809.98px) { .read-more { display: inline; } }

/* Scroll reveal on case studies (classes added by nav.js) */
.has-reveal .reveal {
  opacity: 0; transform: translate3d(0, 48px, 0);
  transition: opacity .9s cubic-bezier(.22, .61, .36, 1), transform 1.1s cubic-bezier(.16, 1, .3, 1);
  will-change: opacity, transform;
}
.has-reveal .reveal.is-done { will-change: auto; }
.has-reveal .reveal.is-in { opacity: 1; transform: none; }
/* Folded "Read more" text stays hidden on phones even after it has revealed */
.section.is-folded .more.reveal { display: none; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .tk-letter { animation: none !important; }
  a:hover > .wave span, a:focus-visible > .wave span, .name:hover .wave span, .name:focus-visible .wave span { transform: none; }
}

/* Plugin demo recording */
figure.demo video { width: 100%; height: auto; display: block; border-radius: 8px; background: var(--hover); aspect-ratio: 1920 / 1012; }

/* Pull to the next project */
.pull { display: flex; align-items: center; gap: 12px; margin-top: 20px; font-size: 13px; color: var(--muted); }
.pull-bar { flex: 1; height: 2px; border-radius: 2px; background: var(--line); overflow: hidden; }
.pull-bar i { display: block; height: 100%; background: var(--ink); transform: scaleX(0); transform-origin: left center; }
.pull-label { white-space: nowrap; transition: color .2s ease; }
.next-section.is-pulling .pull-label { color: var(--ink); }
.arriving .main { animation: arrive .7s cubic-bezier(.16, 1, .3, 1) both; }
@keyframes arrive { from { opacity: 0; transform: translate3d(0, 40px, 0); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .pull { display: none; }
  .arriving .main { animation: none; }
}
.leaving .main { opacity: 0; transform: translate3d(0, -24px, 0); transition: opacity .3s ease, transform .32s cubic-bezier(.7, 0, .84, 0); }

/* Dark mode toggle: sits at the foot of the sidebar; icon only in the phone header */
.theme-toggle {
  margin-top: auto; align-self: flex-start;
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 14px; color: var(--muted);
  background: none; border: 0; padding: 4px 0; cursor: pointer; transition: color .15s;
}
.theme-toggle:hover { color: var(--ink); }
.theme-toggle .i-sun { display: none; }
.theme-toggle[aria-pressed="true"] .i-sun { display: block; }
.theme-toggle[aria-pressed="true"] .i-moon { display: none; }
.theme-toggle svg { transition: transform .4s cubic-bezier(.34, 1.56, .64, 1); }
.theme-toggle:hover svg { transform: rotate(-20deg); }
.top-actions { display: flex; align-items: center; gap: 8px; }
.theme-toggle--icon {
  margin: 0; width: 44px; height: 44px; justify-content: center; padding: 0;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--ink);
}
.theme-toggle--icon .theme-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Colours ease across when the visitor switches themes */
.theme-anim, .theme-anim *, .theme-anim *::before, .theme-anim *::after {
  transition: background-color .35s ease, color .35s ease, border-color .35s ease, fill .35s ease !important;
}

/* Pull to the previous project: hidden above the page, revealed as it stretches down */
.pull-prev {
  position: absolute; top: -52px; left: 50%; transform: translateX(-50%);
  width: min(873px, calc(100% - 88px));
  display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--muted);
  opacity: 0; pointer-events: none;
}
.pull-prev .pull-bar { order: 2; }
.pull-prev .pull-bar i { transform-origin: right center; }
.pull-prev.is-pulling .pull-label { color: var(--ink); }
.arriving.arriving-prev .main { animation-name: arrive-prev; }
@keyframes arrive-prev { from { opacity: 0; transform: translate3d(0, -40px, 0); } to { opacity: 1; transform: none; } }
@media (max-width: 809.98px) { .pull-prev { width: calc(100% - 48px); } }
@media (prefers-reduced-motion: reduce) { .pull-prev { display: none; } }

/* Avoid lone words on the last line: browsers that support it rebalance paragraphs and headings
   (the build also ties each block's last two words together for the rest) */
p, li, figcaption { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }
