/* ===========================================================================
 * Woong Demian Park - personal site
 *
 * Design tokens are taken from the Biznius landing so the two read as the same
 * visual family (frontend/tailwind.config.js + src/index.css):
 *   canvas  #0a0a0f      body ink  #e8e8f0
 *   accent  #22d3ee (cyan)         violet #a855f7
 *   grid    44px, cyan at 3.5%
 *   scene   mint #4cbe98 -> violet #524bb3 (assets/scene.js)
 * =========================================================================== */

:root {
  --canvas: #0a0a0f;
  --ink: #e8e8f0;
  --accent: #22d3ee;
  --violet: #a855f7;
  --mint: #4cbe98;
  --line: rgba(255, 255, 255, 0.12);
  --panel: rgba(255, 255, 255, 0.035);
  --muted: rgba(232, 232, 240, 0.62);
  --faint: rgba(232, 232, 240, 0.42);
  --maxw: 1080px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
  -webkit-font-smoothing: antialiased;
  line-height: 1.62;
  overflow-x: hidden;
}

/* The particle scene. Fixed behind everything, never interactive. */
#scene {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  user-select: none;
}

/* Same 44px cyan grid as the Biznius landing, over the scene. */
.grid-overlay {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(34, 211, 238, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(34, 211, 238, 0.035) 1px, transparent 1px);
  background-size: 44px 44px;
}

/* Content rides above the scene. */
.page { position: relative; z-index: 2; }

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 24px;
}

/* ---- section rhythm ----------------------------------------------------
 * Hierarchy is carried by whitespace: the gap BETWEEN sections must be clearly
 * larger than the largest gap INSIDE one, or the reader cannot see where a
 * section ends without reading the heading.
 *
 * The selector is `section.wrap`, not `section`. Every section here also
 * carries .wrap, and `.wrap { padding: 0 24px }` is a class selector, so a bare
 * `section { padding: 88px 0 }` lost the cascade and the vertical padding
 * silently evaporated: measured boundary gap was 9px against a 34px gap inside
 * a section - the hierarchy was inverted, which is exactly what "the sections
 * run together" looks like. Matching specificity fixes it at the source.      */

section.wrap { padding-top: 96px; padding-bottom: 96px; }
section.wrap:first-of-type { padding-top: 72px; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 14px;
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 1px;
  background: var(--accent);
  opacity: 0.7;
}

h1, h2, h3 { line-height: 1.22; margin: 0; }

h2 {
  font-size: clamp(26px, 4vw, 36px);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 10px;
}

.section-lead {
  color: var(--muted);
  font-size: 15.5px;
  max-width: 62ch;
  margin: 0 0 34px;
}

/* ---- panels ------------------------------------------------------------
 * Text sits on a faint translucent panel. The scene stays fully visible around
 * and between panels; this only guarantees contrast where words are, which is
 * the readability gate for narrow screens.                                  */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 22px 24px;
  /* No backdrop blur on purpose. A blur behind the panel smears the particle
     shape into a haze - the shape stops reading, which is the same failure as
     hiding it. Contrast is held by this tint plus the scene's own avoidance
     field, which dims particles behind text lines (assets/scene.js). */
}

/* ---- hero -------------------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 44px;
  align-items: center;
  min-height: 78vh;
  padding: 96px 0 72px;
}

.hero h1 {
  font-size: clamp(38px, 6.4vw, 62px);
  font-weight: 900;
  letter-spacing: -0.035em;
}
.hero .role {
  margin: 14px 0 0;
  font-size: clamp(16px, 2.2vw, 20px);
  font-weight: 600;
  color: var(--accent);
  letter-spacing: -0.01em;
}
.hero .tagline {
  margin: 18px 0 0;
  font-size: 16.5px;
  color: var(--muted);
  max-width: 46ch;
}

.stats {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}
.stats li {
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.03);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  color: rgba(232, 232, 240, 0.86);
}
.stats b { color: var(--accent); font-weight: 800; }

.links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 28px 0 0;
}
.links a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease;
}
.links a:hover, .links a:focus-visible {
  border-color: rgba(34, 211, 238, 0.55);
  background: rgba(34, 211, 238, 0.08);
  color: #fff;
}
.links a.primary {
  border-color: rgba(34, 211, 238, 0.5);
  color: var(--accent);
}

/* Profile card. The source image is a light illustrated card, so it gets a
   real frame rather than sitting flush against the dark canvas. */
