/* ============================================================
   CBIGO — fixed-viewport index site
   ============================================================ */

:root {
    --ink: #ffffff;
    --ink-dim: rgba(255, 255, 255, 0.55);
    --ink-faint: rgba(255, 255, 255, 0.3);
    --rule: rgba(255, 255, 255, 0.14);
    --bg: #05060a;

    --pad: clamp(18px, 2.6vw, 45px);
    --fs: clamp(17px, 1.36vw, 22px);   /* 80% of the previous scale */
    --lh: 1.7;
}

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

html, body {
    height: 100%;
    width: 100%;
    overflow: hidden;                 /* 첫 화면에 스크롤 없음 */
    overscroll-behavior: none;
}

body {
    background: var(--bg);
    color: var(--ink);
    font-family: 'Space Mono', ui-monospace, monospace;
    font-size: var(--fs);
    line-height: var(--lh);
    -webkit-font-smoothing: antialiased;
    cursor: none;
}

a { color: inherit; text-decoration: none; cursor: none; }
ul, ol { list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: none; }
::selection { background: var(--ink); color: var(--bg); }

/* Hide every native scrollbar; panels scroll silently. */
* { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ============================================================
   Backdrop — WebGL refraction
   ============================================================ */

.backdrop {
    position: fixed;
    inset: 0;
    z-index: 0;
    background: var(--bg);
}
#backdrop-canvas {
    display: block;
    width: 100%;
    height: 100%;
}

.grain {
    position: fixed;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    opacity: 0.05;
    background: url('data:image/svg+xml;utf8,%3Csvg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"%3E%3Cfilter id="n"%3E%3CfeTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="3" stitchTiles="stitch"/%3E%3C/filter%3E%3Crect width="100%25" height="100%25" filter="url(%23n)"/%3E%3C/svg%3E');
}

.vignette {
    position: fixed;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background:
        radial-gradient(128% 98% at 50% 45%, transparent 46%, rgba(0, 0, 0, 0.415) 100%),
        linear-gradient(to bottom, rgba(0, 0, 0, 0.305) 0%, transparent 22%, transparent 76%, rgba(0, 0, 0, 0.34) 100%);
}

/* Reading scrim — only while a page is open, so the index stays clean. */
.vignette::after {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 0.55s ease;
    background: linear-gradient(102deg,
        rgba(4, 5, 10, 0.90) 0%,
        rgba(4, 5, 10, 0.82) 38%,
        rgba(4, 5, 10, 0.42) 68%,
        rgba(4, 5, 10, 0.05) 88%,
        transparent 100%);
}
body:not([data-view="index"]) .vignette::after { opacity: 1; }

/* ============================================================
   Cursor
   ============================================================ */

.cursor-dot,
.cursor-ring {
    position: fixed;
    top: 0; left: 0;
    z-index: 10000;
    pointer-events: none;
    transform: translate(-50%, -50%);
    mix-blend-mode: difference;
}
.cursor-dot {
    width: 6px; height: 6px;
    background: #fff;
    border-radius: 50%;
}
.cursor-ring {
    width: 34px; height: 34px;
    border: 1px solid rgba(255, 255, 255, 0.45);
    border-radius: 50%;
    transition: width 0.22s cubic-bezier(0.2, 1, 0.2, 1),
                height 0.22s cubic-bezier(0.2, 1, 0.2, 1),
                background 0.22s ease,
                border-color 0.22s ease;
}
body.hovering .cursor-ring {
    width: 64px; height: 64px;
    background: #fff;
    border-color: transparent;
}

/* ============================================================
   Loading — there is no overlay. The backdrop starts empty and the
   paint rises into it; the UI is held back until that finishes.
   ============================================================ */

body.is-loading .stage,
body.is-loading .music-ctrl {
    opacity: 0;
    pointer-events: none;
}
.stage, .music-ctrl { transition: opacity 0.8s ease; }

/* ============================================================
   Stage — exactly one viewport, never scrolls
   ============================================================ */

.stage {
    position: fixed;
    inset: 0;
    z-index: 4;
    padding: var(--pad);
}

