/*
Theme Name: Youngmi Hwang
Theme URI: https://youngmihwang.com/
Author: Youngmi Hwang
Description: Bilingual one-page portfolio theme for violinist Youngmi Hwang — staged
  loading, 3D hero filmstrip, scroll-morphing About, and a video playlist. English is
  the front page; Korean is the "Korean (한국어)" page template. Contact is handled by
  Contact Form 7.
Version: 2.1.0
Requires at least: 6.0
Tested up to: 6.6
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: youngmi-hwang
*/

/* Generated from index.html + ko.html by build_theme.py — edit the source, not this file. */

:root{
    --paper: #EFE8D8;
    --paper-deep: #E6DCC6;
    --ink: #201A14;
    --ink-soft: #4A4136;
    --wine: #6B1F2E;
    --wine-deep: #521622;
    --spruce: #2B3A28;
    --spruce-deep: #1E2A1C;
    --gold: #A8823C;
    --gold-soft: #C9AD73;
    --line: #D8CDB3;
    --line-on-dark: rgba(201,173,115,0.35);

    --display: 'Fraunces', serif;
    --body: 'Literata', serif;
    --mono: 'Space Mono', monospace;

    --max: 780px;
    --edge: clamp(24px, 6vw, 96px);
    --hero-tail: 22svh;        /* how far the hero reaches over the About section */

    /* One romantic maroon night, shared by every dark section so the seams match
       by construction rather than by two gradients happening to agree. */
    --night-1: #2C0E19;        /* oxblood, lifted */
    --night-2: #1D0910;        /* burgundy velvet */
    --night-3: #120509;        /* deepest — the colour every joint lands on */
    --night-lift: #250B14;     /* the tone sections hand off to each other  */
    --glow-wine: rgba(150,36,70,0.20);   /* restrained rose bloom */
    --glow-plum: rgba(84,36,92,0.16);    /* cool counterpoint so it isn't flat */
    --glow-gold: rgba(168,130,60,0.12);
  }

  *{ box-sizing: border-box; }
  html{ scroll-behavior: smooth; }
  @media (prefers-reduced-motion: reduce){
    html{ scroll-behavior: auto; }
    *{ animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  }

  .skip-link{
    position:absolute; left:-9999px; top:0; z-index:100;
    background: var(--paper); color: var(--ink);
    padding: 12px 20px; font-family: var(--mono); font-size: 12.5px;
    text-decoration:none;
  }
  .skip-link:focus{ left:0; }

  /* ---------- Nav ---------- */
  .nav{
    position: fixed;
    top:0; left:0; right:0;
    z-index: 50;
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding: 18px var(--edge);
    font-family: var(--mono);
    font-size: 12.5px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--paper);
    background: transparent;
    transition: background .35s ease, color .35s ease, box-shadow .35s ease, backdrop-filter .35s ease;
  }
  .nav.scrolled{
    background: rgba(239,232,216,0.92);
    -webkit-backdrop-filter: blur(6px);   /* Safari needs the prefix before 18 */
            backdrop-filter: blur(6px);
    color: var(--ink);
    box-shadow: 0 1px 0 var(--line);
  }
  .nav-name{ font-family: var(--display); font-size: 15px; letter-spacing: 0; text-transform: none; }
  .nav-links{ display:flex; gap: 26px; list-style:none; margin:0; padding:0; }
  .nav-links a{ color: inherit; text-decoration:none; opacity: .82; }
  .nav-links a:hover{ opacity: 1; }
  .nav-toggle{
    display:none;
    background:none; border:none; color: inherit; font-family: var(--mono);
    font-size: 12.5px; letter-spacing: 0.1em; text-transform: uppercase; cursor:pointer;
  }
  @media (max-width: 720px){
    .nav-links{
      position: fixed; top: 56px; right: var(--edge); left: var(--edge);
      flex-direction: column; gap: 4px;
      background: var(--paper); color: var(--ink);
      border: 1px solid var(--line);
      padding: 14px 18px;
      display: none;
    }
    .nav-links.open{ display:flex; }
    .nav-links a{ color: var(--ink); padding: 8px 0; }
    .nav-toggle{ display:block; }
  }

  /* ---------- Scroll reveal ---------- */
  .reveal{ opacity: 0; transform: translateY(22px); transition: opacity .7s ease, transform .7s ease; }
  .reveal.in-view{ opacity: 1; transform: translateY(0); }
  @media (prefers-reduced-motion: reduce){
    .reveal{ opacity: 1; transform: none; }
  }

  body{
    margin:0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--body);
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
  }

  a{ color: var(--wine); text-decoration-thickness: 1px; text-underline-offset: 3px; }
  a:hover{ color: var(--wine-deep); }
  a:focus-visible, button:focus-visible{
    outline: 2px solid var(--gold);
    outline-offset: 3px;
  }

  h1,h2,h3{ font-family: var(--display); font-weight: 500; margin: 0; color: inherit; }

  .eyebrow, .opus{
    font-family: var(--mono);
    text-transform: uppercase;
    letter-spacing: 0.18em;
    font-size: 12.5px;
  }

  /* ---------- Hero: drifting filmstrip ---------- */
  /* The hero runs one "tail" taller than the viewport and About is pulled up under
     it, so the lower cards genuinely sit on top of the About section instead of
     stopping at a seam. Only the first 100svh carries the hero's own backdrop. */
  .hero{
    position: relative;
    min-height: calc(100svh + var(--hero-tail));
    background: transparent;
    color: var(--paper);
    overflow: hidden;          /* contains the 7000px-wide filmstrip tracks */
    z-index: 2;
  }
  /* Spans the WHOLE hero (incl. tail) and only dissolves across the tail — where
     About is actually behind it. Fading any earlier would reveal the paper <body>. */
  .hero-bg{
    position:absolute; inset:0; z-index:0;
    background-color: var(--night-3);
    background-image:
      /* settles everything onto the flat joint tone before the tail begins,
         so the crossfade into About is between two identical colours */
      linear-gradient(180deg, transparent 58svh, var(--night-3) 97svh),
      radial-gradient(70% 55% at 18% 82%, var(--glow-plum) 0%, transparent 60%),
      radial-gradient(85% 65% at 68% 40%, var(--glow-wine) 0%, transparent 62%),
      radial-gradient(120% 100% at 24% 26%, var(--night-1) 0%, var(--night-2) 52%, var(--night-3) 100%);
    background-size: 100% 100svh, 100% 100svh, 100% 100svh, 100% 100svh;
    background-repeat: no-repeat;
    -webkit-mask-image: linear-gradient(180deg, #000 100svh, transparent 100%);
            mask-image: linear-gradient(180deg, #000 100svh, transparent 100%);
  }
  .hero::before{ /* top fade + edge vignette above the cards */
    content:"";
    position:absolute; inset:0;
    z-index:3; pointer-events:none;
    background:
      linear-gradient(180deg, rgba(16,11,8,0.9) 0%, transparent 22%),
      radial-gradient(78% 70% at 55% 50%, transparent 55%, rgba(0,0,0,0.42) 100%);
    background-size: 100% 100svh, 100% 100svh;
    background-repeat: no-repeat, no-repeat;
    /* gone before the tail, so it can't tint the handoff */
    -webkit-mask-image: linear-gradient(180deg, #000 78svh, transparent 99svh);
            mask-image: linear-gradient(180deg, #000 78svh, transparent 99svh);
  }

  /* horizontal 3D filmstrip */
  .filmstrip-stage{
    position:absolute; inset:0; z-index:1; pointer-events:none;
    perspective: 1300px;
    perspective-origin: 56% 50%;
    /* fade the cards out across the tail so they melt into About rather than
       ending on a line — masking the cards keeps About's own copy untouched */
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 12%, #000 74%, transparent 100%);
            mask-image: linear-gradient(180deg, transparent 0%, #000 12%, #000 74%, transparent 100%);
  }
  .film-world{ position:absolute; inset:0; transform-style:preserve-3d; }
  .film-row{
    position:absolute; left:0; top:var(--y);
    width:100%; height:0;
    transform: translateZ(var(--z, 0px));
    transform-style: preserve-3d;
  }
  .film-track{
    position:absolute; left:0; top:0;
    display:flex; align-items:flex-start;
    gap: var(--gap, 120px);
    will-change: transform;
  }
  .frame-wrap{
    flex:0 0 auto;
    width: var(--w, 220px);
    margin-left: var(--mx, 0px);
    transform: translateY(calc(-50% + var(--dy, 0px)));
  }
  .frame{
    position:relative;
    width:100%;
    aspect-ratio: 4/5;
    margin:0; padding:0; border:0;
    border-radius:18px; overflow:hidden;
    background:#0d0a08;
    box-shadow: 0 30px 60px rgba(0,0,0,0.55);
    outline: 1px solid rgba(201,173,115,0.12);
    outline-offset:-1px;
    transform-origin:center;
    will-change: transform, filter, opacity;
    pointer-events:none;
    /* transform + filter are driven per-frame by JS; only these transition */
    transition: box-shadow .45s ease, outline-color .45s ease;
    /* resting state until the focus pass takes over */
    transform: scale(.95);
    filter: blur(4px) brightness(.7);
  }
  .frame.is-hot{
    outline-color: rgba(201,173,115,0.5);
    box-shadow: 0 48px 96px rgba(0,0,0,0.62);
  }

  /* carousel controls */
  .film-ui{
    position:absolute; z-index:5;
    right: var(--edge); bottom: calc(var(--hero-tail) + 42px);
    display:flex; align-items:center;
    color: var(--paper);
    pointer-events:none;
  }
  .film-count{ font-family:var(--mono); font-size:13px; letter-spacing:.14em; text-align:center; opacity:.75; }
  .film-count .cur{ color:var(--gold-soft); }

  /* the whole hero is draggable */
  .hero{ cursor: grab; }
  .hero.dragging, .hero.dragging *{ cursor: grabbing; }
  .hero-cta{ cursor: pointer; }
  .frame img{
    width:100%; height:100%; object-fit:cover; display:block;
    /* grade so bright studio shots sit inside the moody palette */
    filter: saturate(0.82) contrast(1.07) brightness(0.95) sepia(0.14);
  }
  .frame::after{
    content:""; position:absolute; inset:0;
    background:
      linear-gradient(180deg, transparent 52%, rgba(0,0,0,0.38)),
      linear-gradient(0deg, rgba(74,38,26,0.20), rgba(74,38,26,0.20));
    pointer-events:none;
  }

  /* text overlay */
  .hero-inner{
    position:relative; z-index:4;
    min-height:100svh;
    display:flex; flex-direction:column; justify-content:center;
    padding: calc(var(--edge) + 30px) var(--edge) var(--edge);
    max-width: 680px;
    pointer-events:none;
  }
  .hero-inner > *{ pointer-events:auto; }
  .hero .eyebrow{ color: var(--gold-soft); margin-bottom: 20px; }
  .hero h1{
    font-size: clamp(54px, 9.5vw, 122px);
    line-height: 0.9;
    letter-spacing: -0.02em;
    text-shadow: 0 2px 50px rgba(0,0,0,0.55);
  }
  .hero-sub{
    font-family: var(--body);
    font-size: clamp(16px, 1.8vw, 19px);
    color: rgba(239,232,216,0.82);
    margin: 24px 0 38px;
    max-width: 42ch;
    line-height: 1.55;
  }
  .hero-cta{
    display:inline-flex; align-items:center; gap:16px;
    text-decoration:none; color:var(--paper);
  }
  .hero-cta .circle{
    width:60px; height:60px; border-radius:50%;
    border:1px solid rgba(239,232,216,0.4);
    background-color: rgba(239,232,216,0.04);
    display:flex; align-items:center; justify-content:center;
    font-size:20px; line-height:1;
    transition: background-color .38s ease, border-color .38s ease,
                box-shadow .38s ease, transform .5s cubic-bezier(.16,1,.3,1);
  }
  .hero-cta .label{
    font-family:var(--mono); font-size:12.5px; letter-spacing:0.14em; text-transform:uppercase;
    color: rgba(239,232,216,0.78);
    transition: color .38s ease, transform .5s cubic-bezier(.16,1,.3,1);
  }
  /* The old hover flooded the circle with flat --wine, which killed the arrow's
     contrast and left the label behind. Now both halves answer: the disc lifts
     onto a gold rim over a translucent wine, and the arrow keeps its paper. */
  .hero-cta:hover .circle,
  .hero-cta:focus-visible .circle{
    background-color: rgba(107,31,46,0.68);
    border-color: var(--gold-soft);
    color: var(--paper);
    transform: translateY(4px);
    box-shadow: 0 12px 28px rgba(0,0,0,0.38), 0 0 0 6px rgba(201,173,115,0.07);
  }
  .hero-cta:hover .label,
  .hero-cta:focus-visible .label{
    color: var(--gold-soft);
    transform: translateX(3px);
  }
  .hero-cta:active .circle{ transform: translateY(6px); }
  @media (prefers-reduced-motion: reduce){
    .hero-cta .circle, .hero-cta .label{ transition-duration: .001ms; }
    .hero-cta:hover .circle, .hero-cta:focus-visible .circle,
    .hero-cta:active .circle{ transform: none; }
    .hero-cta:hover .label, .hero-cta:focus-visible .label{ transform: none; }
  }

  @media (max-width: 820px){
    .filmstrip-stage{ perspective-origin: 50% 50%; }
    .row-back { --y: 42%; }
    .row-mid  { --y: 66%; }
    .row-front{ --y: 90%; }
    .hero-inner{ justify-content:flex-start; padding-top: 104px; max-width:none; }
    .hero h1{ font-size: clamp(48px, 15vw, 92px); }
    .film-ui{ bottom: 22px; }
  }

  /* ---------- Sections (paper) ---------- */
  .section{
    padding: 108px var(--edge);
  }
  .section-inner{
    max-width: var(--max);
    margin: 0 auto;
  }
  .section.dark{
    background: none;
    color: var(--paper);
  }

  /* ---------- One unbroken night behind About + Playlist + Teaching ----------
     Painting per-section put a glow at each section's own top edge, which is
     exactly what read as a separator band. One backdrop = no seams, by design. */
  .night{
    position: relative;
    z-index: 1;
    margin-top: calc(var(--hero-tail) * -1);   /* slide up under the hero's tail */
    color: var(--paper);
    background:
      radial-gradient(48% 15% at 76% 9%,  var(--glow-plum) 0%, transparent 64%),
      radial-gradient(52% 13% at 20% 27%, var(--glow-wine) 0%, transparent 62%),
      radial-gradient(46% 12% at 86% 46%, var(--glow-plum) 0%, transparent 62%),
      radial-gradient(54% 14% at 26% 64%, var(--glow-wine) 0%, transparent 62%),
      radial-gradient(46% 12% at 80% 86%, var(--glow-gold) 0%, transparent 62%),
      linear-gradient(180deg,
        var(--night-3)     0%,
        var(--night-3)     5%,
        var(--night-2)    22%,
        var(--night-1)    44%,
        var(--night-2)    68%,
        var(--night-1)    86%,
        var(--night-lift) 100%);
  }
  .section.dark .opus{ color: var(--gold-soft); }
  .section.dark h2{ color: var(--paper); }
  .section.dark .staff-divider{ background: var(--line-on-dark); }
  .section.dark a{ color: var(--gold-soft); }
  .section.dark a:hover{ color: var(--paper); }

  .opus{ color: var(--wine); margin-bottom: 10px; display:block; }

  .section h2{
    font-size: clamp(30px, 4vw, 42px);
    margin-bottom: 22px;
  }

  .staff-divider{
    height: 1px;
    background: var(--line);
    margin: 0 0 34px;
    position: relative;
  }
  .nav-lang a{ color: var(--gold); }
  .nav-lang a::after{ display: none; }

  .staff-divider::after{
    content:"";
    position:absolute; left:0; top:-1px;
    width: 46px; height: 3px;
    background: var(--gold);
  }

  /* ---------- About: glyph morph (note → violin) ---------- */
  /* continues the hero's night rather than cutting to paper */
  .about-morph{
    position: relative;
    background: none;          /* the .night wrapper paints for all three sections */
    color: var(--paper);
  }
  .about-morph .opus{ color: var(--gold-soft); }
  .about-morph h2{ color: var(--paper); }
  .about-morph .staff-divider{ background: var(--line-on-dark); }
  .about-morph .bio{ color: rgba(239,232,216,0.87); }
  .about-morph .bio strong{ color: var(--paper); }
  .about-morph .morph-cap{ color: rgba(239,232,216,0.48); }
  .about-morph .morph-rail{ background: var(--line-on-dark); }
  .morph-wrap{ position: relative; height: 380vh; }
  .morph-sticky{
    position: sticky; top: 0;
    height: 100svh;
    overflow: hidden;
  }
  #morphCanvas{ position:absolute; inset:0; width:100%; height:100%; display:block; }
  .morph-copy{
    position:absolute; z-index:2;
    top: clamp(80px, 13vh, 150px); left:50%;
    transform: translateX(-50%);
    text-align:center; pointer-events:none; width:100%;
    padding: 0 var(--edge);
  }
  .morph-copy .opus{ margin-bottom: 8px; }
  .morph-copy .morph-title{ font-family: var(--display); font-weight:500; color: var(--paper);
    font-size: clamp(30px, 4vw, 42px); margin: 0 0 16px; }
  .morph-cap{
    font-family: var(--mono); font-size: 11.5px; letter-spacing:.18em;
    text-transform:uppercase; color: var(--ink-soft); margin:0;
    transition: opacity .45s ease;
  }
  .morph-rail{
    position:absolute; z-index:2; left:50%; transform:translateX(-50%);
    bottom: 42px; width: min(240px, 40vw); height:1px; background: var(--line);
  }
  .morph-rail span{
    position:absolute; left:0; top:-1px; height:3px; width:0%;
    background: var(--gold); transition: width .1s linear;
  }
  /* bio column that rides in beside the violin */
  .morph-body{
    position:absolute; z-index:2;
    left: var(--edge); top: 9.5vh; bottom: 7.5vh;
    width: min(48%, 560px);
    overflow: hidden;
    opacity: 0;
  }
  .morph-body-inner{ will-change: transform; }
  .morph-body .opus{ margin-bottom: 8px; }
  .morph-body h2{ font-size: clamp(26px, 3.4vw, 38px); margin-bottom: 16px; }
  .morph-body .staff-divider{ margin-bottom: 22px; }
  /* prose sizing: light-on-dark serif needs more size and air than the paper
     sections do, or the hairlines close up and the column reads as texture */
  .morph-body .bio{
    font-size: clamp(16px, 1.62vw, 18.5px);
    line-height: 1.78;
    max-width: none;
    text-wrap: pretty;
  }
  .morph-body .bio + .bio{ margin-top: 24px; }

  /* the halls are the hook — let them arrive as a line, not as a sentence */
  .morph-body .bio-halls{
    font-family: var(--display);
    font-weight: 400;
    font-size: clamp(21px, 2.25vw, 27px);
    line-height: 1.34;
    color: var(--paper);
    margin: 0 0 18px;
    text-wrap: balance;
  }
  .morph-body .bio-lede{ color: rgba(239,232,216,0.95); }

  @media (max-width: 820px){
    .morph-body{ width: calc(100% - 2*var(--edge)); top: 13vh; }
    .morph-body .bio{ font-size: 16.5px; }
    .morph-body .bio-halls{ font-size: 22px; }
  }
  @media (max-width: 720px){ .morph-wrap{ height: 320vh; } }

  .bio{ max-width: 62ch; font-size: 18px; color: var(--ink-soft); }
  .bio strong{ color: var(--ink); font-weight: 500; }

  /* ---------- Recognition list ---------- */
  .cred-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; }
  .cred-list li{
    display:grid;
    grid-template-columns: 92px 1fr;
    gap: 20px;
    padding: 22px 0;
    border-bottom: 1px solid var(--line);
  }
  .cred-list li:first-child{ padding-top: 0; }
  .cred-list li:last-child{ border-bottom:none; }
  .cred-year{ font-family: var(--mono); font-size: 13px; color: var(--wine); padding-top: 3px; }
  .cred-title{ font-family: var(--display); font-size: 19px; margin: 0 0 4px; font-weight: 500; }
  .cred-detail{ color: var(--ink-soft); font-size: 15.5px; margin:0; }

  /* ---------- Education timeline ---------- */
  .edu-list{ list-style:none; margin:0; padding:0; }
  .edu-list li{ padding: 20px 0; border-bottom: 1px solid var(--line); }
  .edu-list li:last-child{ border-bottom:none; }
  .edu-degree{ font-family: var(--display); font-size: 19px; font-weight:500; margin:0 0 3px; }
  .edu-school{ font-family: var(--mono); font-size: 12.5px; text-transform: uppercase; letter-spacing:0.06em; color: var(--wine); margin: 0 0 6px; }
  .edu-note{ color: var(--ink-soft); font-size: 15.5px; margin:0; }

  /* ---------- Media ---------- */
  .video-card{
    position: relative;
    display:block;
    width: 100%;
    aspect-ratio: 16/9;
    border: 1px solid var(--line);
    margin-bottom: 10px;
    background: var(--ink) center/cover no-repeat;
    overflow: hidden;
  }
  .video-card .play-badge{
    position:absolute; top:50%; left:50%;
    transform: translate(-50%,-50%);
    width: 64px; height: 64px;
    border-radius: 50%;
    background: rgba(32,26,20,0.55);
    border: 1px solid rgba(239,232,216,0.8);
    display:flex; align-items:center; justify-content:center;
    color: var(--paper);
    font-size: 20px;
    transition: background .2s ease, transform .2s ease;
  }
  .video-card:hover .play-badge{ background: var(--wine); transform: translate(-50%,-50%) scale(1.06); }

  .embed-wrap{
    position: relative;
    width: 100%;
    aspect-ratio: 16/9;
    border: 1px solid var(--line);
    margin-bottom: 28px;
    background: var(--ink);
  }
  .embed-wrap iframe{
    position: absolute; inset:0;
    width: 100%; height: 100%;
    border: 0;
  }
  .embed-caption{
    font-family: var(--mono);
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--ink-soft);
    margin: -14px 0 34px;
  }

  .watch-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; margin-bottom: 40px; }
  .watch-card{
    display:block;
    border: 1px solid var(--line);
    padding: 22px;
    text-decoration:none;
    color: var(--ink);
    transition: border-color .25s ease, transform .25s ease;
  }
  .watch-card:hover{ border-color: var(--wine); transform: translateY(-3px); }
  .watch-card .play{
    width: 34px; height: 34px;
    border: 1px solid var(--wine);
    border-radius: 50%;
    display:flex; align-items:center; justify-content:center;
    margin-bottom: 16px;
    color: var(--wine);
    font-size: 12px;
  }
  .watch-card h3{ font-size: 17px; margin-bottom: 6px; }
  .watch-card p{ margin:0; font-size: 14px; color: var(--ink-soft); }

  /* ---------- Playlist ---------- */
  .playlist-sec{
    background: none;
    color: var(--paper);
  }
  .playlist-sec .opus{ color: var(--gold-soft); }
  .playlist-sec h2{ color: var(--paper); }
  .playlist-sec .staff-divider{ background: var(--line-on-dark); }
  .playlist-sec{ position: relative; overflow-x: clip; overflow-y: visible; }
  .playlist-sec > *{ position: relative; z-index: 1; }

  /* audio-reactive gooey aura, only alive while a track plays */
  .pl-aura{
    position:absolute; inset:-12%; z-index:0;
    /* Was `url(#plGoo) blur(44px)`. WebKit drops a filter list that mixes an SVG
       reference with a filter function, so Safari painted the blobs as five hard
       circles. The softness now comes from a plain blur plus each blob's own
       radial falloff — no SVG filter, identical in every engine. */
    filter: blur(clamp(30px, 4.4vw, 56px));
    opacity:0; transition: opacity 1.1s ease;
    pointer-events:none;
    /* the section clips overflow, so soften the blobs before they reach its
       edges — otherwise a blob can end on a straight line at the boundary */
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 14%, #000 82%, transparent 100%);
            mask-image: linear-gradient(180deg, transparent 0%, #000 14%, #000 82%, transparent 100%);
  }
  .pl-aura.is-on{ opacity:.74; }   /* the removed feColorMatrix used to boost alpha */
  .pl-aura i{
    position:absolute; display:block;
    border-radius:50%;
    /* background-color, not a gradient, so the per-track colour still animates */
    background-color: var(--aura, #6B1F2E);
    -webkit-mask-image: radial-gradient(closest-side, #000 28%, rgba(0,0,0,0) 100%);
            mask-image: radial-gradient(closest-side, #000 28%, rgba(0,0,0,0) 100%);
    will-change: transform;
    transition: background-color 1.6s ease;
  }
  .pl-aura i:nth-child(1){ left:12%; top:22%; width:22vw; height:22vw; }
  .pl-aura i:nth-child(2){ left:63%; top:14%; width:17vw; height:17vw; background-color: var(--aura2, #A8823C); }
  .pl-aura i:nth-child(3){ left:38%; top:52%; width:26vw; height:26vw; }
  .pl-aura i:nth-child(4){ left:76%; top:56%; width:15vw; height:15vw; background-color: var(--aura2, #A8823C); }
  .pl-aura i:nth-child(5){ left:24%; top:64%; width:19vw; height:19vw; }

  /* broad colour wash that re-tints the whole section per track */
  .pl-tint{
    position:absolute; inset:0; z-index:0; pointer-events:none;
    background-color: var(--tint, #6B1F2E);
    opacity:.20; mix-blend-mode: screen;
    -webkit-mask-image: radial-gradient(75% 65% at 50% 45%, #000 0%, transparent 78%);
            mask-image: radial-gradient(75% 65% at 50% 45%, #000 0%, transparent 78%);
    transition: background-color 1.6s ease, opacity 1.2s ease;
  }
  .playlist-sec.is-playing .pl-tint{ opacity:.34; }

  @media (prefers-reduced-motion: reduce){
    .pl-aura{ display:none; }
    .pl-tint{ transition: none; }
  }

  .pl-stage{
    position: relative;
    height: clamp(220px, 34vw, 400px);
    margin: clamp(28px, 5vh, 54px) 0 clamp(24px, 4vh, 44px);
    perspective: 1500px;
  }
  .pl-stage{ cursor: grab; touch-action: pan-y; }
  .pl-stage.is-drag{ cursor: grabbing; }
  .pl-rack{ position:absolute; inset:0; transform-style: preserve-3d; }
  .pl-rack.is-drag .pl-card{ transition: none; }
  .pl-card{
    position:absolute; top:50%; left:50%;
    width: clamp(250px, 44vw, 600px);
    aspect-ratio: 16/9;
    margin:0; padding:0; border:0;
    border-radius: 14px; overflow:hidden;
    background:#000; cursor:pointer;
    box-shadow: 0 30px 70px rgba(0,0,0,0.6);
    outline: 1px solid rgba(201,173,115,0.16); outline-offset:-1px;
    transition: transform .8s cubic-bezier(.16,1,.3,1), opacity .8s ease,
                filter .8s ease, outline-color .5s ease, box-shadow .6s ease;
    will-change: transform, opacity;
  }
  /* Hover zoom. The scale itself rides in the inline transform written by
     layout() — CSS cannot own it, since that string is rewritten on every drag
     frame — so this only carries the lift that comes with it. */
  .pl-card.is-hover{
    box-shadow: 0 46px 104px rgba(0,0,0,0.74);
    outline-color: rgba(201,173,115,0.42);
  }
  .pl-poster{ width:100%; height:100%; object-fit:cover; display:block; pointer-events:none; }
  .pl-video{
    position:absolute; inset:0; width:100%; height:100%;
    object-fit:cover; display:block; pointer-events:none;
    opacity:0; transition: opacity .45s ease;
  }
  .pl-video.is-live{ opacity:1; }

  /* Buffering state for the active card — the video is 20–50 MB, so the gap
     between pressing play and the first frame needs to be spoken for. */
  .pl-spin{
    position:absolute; inset:0; z-index:3;
    display:grid; place-items:center;
    background: rgba(18,5,9,0.44);
    opacity:0; visibility:hidden;
    transition: opacity .35s ease, visibility .35s;
    pointer-events:none;
  }
  .pl-spin.is-on{ opacity:1; visibility:visible; }
  .pl-spin i{
    width:36px; height:36px; border-radius:50%;
    border:1.5px solid rgba(201,173,115,0.22);
    border-top-color: var(--gold-soft);
    animation: plSpin .9s linear infinite;
  }
  @keyframes plSpin{ to{ transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce){
    .pl-spin i{ animation-duration: 2.6s; }
  }
  .pl-card.is-active{ outline-color: rgba(201,173,115,0.55); box-shadow: 0 40px 90px rgba(0,0,0,0.7); }

  .pl-meta{ max-width: var(--max); margin: 0 auto; text-align:center; }
  .pl-now{
    font-family: var(--display); font-weight:500;
    font-size: clamp(19px, 2.6vw, 31px);
    line-height:1.25; margin: 0 0 22px; color: var(--paper);
    min-height: 1.25em;
  }
  .pl-bar{
    position:relative; height:4px; border-radius:2px;
    background: rgba(201,173,115,0.22);
    cursor:pointer; margin-bottom: 9px;
    touch-action: none;
    transition: height .18s ease;
  }
  /* invisible padding so the 4px bar is actually easy to grab */
  .pl-bar::before{
    content:''; position:absolute; left:0; right:0; top:-12px; bottom:-12px;
  }
  .pl-bar:hover, .pl-bar.is-scrub{ height:7px; }
  .pl-bar span{
    position:absolute; left:0; top:0; bottom:0; width:0%;
    background: var(--gold); border-radius:2px;
    pointer-events:none;
  }
  .pl-bar span::after{                       /* scrub handle */
    content:''; position:absolute; right:-6px; top:50%;
    width:12px; height:12px; margin-top:-6px; border-radius:50%;
    background: var(--gold);
    opacity:0; transform: scale(.5);
    transition: opacity .18s ease, transform .18s ease;
  }
  .pl-bar:hover span::after, .pl-bar.is-scrub span::after{ opacity:1; transform: scale(1); }
  .pl-time{
    display:flex; justify-content:space-between;
    font-family: var(--mono); font-size:11px; letter-spacing:.1em;
    color: rgba(239,232,216,0.55); margin-bottom: 26px;
  }
  .pl-ctrls{ display:flex; align-items:center; justify-content:center; gap:22px; }
  .pl-ctrls button{
    width:48px; height:48px; border-radius:50%;
    background:none; border:1px solid rgba(239,232,216,0.32);
    color: var(--paper); cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    transition: background .25s ease, border-color .25s ease, transform .2s ease;
  }
  .pl-ctrls button:hover{ background: rgba(239,232,216,0.10); transform: scale(1.07); }
  .pl-ctrls .pl-play{
    width:64px; height:64px;
    background: var(--wine); border-color: var(--wine);
  }
  .pl-ctrls .pl-play:hover{ background: var(--wine-deep); border-color: var(--wine-deep); }
  .pl-ctrls svg{ width:17px; height:17px; fill: currentColor; }
  .pl-ctrls .pl-play svg{ width:20px; height:20px; }

  @media (max-width: 640px){
    .pl-stage{ height: clamp(180px, 52vw, 260px); }
    .pl-card{ width: min(74vw, 340px); }
    .watch-grid{ grid-template-columns: 1fr; }
  }
  /* ---------- Upcoming performances ---------- */
  .schedule-list{ list-style:none; margin: 0 0 24px; padding:0; }
  .schedule-list li{
    display:grid; grid-template-columns: 140px 1fr; gap: 18px;
    padding: 16px 0; border-bottom: 1px solid var(--line);
    align-items:baseline;
  }
  .schedule-date{ font-family: var(--mono); font-size: 12.5px; color: var(--wine); }
  .schedule-empty{ color: var(--ink-soft); font-style: italic; }

  /* ---------- Inquiry form ---------- */
  .inquiry-form{ max-width: 560px; margin-top: 32px; display:flex; flex-direction:column; gap: 20px; }
  .form-row{ display:flex; flex-direction:column; gap: 8px; }
  .form-row.two-up{ flex-direction:row; gap: 20px; }
  .form-row.two-up > *{ flex:1; min-width:0; }
  .inquiry-form label{
    font-family: var(--mono); font-size: 11px; text-transform:uppercase; letter-spacing:0.12em;
    color: var(--ink-soft);
  }
  .inquiry-form input, .inquiry-form select, .inquiry-form textarea{
    font-family: var(--body);
    font-size: 15.5px;
    color: var(--ink);
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--line);
    padding: 8px 2px;
    outline: none;
    transition: border-color .2s ease;
  }
  .inquiry-form input:focus, .inquiry-form select:focus, .inquiry-form textarea:focus{
    border-color: var(--wine);
  }
  .inquiry-form textarea{ resize: vertical; min-height: 90px; font-family: var(--body); }
  .inquiry-submit{
    align-self: flex-start;
    font-family: var(--mono);
    font-size: 12.5px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    background: var(--wine);
    color: var(--paper);
    border: none;
    padding: 14px 30px;
    cursor: pointer;
    transition: background .2s ease;
  }
  .inquiry-submit:hover{ background: var(--wine-deep); }
  .inquiry-note{ font-size: 13px; color: var(--ink-soft); margin-top: 4px; }

  /* ---------- Questions ----------
     Plain always-visible definition list rather than <details>: the answers are
     what search engines and AI summaries quote, and collapsed text is a worse
     bet for extraction than open text. */
  .faq{ margin: 32px 0 0; display: flex; flex-direction: column; gap: 30px; max-width: 70ch; }
  .faq-item{ display: flex; flex-direction: column; gap: 9px; }
  .faq dt{
    font-family: var(--display); font-weight: 500;
    font-size: clamp(17px, 1.95vw, 21px); line-height: 1.3;
    letter-spacing: -0.012em; color: var(--ink);
    text-wrap: balance;
  }
  .faq dd{ margin: 0; font-size: 16.5px; line-height: 1.72; color: var(--ink-soft); }
  .faq dd a{ color: var(--wine); text-underline-offset: 3px; }
  .section.dark .teach-links{ margin-top: 30px; font-size: 15.5px; color: rgba(239,232,216,0.7); }
  .section.dark .teach-links a{ color: var(--gold-soft); text-underline-offset: 3px; }
  html[lang="ko"] .faq dd{ line-height: 1.85; }

  @media (max-width: 560px){
    .form-row.two-up{ flex-direction: column; }
  }

  /* ---------- Teaching (dark) ---------- */
  .teach-points{ display:grid; gap: 28px; margin-top: 34px; grid-template-columns: repeat(3,1fr); }
  .teach-point{ border-top: 1px solid var(--line-on-dark); padding-top: 16px; }
  .teach-point .num{ font-family: var(--mono); font-size: 26px; color: var(--gold-soft); display:block; margin-bottom: 6px; }
  .teach-point p{ margin:0; font-size: 15px; color: rgba(239,232,216,0.82); }

  /* the .section.dark a rules are more specific than a bare class, so scope these */
  .section.dark .btn-lesson{
    display:inline-flex; align-items:center; gap:12px;
    margin-top: clamp(34px, 5vh, 52px);
    padding: 15px 30px;
    border: 1px solid var(--gold-soft);
    color: var(--gold-soft);
    font-family: var(--mono); font-size: 12.5px;
    letter-spacing: 0.14em; text-transform: uppercase;
    text-decoration: none;
    transition: background .28s ease, color .28s ease, transform .22s ease;
  }
  .section.dark .btn-lesson:hover{
    background: var(--gold-soft);
    color: var(--night-2);
    transform: translateY(-2px);
  }
  .section.dark .btn-lesson svg{ width:13px; height:13px; fill:currentColor; flex:0 0 auto; }

  /* ---------- Contact ---------- */
  footer{
    background: var(--ink);
    color: rgba(239,232,216,0.55);
    text-align:center;
    padding: 28px var(--edge);
    font-family: var(--mono);
    font-size: 11.5px;
    letter-spacing: 0.06em;
    display: flex; flex-wrap: wrap; gap: 10px 22px;
    align-items: center; justify-content: center;
  }
  .foot-social{
    color: var(--gold-soft); text-decoration: none;
    border-bottom: 1px solid rgba(201,173,115,0.3); padding-bottom: 1px;
    transition: color .2s ease, border-color .2s ease;
  }
  .foot-social:hover{ color: var(--paper); border-color: var(--paper); }

  @media (max-width: 640px){
    .section{ padding: 76px var(--edge); }
    .teach-points{ grid-template-columns: 1fr; gap: 22px; }
    .cred-list li{ grid-template-columns: 1fr; gap: 4px; }
    .cred-year{ padding-top: 0; }
  }

/* ============================================================
     Staged loading — hero, then About, then everything else.
     Each stage adds html.stage-<name>; modules hook in via bootWhen().
     Nothing here may permanently hide content: every gate has a
     timeout, and .no-js short-circuits the whole system.
     ============================================================ */

  html.booting{ overflow: hidden; }

  .boot{
    position: fixed; inset: 0; z-index: 999;
    display: grid; place-items: center;
    background:
      radial-gradient(70% 55% at 18% 82%, var(--glow-plum) 0%, transparent 60%),
      radial-gradient(85% 65% at 68% 40%, var(--glow-wine) 0%, transparent 62%),
      radial-gradient(120% 100% at 24% 26%, var(--night-1) 0%, var(--night-2) 52%, var(--night-3) 100%);
    transition: opacity .85s ease .1s, visibility .85s .1s;
  }
  html.booted .boot{ opacity: 0; visibility: hidden; pointer-events: none; }
  html.no-js .boot{ display: none; }

  .boot-inner{ width: min(320px, 74vw); text-align: center; }
  .boot-name{
    font-family: var(--display); font-size: clamp(20px, 3.2vw, 26px);
    color: var(--paper); margin: 0 0 26px; opacity: 0;
    animation: bootFade 1.1s ease forwards .15s;
  }
  .boot-rail{
    position: relative; height: 1px; overflow: hidden;
    background: rgba(201,173,115,0.20);
  }
  .boot-fill{
    position: absolute; top: 0; bottom: 0; left: 0; width: 0%;
    background: linear-gradient(90deg, var(--gold), var(--gold-soft));
    transition: width .5s cubic-bezier(.4,0,.2,1);
  }
  .boot-stage{
    font-family: var(--mono); font-size: 11px; letter-spacing: 0.2em;
    text-transform: uppercase; color: var(--gold-soft);
    margin: 18px 0 0; opacity: 0;
    animation: bootFade 1.1s ease forwards .35s;
  }
  @keyframes bootFade{ from{ opacity:0; transform: translateY(8px); } to{ opacity:.78; transform:none; } }

  /* About waits for the hero to finish, so it fades in as its own beat. */
  .gate{ opacity: 0; transition: opacity .9s ease; }
  html.no-js .gate, .gate.gate-in{ opacity: 1; }

  /* Playlist posters arrive last — each card holds a shimmer until its own
     poster decodes, so the rack never shows a row of black rectangles. */
  .pl-card.is-loading .pl-poster{ opacity: 0; }
  .pl-poster{ transition: opacity .5s ease; }
  .pl-card.is-loading::after{
    content: ''; position: absolute; inset: 0;
    background:
      linear-gradient(100deg, transparent 20%, rgba(201,173,115,0.10) 50%, transparent 80%),
      linear-gradient(180deg, var(--night-1), var(--night-3));
    background-size: 220% 100%, 100% 100%;
    animation: bootShimmer 1.5s ease-in-out infinite;
  }
  @keyframes bootShimmer{ from{ background-position: 140% 0, 0 0; } to{ background-position: -60% 0, 0 0; } }

  @media (prefers-reduced-motion: reduce){
    .boot{ transition-duration: .001ms; }
    .pl-card.is-loading::after{ animation: none; }
  }

/* ---------- Korean page ---------- */
  /* keep-all stops Hangul from breaking mid-word, which is the single biggest
     readability win; Hangul also carries more ink per line, so the prose gets
     a touch more leading and slightly negative tracking to compensate. */
  html[lang="ko"] body{ word-break: keep-all; overflow-wrap: break-word; }
  html[lang="ko"] .bio,
  html[lang="ko"] .hero-sub,
  html[lang="ko"] .morph-body .bio{ letter-spacing: -0.006em; }
  /* Nanum Myeongjo ships 400/700/800 — the Latin styles ask for 500, which
     lands back on regular and erases the emphasis. */
  html[lang="ko"] .bio strong{ font-weight: 700; }
  html[lang="ko"] .morph-body .bio{ line-height: 1.85; }
  html[lang="ko"] h1,
  html[lang="ko"] h2,
  html[lang="ko"] .morph-title{ letter-spacing: -0.02em; }
  .nav-lang a{ color: var(--gold); }
  .nav-lang a::after{ display: none; }

/* ---------- landing pages ----------
   Scoped to .yh-landing so the very same block can be concatenated into the
   theme's shared stylesheet without disabling the one-pager's scroll reveal.
   No GSAP here, so those transforms must not apply — the page would otherwise
   render permanently invisible. */
  .yh-landing .reveal{ opacity: 1 !important; transform: none !important; }
  .lp-hero{
    background:
      radial-gradient(78% 120% at 12% 88%, rgba(107,31,46,0.34) 0%, transparent 60%),
      radial-gradient(120% 110% at 74% 10%, var(--night-1) 0%, var(--night-2) 54%, var(--night-3) 100%);
    color: var(--paper);
    padding: clamp(104px, 17vh, 190px) var(--edge) clamp(56px, 9vh, 96px);
  }
  .lp-inner{ max-width: var(--max); margin: 0 auto; }
  .lp-hero .opus{ color: var(--gold-soft); }
  .lp-hero h1{
    font-family: var(--display); font-weight: 500;
    font-size: clamp(34px, 6vw, 62px); line-height: 1.02; letter-spacing: -0.025em;
    margin: 10px 0 0; color: var(--paper); text-wrap: balance;
  }
  .lp-hero .lede{
    font-family: var(--body); font-size: clamp(16.5px, 1.8vw, 19px); line-height: 1.75;
    color: rgba(239,232,216,0.9); margin: 22px 0 0; max-width: 60ch;
  }
  .lp-hero .lede strong{ color: var(--paper); font-weight: 500; }
  .lp-hero .staff-divider{ background: var(--line-on-dark); margin-top: 26px; }
  .lp-body{ padding: clamp(52px, 9vh, 96px) var(--edge); background: var(--paper); }
  .lp-block{ max-width: var(--max); margin: 0 auto; display: flex; flex-direction: column; gap: 40px; }
  .lp-block h2{
    font-family: var(--display); font-weight: 500;
    font-size: clamp(21px, 2.7vw, 30px); letter-spacing: -0.015em; margin: 0 0 12px;
    color: var(--ink); text-wrap: balance;
  }
  .lp-block .bio{ margin: 0; }
  .lp-cta{
    border-top: 1px solid var(--line); padding-top: 34px;
    display: flex; flex-direction: column; gap: 14px; align-items: flex-start;
  }
  .lp-sibling{ font-size: 15.5px; color: var(--ink-soft); }
  .lp-sibling a{ color: var(--wine); }
  .lp-back{
    font-family: var(--mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--gold-soft); text-decoration: none;
  }
  .lp-back:hover{ color: var(--paper); }
  /* The nav opens over a dark hero here, so it starts light and flips to the
     site's paper treatment once .scrolled lands. */
  .yh-landing .nav, .yh-landing .nav .nav-name{ color: var(--paper); }
  .yh-landing .nav.scrolled{ color: var(--ink); }
  .yh-landing .nav.scrolled .nav-name{ color: var(--wine); }


/* ---------- Contact Form 7 ----------
   CF7 renders its own markup, so the inquiry-form look is mapped onto its
   classes here. The form templates that match this layout are in README.md. */
.wpcf7{ max-width: 560px; margin-top: 32px; }
.wpcf7-form{ display:flex; flex-direction:column; gap: 20px; }
.wpcf7-form .form-row{ display:flex; flex-direction:column; gap: 8px; }
.wpcf7-form .form-row.two-up{ flex-direction:row; gap: 20px; }
.wpcf7-form .form-row.two-up > *{ flex:1; min-width:0; }
.wpcf7-form label{
  display:flex; flex-direction:column; gap:8px;
  font-family: var(--mono); font-size: 11px; text-transform:uppercase; letter-spacing:0.12em;
  color: var(--ink-soft);
}
.wpcf7-form input[type=text], .wpcf7-form input[type=email], .wpcf7-form input[type=date],
.wpcf7-form select, .wpcf7-form textarea{
  font-family: var(--body);
  font-size: 15.5px;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 8px 2px;
  outline: none;
  width: 100%;
  transition: border-color .2s ease;
}
.wpcf7-form input:focus, .wpcf7-form select:focus, .wpcf7-form textarea:focus{
  border-color: var(--wine);
}
.wpcf7-form textarea{ resize: vertical; min-height: 90px; }
.wpcf7-form .wpcf7-submit{
  align-self: flex-start;
  font-family: var(--mono);
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  background: var(--wine);
  color: var(--paper);
  border: none;
  padding: 14px 30px;
  cursor: pointer;
  transition: background .2s ease;
}
.wpcf7-form .wpcf7-submit:hover{ background: var(--wine-deep); }
.wpcf7-form .wpcf7-spinner{ margin: 0 0 0 12px; }
.wpcf7 form .wpcf7-response-output{
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.06em;
  border-color: var(--line); color: var(--ink-soft);
  margin: 8px 0 0; padding: 12px 14px;
}
.wpcf7-not-valid-tip{ font-family: var(--mono); font-size: 11px; color: var(--wine); }
.yh-form-missing{
  font-family: var(--mono); font-size: 12.5px; color: var(--ink-soft);
  border: 1px dashed var(--line); padding: 18px 20px; margin-top: 32px;
}
/* Korean labels are not acronyms — uppercasing them does nothing, but the wide
   mono tracking pulls Hangul apart, so it is dialled back here. */
html[lang="ko"] .wpcf7-form label{ letter-spacing: 0.02em; font-size: 11.5px; }
html[lang="ko"] .wpcf7-form .wpcf7-submit{ letter-spacing: 0.04em; text-transform: none; }