.portrait {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 10px;
  background: rgba(255, 255, 255, 0.05);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}
.portrait img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
}
.portrait figcaption {
  margin-top: 10px;
  font-size: 12px;
  color: var(--faint);
  text-align: center;
}

/* ---- creed -------------------------------------------------------------
 * The opening statement, set larger than body copy with the author's own
 * phrasing preserved as line units.
 *
 * Deliberately not inside a .panel: a box would read as a pull quote, and this
 * is the page speaking in the first person. Contrast is held instead by nearly
 * opaque ink (the ratio is measured, see README) plus the scene's avoidance
 * field, which dims particles behind every text line at all widths.          */

.creed {
  margin: 0;
  border-left: 2px solid rgba(34, 211, 238, 0.45);
  padding-left: clamp(18px, 3vw, 34px);
  /* Wide enough that the longest intended line (74 characters at 22px) fits on
     one row. At 74ch the column was 652px and three lines folded, which breaks
     the phrasing the breaks exist to create. A long measure is not a problem
     here because the lines are authored, not reflowed. */
  max-width: 900px;
}

.creed p {
  margin: 0 0 clamp(22px, 3vw, 34px);   /* stanza gap, larger than the line gap */
  font-size: clamp(17px, 1.55vw, 22px);
  line-height: 1.62;
  font-weight: 400;
  color: rgba(232, 232, 240, 0.93);
  letter-spacing: -0.008em;
  text-align: left;                     /* never justified - a ragged right edge
                                           is what makes the phrasing readable */
  text-wrap: pretty;
}
.creed p:last-child { margin-bottom: 0; }

/* One intended breath per line. Block on wide screens, inline when the line
   would wrap anyway (see the media query below). */
.creed .ln { display: block; }

/* The closing stanza carries the actual ask, so it gets the emphasis. */
.creed p:last-child { color: #fff; font-weight: 500; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

/* ---- experience -------------------------------------------------------- */

.role-block + .role-block { margin-top: 18px; }

.role-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 16px;
  margin-bottom: 4px;
}
.role-head h3 { font-size: 19px; font-weight: 800; letter-spacing: -0.015em; }
.role-head .when {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}
.role-org {
  margin: 0 0 14px;
  font-size: 14px;
  color: var(--faint);
  font-weight: 600;
}

.bullets { margin: 0; padding: 0; list-style: none; }
.bullets > li { padding: 10px 0; border-top: 1px solid rgba(255, 255, 255, 0.07); }
.bullets > li:first-child { border-top: 0; padding-top: 2px; }
.bullets .b-title {
  display: block;
  font-size: 14.5px;
  font-weight: 700;
  color: rgba(232, 232, 240, 0.95);
  margin-bottom: 3px;
}
.bullets p { margin: 0; font-size: 14.5px; color: var(--muted); }

/* ---- card grids -------------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: 16px;
}
.card h3 {
  font-size: 15px;
  font-weight: 800;
  color: var(--accent);
  margin-bottom: 8px;
  letter-spacing: -0.01em;
}
.card p { margin: 0; font-size: 14.5px; color: var(--muted); }

.tags { display: flex; flex-wrap: wrap; gap: 7px; margin: 10px 0 0; padding: 0; list-style: none; }
.tags li {
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  padding: 4px 9px;
  font-size: 12.5px;
  color: rgba(232, 232, 240, 0.78);
}

/* ---- education --------------------------------------------------------- */