/* ============================================================
   Index (the nav itself is the home screen)
   ============================================================ */

.index {
    position: absolute;
    top: var(--pad);
    left: var(--pad);
    z-index: 6;
    display: flex;
    flex-direction: column;
    opacity: 0;
    animation: rise 1.1s cubic-bezier(0.2, 1, 0.2, 1) 0.25s forwards;
}
@keyframes rise {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

.brand {
    font-weight: 700;
    letter-spacing: 0.02em;
    margin-bottom: 2.2em;
}

.index-list { display: flex; flex-direction: column; gap: 1.15em; }

.index-list a {
    position: relative;
    display: inline-block;
    width: fit-content;
    transition: opacity 0.3s ease, letter-spacing 0.4s cubic-bezier(0.2, 1, 0.2, 1);
}
.index-list a::after {
    content: '';
    position: absolute;
    left: 0; bottom: -2px;
    width: 100%; height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.4s cubic-bezier(0.2, 1, 0.2, 1);
}
.index-list a:hover::after,
.index-list a.active::after {
    transform: scaleX(1);
    transform-origin: left;
}
.index-list a:hover { letter-spacing: 0.06em; }

/* When a page is open the index stays put but recedes slightly. */
body:not([data-view="index"]) .index-list a:not(.active) { opacity: 0.4; }

/* ============================================================
   Close button
   ============================================================ */

.close-btn {
    position: absolute;
    top: var(--pad);
    right: var(--pad);
    z-index: 7;
    width: 2.4em;
    height: 2.4em;
    display: grid;
    place-items: center;
    opacity: 0;
    pointer-events: none;
    transform: scale(0.7) rotate(-45deg);
    transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.2, 1, 0.2, 1);
}
body:not([data-view="index"]) .close-btn {
    opacity: 1;
    pointer-events: auto;
    transform: none;
}
.close-btn:hover { transform: rotate(90deg); }

/* ============================================================
   Scroll indicator — shown only when the open page overflows
   ============================================================ */

.scroll-rail {
    position: fixed;
    right: calc(var(--pad) * 0.6);
    top: calc(var(--pad) + 4.2em);
    bottom: calc(var(--pad) + 3em);
    width: 2px;
    z-index: 7;
    background: rgba(255, 255, 255, 0.14);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.45s ease;
}
.scroll-rail.on { opacity: 1; }

.scroll-thumb {
    position: absolute;
    left: 0;
    width: 2px;
    min-height: 26px;
    background: rgba(255, 255, 255, 0.55);
}


/* ============================================================
   Pages
   ============================================================ */

.pages {
    position: absolute;
    inset: var(--pad);
    z-index: 5;
    pointer-events: none;
}

/* Outgoing pages vanish instantly; only the incoming one animates.
   A crossfade would let two pages' text overlap in the same column. */
.page {
    position: absolute;
    inset: 0;
    /* leave the index column clear on the left */
    padding-left: clamp(90px, 14vw, 300px);
    padding-top: 2.6em;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}
.page.active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    animation: pageIn 0.6s cubic-bezier(0.2, 1, 0.2, 1);
}
@keyframes pageIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}

/* The only scrollable thing on the site — and only when a page overflows. */
.page-scroll {
    height: 100%;
    overflow-y: auto;
    padding-right: clamp(26px, 3vw, 54px);
    padding-bottom: 3em;
    -webkit-overflow-scrolling: touch;
}

/* Staggered entrance for a page's children */
.page.active .stagger {
    animation: rise 0.85s cubic-bezier(0.2, 1, 0.2, 1) backwards;
}

.link {
    position: relative;
    border-bottom: 1px solid var(--rule);
    transition: border-color 0.3s ease;
}
.link:hover { border-color: var(--ink); }

/* ============================================================
   Works
   ============================================================ */

.pub-list {
    display: flex;
    flex-direction: column;
    max-width: min(100%, 74ch);
}

.pub-item {
    display: flex;
    gap: 1.6em;
    padding: 1.7em 0;
    border-top: 1px solid var(--rule);
    transition: opacity 0.35s ease;
}
.pub-item:last-child { border-bottom: 1px solid var(--rule); }

/* dim siblings on hover, so the hovered one reads as focused */
.pub-list:hover .pub-item { opacity: 0.38; }
.pub-list:hover .pub-item:hover { opacity: 1; }

.pub-index {
    flex: none;
    opacity: 0.4;
    font-size: 0.85em;
    padding-top: 0.35em;
}

.pub-body { display: flex; flex-direction: column; gap: 0.45em; }

.pub-title {
    font-size: clamp(0.85rem, 1.7vw, 1.32rem);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.01em;
    transition: transform 0.45s cubic-bezier(0.2, 1, 0.2, 1);
}
.pub-item:hover .pub-title { transform: translateX(6px); }

.pub-subtitle { font-size: 0.82em; color: var(--ink-dim); line-height: 1.65; }

.pub-authors { font-size: 0.74em; color: var(--ink-faint); line-height: 1.65; }
.pub-authors strong { color: var(--ink-dim); font-weight: 700; }

.pub-meta {
    margin-top: 0.35em;
    font-size: 0.82em;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    opacity: 0.45;
}

/* Floating preview image */
#hover-img {
    position: fixed;
    top: 0; left: 0;
    z-index: 9000;               /* above .stage(4)/.grain(3)/.vignette(2) */
    width: clamp(300px, 30vw, 620px);
    border-radius: 4px;
    object-fit: cover;
    opacity: 0;
    pointer-events: none;
    transform: translate(24px, -50%) scale(0.94);
    transition: opacity 0.35s ease, transform 0.7s cubic-bezier(0.2, 1, 0.2, 1);
    box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6);
}
#hover-img.show {
    opacity: 0.9;
    transform: translate(40px, -50%) scale(1);
}

/* ============================================================
   About
   ============================================================ */

/* Wide enough to hold the intro on two lines. */
.lede {
    max-width: min(100%, 96ch);
    font-size: clamp(0.8rem, 1.44vw, 1.08rem);
    line-height: 1.6;
    margin-bottom: 3em;
}

.cv {
    display: flex;
    flex-direction: column;
    max-width: min(100%, 72ch);
    margin-bottom: 3em;
}
.cv li {
    display: flex;
    gap: 1.6em;
    padding: 1.4em 0;
    border-top: 1px solid var(--rule);
}
.cv li:last-child { border-bottom: 1px solid var(--rule); }

.cv-date {
    flex: none;
    width: 11em;
    opacity: 0.45;
    font-size: 0.9em;
    padding-top: 0.15em;
}
.cv-body { display: flex; flex-direction: column; gap: 0.3em; }
.cv-role { font-weight: 700; }
.cv-org { font-size: 0.85em; color: var(--ink-dim); }

.socials {
    display: flex;
    gap: 0.9em;
    font-size: 1.7em;
}
.socials a {
    opacity: 0.55;
    transition: opacity 0.3s ease, transform 0.3s ease;
}
.socials a:hover { opacity: 1; transform: translateY(-3px); }

/* ============================================================
   Interests
   ============================================================ */

.areas {
    display: flex;
    flex-direction: column;
    max-width: 100%;
}
/* Number in its own column; name and description stack beside it, so the
   description gets the full width instead of a narrow third column. */
.area {
    display: grid;
    grid-template-columns: 3em minmax(0, 1fr);
    gap: 0.45em 1.4em;
    align-items: baseline;
    padding: 1.5em 0;
    border-top: 1px solid var(--rule);
    transition: opacity 0.35s ease;
}
.area-num  { grid-column: 1; grid-row: 1; }
.area-name { grid-column: 2; grid-row: 1; }
.area-desc { grid-column: 2; grid-row: 2; }
.area:last-child { border-bottom: 1px solid var(--rule); }

/* Interests entries are read, not clicked — so they do not react to hover. */

.area-num { opacity: 0.4; font-size: 0.85em; }

.area-name {
    font-size: 1em;
    font-weight: 700;
    line-height: 1.3;
}