.edu { display: grid; gap: 14px; }
.edu .role-head h3 { font-size: 17px; }

/* ---- honors ------------------------------------------------------------ */

.honors { width: 100%; border-collapse: collapse; font-size: 14px; }
.honors caption {
  text-align: left;
  color: var(--faint);
  font-size: 13px;
  padding-bottom: 12px;
}
.honors th {
  text-align: left;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint);
  font-weight: 700;
  padding: 0 12px 10px 0;
  border-bottom: 1px solid var(--line);
}
.honors td {
  padding: 11px 12px 11px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  vertical-align: top;
  color: var(--muted);
}
.honors td:first-child {
  color: var(--accent);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  width: 1%;
}
.honors td.award { color: rgba(232, 232, 240, 0.92); font-weight: 600; }
.honors tr.top td.award { color: #fff; }
.honors tr.top td:first-child::after {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-left: 7px;
  border-radius: 50%;
  background: var(--violet);
  vertical-align: middle;
}

/* ---- closing ----------------------------------------------------------- */

.closing p { margin: 0 0 14px; font-size: 15.5px; color: var(--muted); }
.closing p:last-child { margin-bottom: 0; }
.closing strong { color: rgba(232, 232, 240, 0.95); font-weight: 700; }

footer {
  border-top: 1px solid var(--line);
  padding: 32px 0 56px;
  font-size: 13px;
  color: var(--faint);
}
footer .wrap { display: flex; flex-wrap: wrap; gap: 10px 24px; justify-content: space-between; align-items: center; }
.foot-links { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.foot-links a { white-space: nowrap; }
footer a { color: var(--muted); text-decoration: none; }
footer a:hover, footer a:focus-visible { color: var(--accent); }

/* ---- accessibility ----------------------------------------------------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: #04121a;
  padding: 10px 16px;
  font-weight: 800;
  border-radius: 0 0 10px 0;
  z-index: 10;
}
.skip:focus { left: 0; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---- responsive --------------------------------------------------------
 * The scene's own avoidance field dims particles behind text on narrow
 * screens; the panels above guarantee contrast on top of that.             */

@media (max-width: 900px) {
  .hero {
    grid-template-columns: 1fr;
    gap: 34px;
    min-height: 0;
    padding: 72px 0 48px;
  }
  .portrait { max-width: 420px; }
  section.wrap { padding-top: 72px; padding-bottom: 72px; }
}

/* Below this width the longest intended line (74 characters) cannot fit on one
   row, so honouring the break would produce three ragged fragments instead of
   one phrase - worse phrasing than no break at all. The lines collapse to
   inline and reflow; the stanzas, which carry the structure, still hold. */
@media (max-width: 700px) {
  .creed .ln { display: inline; }
  .creed { border-left-width: 2px; }
}

@media (max-width: 560px) {
  .wrap { padding: 0 18px; }
  .panel { padding: 18px 16px; border-radius: 14px; }
  /* Mobile keeps the same hierarchy with a smaller absolute gap: copying the
     desktop value here would only make the page longer to scroll. The gap is
     still well above the largest in-section gap, which is what has to hold. */
  section.wrap { padding-top: 56px; padding-bottom: 56px; }
  .hero { padding: 56px 0 40px; }
  .role-head .when { font-size: 12.5px; }

  /* The honors table becomes stacked rows - 3 columns cannot hold at 360px. */
  .honors, .honors tbody, .honors tr, .honors td { display: block; width: auto; }
  .honors thead { display: none; }
  .honors tr {
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    padding: 12px 0;
  }
  .honors td { border: 0; padding: 0; }
  .honors td:first-child { width: auto; margin-bottom: 3px; }
  .honors td.org { font-size: 13px; color: var(--faint); margin-top: 2px; }
}

@media print {
  #scene, .grid-overlay { display: none; }
  body { background: #fff; color: #111; }
  .panel { border-color: #ccc; background: none; }
}