/* Wide enough that these descriptions land on two lines, not three. */
.area-desc {
    font-size: 0.78em;
    color: var(--ink-dim);
    line-height: 1.7;
    max-width: 100ch;
}

/* ============================================================
   Contact
   ============================================================ */

/* Text first, portrait underneath. */
.contact {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(2em, 4vw, 3.4em);
}

.portrait {
    position: relative;
    order: 1;
    flex: none;
    width: clamp(184px, 21vw, 288px);
    aspect-ratio: 1;
    display: grid;
    place-items: center;
}
.portrait img {
    width: 63%;
    height: 63%;
    border-radius: 50%;
    object-fit: cover;
    filter: grayscale(100%);
    transition: filter 0.6s ease, transform 0.6s cubic-bezier(0.2, 1, 0.2, 1);
}
.portrait:hover img { filter: grayscale(0%); transform: scale(1.04); }

.portrait-ring {
    position: absolute;
    inset: 0;
    animation: spin 18s linear infinite;
    pointer-events: none;
}
.portrait-ring svg { width: 100%; height: 100%; overflow: visible; }
.portrait-ring text {
    font-family: 'Space Mono', monospace;
    font-size: 7px;
    letter-spacing: 0.06em;
    fill: var(--ink-faint);
    transition: fill 0.5s ease;
}
.portrait:hover .portrait-ring text { fill: var(--ink); }
@keyframes spin { to { transform: rotate(360deg); } }

.contact-body { order: 2; display: flex; flex-direction: column; gap: 1.4em; }

.email {
    font-size: clamp(1.1rem, 3vw, 2.3rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.2;
    word-break: break-word;
    width: fit-content;
    transition: opacity 0.35s ease;
}
.email:hover { opacity: 0.65; }

/* ============================================================
   Persistent chrome
   ============================================================ */

.music-ctrl {
    position: fixed;
    left: var(--pad);
    bottom: var(--pad);
    z-index: 6;
    width: 2.8em;
    height: 2.8em;
    display: grid;
    place-items: center;
    border: 1px solid var(--rule);
    border-radius: 50%;
    font-size: 0.8em;
    opacity: 0;
    transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease;
    animation: rise 1.1s cubic-bezier(0.2, 1, 0.2, 1) 0.7s forwards;
}
.music-ctrl:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.music-ctrl.playing { border-color: rgba(255, 255, 255, 0.6); }

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width: 860px) {
    .index {
        flex-direction: row;
        align-items: baseline;
        gap: 1.4em;
        right: var(--pad);
        flex-wrap: wrap;
    }
    .brand { margin-bottom: 0; width: 100%; }
    .index-list { flex-direction: row; gap: 1.3em; flex-wrap: wrap; }

    .page { padding-left: 0; padding-top: 5.5em; }
    /* Right padding clears the scroll rail; match it on the left so centred
       content sits on the viewport's centre, not offset from it. */
    .page-scroll { padding-left: 1.6em; padding-right: 1.6em; padding-bottom: 6.5em; }

    /* The nav is a row across the top here, so the close button moves out
       from under it — and the rail lifts clear of the button. */
    .close-btn { top: auto; bottom: var(--pad); right: var(--pad); }
    .scroll-rail { bottom: calc(var(--pad) + 4.2em); }

    .area { grid-template-columns: 2.4em 1fr; }
    .area-desc { grid-column: 2; }

    .cv li { flex-direction: column; gap: 0.5em; }
    .cv-date { width: auto; }

    /* Contact reads better centred once the panel is full-width. */
    .contact { align-items: center; }
    .contact-body { align-items: center; text-align: center; }
    .socials { justify-content: center; }

    #hover-img { display: none !important; }
}


/* Touch devices: no custom cursor */
@media (hover: none) and (pointer: coarse) {
    .cursor-dot, .cursor-ring { display: none !important; }
    body, a, button { cursor: auto; }
    a, button, .hover-target { cursor: pointer; }
    .pub-list:hover .pub-item,
    .areas:hover .area { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
