/**
 * v7-tabella-prototype.css
 *
 * Independent stylesheet for the Tabella-principle Home v7 prototype.
 * Does NOT import, extend, or reuse any selector from assets/css/main.css.
 * Every class in this file is prefixed `.tb-` specifically so it can never
 * collide with (or be mistaken for a copy of) an existing v6/v7 class such
 * as `.wide-pad`, `.career-rail`, `.career-scene`, `.detail-panel`, or the
 * old `.hero-grid`.
 *
 * Design principles this file encodes (extracted from a live inspection of
 * https://tabella-phenomenon.netlify.app/, not copied source):
 *   - one large, centered "Stage" per scene, big border-radius, no shadow
 *   - a light warm "paper" register and a dark "charcoal" register that
 *     alternate scene-to-scene, never mixed inside one Stage
 *   - big sharp display type carries the composition; weight restraint
 *     (400-600) does the work color/size used to elsewhere, not 800-900
 *   - lime is a label/pointer color, never a fill color
 *   - content panels float at different sizes/heights inside a Stage
 *     rather than repeating as identical same-size cards
 *   - movement is limited to one clear, purposeful transition per
 *     interaction — never ambient/looping motion
 */

/* ------------------------------------------------------------------ *
 * 0. Reset + base
 * ------------------------------------------------------------------ */

.tb-root, .tb-root *, .tb-root *::before, .tb-root *::after {
  box-sizing: border-box;
}

.tb-root {
  --tb-paper: #FAF8F3;
  --tb-stage-light: #EDE9DF;
  --tb-stage-light-alt: #E3DED2;
  --tb-ink: #16171B;
  /* Report 20 §D: darkened from #63666D. That value measured 4.28:1 on
     --tb-stage-light-alt (Legal RAG panel secondary text) — a real WCAG
     AA failure (4.5:1 required), not just "looks a bit faint" — and only
     4.74:1 on --tb-stage-light (Hero credentials/Career card meta),
     barely passing. This single token drives all of those plus Section
     eyebrow and Footer (grep confirms no separate muted token exists),
     so one change fixes all of them consistently: now 5.15:1 on
     stage-light-alt, 5.70:1 on stage-light, 6.51:1 on paper — a modest,
     uniform lift, not a jump to primary-ink weight. */
  --tb-ink-soft: #575A61;
  --tb-rule: #D9D4C7;

  --tb-stage-dark: #1B1B1F;
  --tb-stage-dark-alt: #232328;
  --tb-dark-ink: #F3F1EA;
  --tb-dark-ink-soft: #A7A9AC;
  --tb-dark-rule: rgba(243, 241, 234, 0.14);

  --tb-lime: #A7C43A;       /* large text / graphics on DARK stage only */
  --tb-lime-ink: #4E6A16;   /* small text / links / focus on LIGHT stage — 5.10:1 on stage-light, 5.82:1 on paper */
  --tb-lime-bright: #C4E15C; /* small text / links / focus on DARK stage — 11.67:1 on stage-dark */

  --tb-oxide: #C63C1B;
  --tb-oxide-ink: #A8330F;   /* 5.51:1 on stage-light — TRPG only */
  --tb-oxide-bright: #FF6B3D; /* 6.07:1 on stage-dark — TRPG only */

  --tb-font-display: 'Red Hat Display', 'Pretendard Variable', -apple-system, 'Segoe UI', sans-serif;
  --tb-font-body: 'Pretendard Variable', -apple-system, 'Segoe UI', sans-serif;
  --tb-font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --tb-stage-max: 1860px;
  --tb-gutter: clamp(1.25rem, 4vw, 4.5rem);
  --tb-radius-xl: clamp(28px, 2.4vw, 48px);
  --tb-radius-lg: clamp(20px, 1.6vw, 32px);
  --tb-radius-md: 16px;
  --tb-header-h: clamp(4rem, 3.7rem + 0.5vw, 4.75rem);

  background: var(--tb-paper);
  color: var(--tb-ink);
  font-family: var(--tb-font-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

.tb-root h1, .tb-root h2, .tb-root h3 {
  font-family: var(--tb-font-display);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 0;
}

.tb-root p { margin: 0; }
.tb-root ul, .tb-root ol { margin: 0; padding: 0; list-style: none; }
.tb-root img { max-width: 100%; display: block; }
.tb-root a { color: inherit; text-decoration: none; }
/* :where() keeps this reset's specificity at (0,1,0) — equal to a plain
   single-class component rule like .tb-career-btn — so any later
   component rule wins on source order instead of silently losing to a
   higher-specificity reset (a real bug caught here: .tb-career-btn's
   border/color/background were being clobbered by this reset before the
   :where() wrap, because ".tb-root button" alone is (0,1,1) > (0,1,0)). */
.tb-root :where(button) { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.tb-mono { font-family: var(--tb-font-mono); font-size: 0.8125rem; letter-spacing: 0.01em; }

.tb-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;
}

.tb-skip {
  position: absolute; left: 1rem; top: -3rem; z-index: 100;
  background: var(--tb-ink); color: var(--tb-paper);
  padding: 0.75rem 1.25rem; border-radius: 999px;
  transition: top 160ms ease;
}
.tb-skip:focus-visible { top: 1rem; }

.tb-root :focus-visible {
  outline: 2px solid var(--tb-lime-ink);
  outline-offset: 3px;
  border-radius: 4px;
}
.tb-root [data-tone="dark"] :focus-visible,
.tb-header :focus-visible {
  outline-color: var(--tb-lime-ink);
}
.tb-career-stage :focus-visible,
.tb-work-stage[data-active] :focus-visible {
  outline-color: var(--tb-lime-bright);
}

@media (prefers-reduced-motion: reduce) {
  .tb-root, .tb-root *, .tb-root *::before, .tb-root *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  /* Belt-and-suspenders on top of the reveal JS not running at all under
     reduced motion (see v7-tabella-prototype.js §3): force every Stage and
     its staggered children to their fully-settled state so nothing can
     ever be caught mid-reveal or left dimmed/offset. */
  .tb-reveal-stage {
    transform: none !important;
    opacity: 1 !important;
  }
  .tb-reveal-child {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .tb-entrance-stage.tb-reveal-stage {
    border-radius: var(--tb-radius-xl) !important;
  }
}

/* ------------------------------------------------------------------ *
 * 0.5 Common "Stage reveal" system — shared by Hero / Career / Selected
 * Work / Current Focus / Closing. A Stage's own scale/translate/opacity
 * is driven continuously by three custom properties the JS sets every
 * scroll frame (--tb-stage-scale / --tb-stage-translate / --tb-stage-
 * opacity), computed from how close the Stage's center is to the
 * viewport's center — see v7-tabella-prototype.js. The variables default
 * to the fully-settled values below so the page is correct even before
 * JS runs or if it fails (progressive enhancement, no content ever
 * hidden). transform/opacity only — no layout-affecting properties —
 * so this never triggers layout thrashing.
 * ------------------------------------------------------------------ */
.tb-reveal-stage {
  transform: translateY(var(--tb-stage-translate, 0px)) scale(var(--tb-stage-scale, 1));
  opacity: var(--tb-stage-opacity, 1);
  transition: transform 90ms linear, opacity 90ms linear;
  will-change: transform, opacity;
}

.tb-reveal-child {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 380ms ease, transform 380ms ease;
  transition-delay: calc(var(--tb-i, 0) * 80ms);
}
.tb-reveal-stage.is-tb-in .tb-reveal-child,
.tb-work-panel.is-active .tb-reveal-child {
  opacity: 1;
  transform: none;
}

/* Closing/Contact: reveal removed (report 20 §A). The statement and CTA
   are the last thing on the page and must be immediately legible the
   moment a user reaches this section — scroll-linked reveal timing here
   only ever produced a large ivory box with invisible text. Overrides
   both the outer Stage (scale/opacity) and its children unconditionally;
   the JS still computes values for this Stage (kept for code-path
   uniformity — see v7-tabella-prototype.js §"Common Stage reveal") but
   they're inert here. */
.tb-closing-stage.tb-reveal-stage {
  transform: none !important;
  opacity: 1 !important;
}
.tb-closing-stage .tb-reveal-child {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* ------------------------------------------------------------------ *
 * 0.6 "Stage Entrance" — a small extra layer on top of §0.5's Stage
 * reveal, opt-in via `.tb-entrance-stage` (added alongside
 * `.tb-reveal-stage`, never instead of it). Report 20: inspired by the
 * general *idea* of tabella-phenomenon.netlify.app (a content frame that
 * arrives as a slightly smaller, softer-edged card and settles into its
 * full-size, full-detail state) — not copied from it. A direct Playwright
 * inspection of that site's live CSS/computed styles for this task found
 * no scale-based entrance transform on its main content sections at all
 * (only a plain nav fade-in/out keyframe and a sticky/pinned tab block);
 * what follows is built from the brief's own numeric spec, not from the
 * reference site's actual (much subtler) implementation.
 *
 * Only the two properties this needs beyond §0.5 live here:
 *   - a visibly larger corner radius before first reveal, settling to the
 *     section's normal --tb-radius-xl once `.is-tb-in` — a real (paint-
 *     only, non-layout) property change, since transform:scale() alone
 *     would make radius look SMALLER while shrunk, the opposite of the
 *     "rounder card" brief.
 *   - a slower, eased transition on transform/opacity than §0.5's base
 *     90ms-linear per-frame follow (tuned for continuous scroll-scrub
 *     tracking) — long enough here to read as one deliberate "expand"
 *     on first arrival. Report 21: bumped from 640/520ms to 860/680ms
 *     to land inside the refined ~700-950ms spec — the original timing
 *     was technically within report 20's looser 650-900ms range, but
 *     read as too quick/subtle once the scale delta below was also
 *     made more dramatic.
 * The scale/translate/opacity magnitude itself is still driven by the
 * SAME --tb-stage-scale/translate/opacity custom properties from §0.5's
 * JS; only sectionConfig's numbers differ per intensity tier (see
 * v7-tabella-prototype.js §5) — no second motion system, no fighting
 * over the same property (constraint: "no new large animation library,
 * use CSS transform + existing JS architecture"). `background` is kept
 * in the transition list so Selected Work's own tab-switch crossfade
 * (§4, `.tb-work-stage`'s `transition: background 400ms ease`) still
 * works — this rule is more specific and would otherwise silently drop
 * it. `outThreshold` is set very high for entrance-tagged sections in
 * the JS config specifically so `.is-tb-in` effectively never reverts
 * once triggered — "strong only on first entry, must not interfere with
 * reading afterward" without needing a separate one-shot state machine. */
.tb-entrance-stage.tb-reveal-stage {
  border-radius: clamp(36px, 5vw, 72px);
  transition: transform 860ms cubic-bezier(.16,.84,.32,1), opacity 680ms ease-out, border-radius 680ms ease-out, background 400ms ease;
}
.tb-entrance-stage.tb-reveal-stage.is-tb-in {
  border-radius: var(--tb-radius-xl);
}

/* Subpages' Page Intro Stage is a special case: it sits immediately below
   the fixed header, at the very top of a short(er) page, so its center is
   already at-or-above the viewport's middle from the very first paint —
   the scroll-distance formula that drives every OTHER Stage (§0.5) never
   gets a chance to see it as "still below, entering", because there's no
   scroll journey to it. Verified in report 20: without this override its
   custom properties measured already-settled (scale~1, opacity~1) at
   scrollY 0. So this one Stage type gets its compact state directly from
   CSS defaults instead of the scroll formula, and v7-tabella-prototype.js
   §5 triggers `.is-tb-in` once, shortly after load/paint (page-arrival
   entrance, not scroll-arrival) rather than registering it into the
   shared scroll frame task at all. */
/* Report 21 fix: the ROOT bug the user reported ("완료 상태에서도 카드가 화면
   왼쪽 절반만 차지") was not really about the scale delta at all — it was
   that `.tb-page-intro-stage` itself carried `max-width: 46rem` (see the
   old rule below §8), so even at the fully-settled scale(1) state the
   frame could never be wider than 736px on any viewport. Measured live
   on the deployed Preview before this fix: 1920px viewport → settled
   frame width 736px (38%), left-aligned, ~1100px of dead space to its
   right. Scale magnitude was never the actual defect.
   Fix has two independent parts:
   1. `.tb-page-intro-stage` (§8 below) no longer carries a width cap —
      it's a full-width frame like every other Stage on the site
      (Hero/Career/Work), so its SETTLED state now genuinely fills the
      Page Intro section's main horizontal area (~88-96% of viewport
      depending on the shared `--tb-gutter`). A new inner
      `.tb-page-intro-reading` wrapper (§8) carries the old 46rem cap
      instead, so heading/lead text still reads as a normal column and
      doesn't stretch edge-to-edge — the "outer Stage frame vs. inner
      reading column" split the brief asked for.
   2. With the frame now genuinely full-width at rest, the SAME uniform
      `transform: scale()` mechanism already proven bug-free on Selected
      Work (§ "work" in v7-tabella-prototype.js) works correctly here too
      — scaling a full-width, horizontally-centered box down and back up
      keeps it centered throughout and produces a real, clearly visible
      "compact card → full stage" transition (roughly 65% of viewport
      width at rest → the full frame), not the previous barely-there
      0.88→1 nudge on an already-wrong final width. transform never
      triggers layout/reflow, so this stays CLS-safe by construction —
      deliberately chosen over animating a real `width` property (which
      would reflow the heading's line breaks and change the frame's own
      height mid-transition, the exact kind of shift `report 21 §4`'s
      CLS check is watching for). */
.tb-page-intro-stage.tb-reveal-stage {
  --tb-stage-scale: 0.66;
  --tb-stage-opacity: 0.88;
  transform-origin: center center;
}
.tb-page-intro-stage.tb-reveal-stage.is-tb-in {
  --tb-stage-scale: 1;
  --tb-stage-opacity: 1;
}
/* Mobile: ~50% of the desktop delta (brief's 40-60% range), and the
   frame is already close to full-viewport-width at rest on a narrow
   screen — so this is mostly a margin/radius/opacity move, not a
   dramatic width reveal, per report 21 §3's mobile guidance. */
@media (max-width: 639.98px) {
  .tb-page-intro-stage.tb-reveal-stage {
    --tb-stage-scale: 0.83;
    --tb-stage-opacity: 0.94;
  }
}

.tb-eyebrow {
  display: inline-flex; align-items: center; gap: 0.4em;
  font-family: var(--tb-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tb-ink-soft);
}
.tb-eyebrow--dark { color: var(--tb-dark-ink-soft); }
.tb-eyebrow::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--tb-lime-ink); flex: none;
}
.tb-eyebrow--dark::before { background: var(--tb-lime-bright); }

.tb-mark {
  background: var(--tb-lime);
  color: var(--tb-ink);
  padding: 0.02em 0.32em;
  border-radius: 0.3em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.tb-stage {
  max-width: var(--tb-stage-max);
  margin-inline: auto;
  padding-inline: var(--tb-gutter);
}

/* ------------------------------------------------------------------ *
 * 1. Fixed Header
 * ------------------------------------------------------------------ */

.tb-header {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  height: var(--tb-header-h);
  display: flex; align-items: center;
  background: rgba(250, 248, 243, 0.92);
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease, background 200ms ease;
}
.tb-header[data-scrolled="true"] {
  border-bottom-color: var(--tb-rule);
  background: rgba(250, 248, 243, 0.98);
}

.tb-header-row {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
}

.tb-wordmark {
  font-family: var(--tb-font-display);
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}

.tb-nav {
  display: flex; align-items: center; gap: clamp(1.25rem, 2.4vw, 2.5rem);
}

.tb-nav-link {
  position: relative;
  font-size: 0.9rem;
  color: var(--tb-ink-soft);
  padding-block: 0.35rem;
}
.tb-nav-link::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -2px;
  height: 2px; background: var(--tb-lime-ink);
  transform: scaleX(0); transform-origin: left;
  transition: transform 220ms ease;
}
.tb-nav-link:hover { color: var(--tb-ink); }
.tb-nav-link.is-active { color: var(--tb-ink); }
.tb-nav-link.is-active::after { transform: scaleX(1); }

.tb-nav-toggle {
  display: none;
  width: 2.5rem; height: 2.5rem;
  align-items: center; justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--tb-rule);
}
.tb-nav-toggle-bars,
.tb-nav-toggle-bars::before,
.tb-nav-toggle-bars::after {
  display: block; width: 16px; height: 1.5px; background: var(--tb-ink);
  transition: transform 200ms ease, opacity 200ms ease;
}
.tb-nav-toggle-bars { position: relative; }
.tb-nav-toggle-bars::before, .tb-nav-toggle-bars::after { content: ''; position: absolute; left: 0; }
.tb-nav-toggle-bars::before { top: -5px; }
.tb-nav-toggle-bars::after { top: 5px; }
.tb-nav-toggle[aria-expanded="true"] .tb-nav-toggle-bars { background: transparent; }
.tb-nav-toggle[aria-expanded="true"] .tb-nav-toggle-bars::before { transform: translateY(5px) rotate(45deg); }
.tb-nav-toggle[aria-expanded="true"] .tb-nav-toggle-bars::after { transform: translateY(-5px) rotate(-45deg); }

.tb-nav-backdrop {
  position: fixed; inset: var(--tb-header-h) 0 0 0; z-index: 55;
  background: rgba(22, 23, 27, 0.4);
  opacity: 0; pointer-events: none;
  transition: opacity 220ms ease;
}
.tb-nav-backdrop[data-open="true"] { opacity: 1; pointer-events: auto; }

@media (max-width: 759.98px) {
  .tb-nav-toggle { display: inline-flex; }
  .tb-nav {
    position: fixed; top: var(--tb-header-h); right: 0; bottom: 0;
    width: min(320px, 84vw);
    background: var(--tb-paper);
    flex-direction: column; align-items: flex-start;
    padding: 2rem var(--tb-gutter);
    gap: 1.5rem;
    transform: translateX(100%);
    transition: transform 240ms ease;
    z-index: 56;
    border-left: 1px solid var(--tb-rule);
  }
  .tb-nav[data-open="true"] { transform: translateX(0); }
  .tb-nav-link { font-size: 1.05rem; }
}

html.tb-nav-lock { overflow: hidden; }

/* ------------------------------------------------------------------ *
 * 2. Hero Stage
 * ------------------------------------------------------------------ */

.tb-hero { padding-top: calc(var(--tb-header-h) + clamp(1rem, 3vw, 2.5rem)); padding-bottom: clamp(1.5rem, 4vw, 3rem); }

.tb-hero-stage {
  background: var(--tb-stage-light);
  border-radius: var(--tb-radius-xl);
  padding: clamp(1.75rem, 3.2vw, 3.5rem);
  display: grid;
  grid-template-columns: 1.55fr 1fr;
  grid-template-rows: auto auto;
  column-gap: clamp(2rem, 4vw, 4rem);
  row-gap: clamp(1.75rem, 3vw, 2.5rem);
  position: relative;
}

.tb-hero-topline {
  grid-column: 1 / -1;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
}
.tb-hero-credentials { font-size: 0.75rem; color: var(--tb-ink-soft); text-align: right; }

.tb-hero-name {
  grid-column: 1; grid-row: 2;
  align-self: center;
}
.tb-hero-name-ko {
  display: block;
  font-size: clamp(2.75rem, 1.9rem + 3.6vw, 6.5rem);
  font-weight: 600;
  color: var(--tb-ink);
}
.tb-hero-name-en {
  display: block;
  margin-top: 0.5rem;
  font-family: var(--tb-font-display);
  font-weight: 500;
  font-size: clamp(1.1rem, 0.9rem + 0.9vw, 1.75rem);
  color: var(--tb-ink-soft);
}

.tb-hero-visual {
  grid-column: 2; grid-row: 2 / 4;
  position: relative;
  border-radius: var(--tb-radius-lg);
  overflow: hidden;
  background: var(--tb-stage-dark);
  min-height: clamp(220px, 26vw, 420px);
  align-self: stretch;
}
.tb-hero-image {
  width: 100%; height: 100%; object-fit: cover;
  /* Report 20 §C: modest brightness/contrast/saturation lift only — the
     image itself, its crop, and its position are unchanged — so the real
     product screenshot reads clearly as real UI rather than a dim,
     washed-out inset next to the warm Stage background. */
  filter: saturate(1.12) contrast(1.08) brightness(1.05);
}
.tb-hero-visual-tag {
  position: absolute; left: 1rem; bottom: 1rem;
  font-family: var(--tb-font-mono);
  font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--tb-dark-ink);
  background: rgba(27, 27, 31, 0.7);
  padding: 0.4em 0.75em;
  border-radius: 999px;
}
.js-tb .tb-hero-visual-shift { transition: transform 200ms linear; will-change: transform; }

.tb-hero-foot {
  grid-column: 1; grid-row: 3;
  display: flex; flex-direction: column; gap: clamp(1.25rem, 2.5vw, 1.75rem);
  align-self: end;
}
.tb-hero-summary {
  font-size: clamp(1rem, 0.92rem + 0.3vw, 1.2rem);
  line-height: 1.6;
  color: var(--tb-ink);
  max-width: 42rem;
}

.tb-axis {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
}
.tb-axis li {
  font-family: var(--tb-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  color: var(--tb-ink-soft);
  padding: 0.45em 0.9em;
  border: 1px solid var(--tb-rule);
  border-radius: 999px;
  display: flex; align-items: center; gap: 0.4em;
}
.tb-axis li:not(:last-child)::after { content: '→'; margin-left: 0.4em; color: var(--tb-rule); }
.tb-axis li.is-current {
  color: var(--tb-ink);
  border-color: var(--tb-lime-ink);
  background: color-mix(in srgb, var(--tb-lime) 22%, transparent);
  font-weight: 600;
}

.tb-hero-cta {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 0.6em;
  font-family: var(--tb-font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--tb-ink);
  padding: 0.85em 1.5em;
  border-radius: 999px;
  background: var(--tb-lime);
  transition: transform 160ms ease, background 160ms ease;
}
.tb-hero-cta:hover { background: var(--tb-lime-bright); transform: translateX(2px); }
.tb-hero-cta:focus-visible { outline-offset: 4px; }

@media (max-width: 1023.98px) {
  .tb-hero-stage {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
  }
  .tb-hero-name { grid-column: 1; grid-row: 2; }
  .tb-hero-visual { grid-column: 1; grid-row: 3; min-height: 260px; }
  .tb-hero-foot { grid-column: 1; grid-row: 4; align-self: start; }
}
@media (max-width: 479.98px) {
  .tb-hero-topline { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
  .tb-hero-credentials { text-align: left; }
  .tb-hero-visual { display: none; }
}

/* ------------------------------------------------------------------ *
 * 3. Career — single Interactive Stage
 * ------------------------------------------------------------------ */

/* Top padding stays generous (Hero→Career breathing room); bottom is
   trimmed — it directly adds to the "dead" distance between Career's
   sticky release and Selected Work becoming visible (see report 17 §2/§5:
   this was one of the two concrete levers used to shorten that gap,
   alongside the Career scene budget itself). */
.tb-career { padding-top: clamp(3rem, 6vw, 5rem); padding-bottom: clamp(1.25rem, 2.5vw, 2rem); }

.tb-career-intro { padding-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.tb-career-heading {
  margin-top: 0.75rem;
  font-size: clamp(2rem, 1.5rem + 2.2vw, 4rem);
  font-weight: 600;
  color: var(--tb-ink);
}

/* Base (no-JS / pre-enhancement) fallback: every scene stacked in normal
   reading flow, fully visible and readable without any script running. */
.tb-career-panels {
  display: flex; flex-direction: column; gap: 1px;
  background: var(--tb-dark-rule);
}
.tb-career-panel {
  background: var(--tb-stage-light);
  padding: clamp(1.5rem, 3vw, 2.5rem);
}

/* Once JS confirms it's running, switch to the interactive scroll-driven
   Stage. This class is added by JS at runtime only — never present in the
   static HTML — so a no-JS visit always gets the readable stacked list
   above, matching this project's established progressive-enhancement
   pattern (same idea as the old .js-hero-parallax flag, written fresh).
   --tb-career-stage-h is declared ONCE here (on `.tb-career`, the shared
   ancestor) and referenced everywhere else — a real bug in an earlier
   revision came from the same clamp() being duplicated as an inline
   fallback in two separate rules, which is exactly the kind of drift a
   single declaration avoids. --tb-scene-scroll-px only sizes
   `.tb-career-scroll` as a PRE-JS fallback now (report 17 §2): the actual
   per-scene scroll budget is no longer an equal share — it's an unequal,
   deliberately short-tailed schedule computed in
   v7-tabella-prototype.js's `layoutCareer()`, which sets this element's
   height directly via inline style (always wins over this calc()) within
   the same tick the script runs. */
.tb-career {
  --tb-career-stage-h: clamp(520px, 68vh, 720px);
  --tb-scene-scroll-px: clamp(220px, 27vh, 320px);
}
.js-tb .tb-career-scroll {
  height: calc(var(--tb-career-stage-h) + var(--tb-scene-count, 4) * var(--tb-scene-scroll-px));
  position: relative;
}
.js-tb .tb-career-pin {
  position: sticky;
  top: var(--tb-header-h);
  height: var(--tb-career-stage-h);
  display: flex; align-items: center;
}
.js-tb .tb-career-stage-wrap { width: 100%; }

.tb-career-stage {
  width: 100%;
  height: var(--tb-career-stage-h, clamp(520px, 68vh, 720px));
  background: var(--tb-stage-dark);
  border-radius: var(--tb-radius-xl);
  padding: clamp(1.5rem, 3vw, 2.75rem);
  display: flex; flex-direction: column;
  position: relative;
  overflow: hidden;
}

.tb-career-stage-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem;
  flex: none;
}
.tb-career-controls { display: flex; align-items: center; gap: 1rem; }
.tb-career-index {
  font-family: var(--tb-font-mono);
  font-size: 0.8rem;
  color: var(--tb-dark-ink-soft);
}
.tb-career-index-current { color: var(--tb-lime-bright); font-weight: 600; }
.tb-career-buttons { display: flex; gap: 0.5rem; }
.tb-career-btn {
  width: 2.5rem; height: 2.5rem;
  border-radius: 50%;
  border: 1px solid var(--tb-dark-rule);
  color: var(--tb-dark-ink);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.1rem;
  transition: background 160ms ease, border-color 160ms ease, opacity 160ms ease;
}
.tb-career-btn:hover:not(:disabled) { background: rgba(243,241,234,0.1); border-color: var(--tb-dark-ink-soft); }
.tb-career-btn:disabled { opacity: 0.3; cursor: default; }

/* Interactive panel positioning only applies once JS is confirmed running
   (see .js-tb note above) — pre-enhancement, .tb-career-panel stays in
   normal flow per the base rules further up. */
.js-tb .tb-career-panels {
  position: relative;
  flex: 1;
  margin-top: clamp(1rem, 2.5vw, 2rem);
  background: none;
}
.js-tb .tb-career-panel {
  /* No overflow:auto / max-height here on purpose — a real bug found in
     QA: any element with overflow:auto captures wheel input once the
     cursor is over it, which is exactly what made Career feel "stuck" to
     native mouse-wheel/trackpad scrolling. Content is sized (padding,
     type scale, --tb-career-stage-h above) to fit without clipping
     instead; see report §1/§2 for the measured proof. */
  position: absolute; top: 50%; left: 50%;
  width: min(660px, 90%);
  overflow: visible;
  border-radius: var(--tb-radius-lg);
  background: var(--tb-stage-light);
  box-shadow: 0 24px 48px -24px rgba(0,0,0,0.35);
  transition: transform 400ms cubic-bezier(.22,.61,.36,1), opacity 400ms ease;
}
.js-tb .tb-career-panel[data-rel="active"] {
  transform: translate(-50%, -54%) scale(1);
  opacity: 1; z-index: 3; pointer-events: auto;
}
.js-tb .tb-career-panel[data-rel="prev"] {
  transform: translate(-108%, -42%) scale(0.82);
  opacity: 0.5; z-index: 2; pointer-events: none;
}
.js-tb .tb-career-panel[data-rel="next"] {
  transform: translate(8%, -66%) scale(0.82);
  opacity: 0.5; z-index: 2; pointer-events: none;
}
.js-tb .tb-career-panel[data-rel="far"] {
  transform: translate(-50%, -50%) scale(0.7);
  opacity: 0; z-index: 1; pointer-events: none;
}

.tb-scene-role { font-size: 0.8rem; color: var(--tb-ink-soft); }
.tb-scene-company {
  margin-top: 0.15rem;
  font-size: clamp(1.4rem, 1.2rem + 1vw, 2rem);
  font-weight: 600;
}
.tb-scene-company-sub { font-family: var(--tb-font-body); font-weight: 400; font-size: 0.6em; color: var(--tb-ink-soft); }
.tb-scene-message { margin-top: 0.6rem; font-size: 0.95rem; color: var(--tb-ink); max-width: 34rem; line-height: 1.6; }

.tb-metric-group { margin-top: 1.25rem; display: flex; align-items: baseline; gap: clamp(0.6rem, 1.6vw, 1.1rem); flex-wrap: wrap; }
.tb-metric-value { font-family: var(--tb-font-display); font-weight: 600; font-size: clamp(1.75rem, 1.3rem + 2vw, 3.25rem); color: var(--tb-ink); }
.tb-metric-arrow { color: var(--tb-lime-ink); font-size: 1.4rem; }
.tb-metric-caption { margin-top: 0.35rem; color: var(--tb-ink-soft); }

.tb-scene-tags { margin-top: 0.85rem; font-size: 0.85rem; color: var(--tb-ink-soft); }

.tb-pair-row { margin-top: 1rem; display: flex; flex-wrap: wrap; gap: 0.6rem; }
.tb-pair {
  display: inline-flex; align-items: center; gap: 0.5em;
  font-family: var(--tb-font-mono); font-size: 0.8rem;
  padding: 0.4em 0.75em; border: 1px solid var(--tb-rule); border-radius: 999px;
  color: var(--tb-ink);
}
.tb-pair span:last-child { color: var(--tb-lime-ink); font-weight: 600; }

.tb-scene-stats { margin-top: 1.1rem; display: flex; flex-wrap: wrap; gap: 1.25rem 2rem; }
.tb-scene-stats div { display: flex; flex-direction: column; gap: 0.15rem; }
.tb-scene-stats dt { font-size: 0.72rem; color: var(--tb-ink-soft); }
.tb-scene-stats dd { margin: 0; font-family: var(--tb-font-mono); font-size: 0.85rem; }

.tb-scene-date { margin-top: 1.25rem; color: var(--tb-ink-soft); }

/* transform pair — 링크샵스 */
.tb-transform-pair { margin-top: 1.25rem; display: flex; align-items: center; gap: clamp(1rem, 2.5vw, 2rem); flex-wrap: wrap; }
.tb-transform-side { display: flex; flex-direction: column; gap: 0.2rem; }
.tb-transform-label { color: var(--tb-ink-soft); }
.tb-transform-value { font-family: var(--tb-font-display); font-weight: 600; font-size: clamp(1.15rem, 1rem + 0.6vw, 1.6rem); }
.tb-transform-note { font-size: 0.8rem; color: var(--tb-ink-soft); }
.tb-transform-arrow { color: var(--tb-lime-ink); font-size: 1.3rem; }

/* hybrid pair — 알티엠, uses ↔ to read as coexistence, not sequence */
.tb-hybrid-pair { margin-top: 1.25rem; display: flex; align-items: center; gap: clamp(1rem, 2.5vw, 2rem); flex-wrap: wrap; }
.tb-hybrid-side { display: flex; flex-direction: column; gap: 0.2rem; }
.tb-hybrid-value { font-family: var(--tb-font-display); font-weight: 600; font-size: clamp(1.15rem, 1rem + 0.6vw, 1.6rem); }
.tb-hybrid-note { font-size: 0.8rem; color: var(--tb-ink-soft); }
.tb-hybrid-arrow { color: var(--tb-lime-ink); font-size: 1.3rem; }

/* transition flow — AI Systems */
.tb-flow { margin-top: 1.25rem; display: flex; flex-wrap: wrap; gap: 0.5rem 0; align-items: center; }
.tb-flow-chip {
  font-size: 0.8rem; padding: 0.5em 0.9em; border-radius: 999px;
  border: 1px solid var(--tb-rule); color: var(--tb-ink-soft);
}
.tb-flow-chip.is-human { color: var(--tb-ink); border-color: var(--tb-lime-ink); background: color-mix(in srgb, var(--tb-lime) 24%, transparent); font-weight: 600; }
.tb-flow li:not(:last-child)::after { content: '→'; margin: 0 0.5rem; color: var(--tb-rule); }
.tb-scene-note { margin-top: 0.9rem; font-size: 0.85rem; color: var(--tb-ink-soft); max-width: 32rem; }

.tb-career-more { padding-top: clamp(0.75rem, 1.5vw, 1.25rem); }
.tb-career-more a { color: var(--tb-lime-ink); border-bottom: 1px solid currentColor; padding-bottom: 2px; }
.tb-career-more a:hover, .tb-career-more a:focus-visible { color: var(--tb-lime-ink); opacity: 0.75; }

@media (max-width: 759.98px) {
  .js-tb .tb-career-scroll { height: auto; }
  .js-tb .tb-career-pin { position: static; height: auto; }
  .tb-career-stage { height: auto; min-height: 0; }
  /* Real bug found via an actual button click (not a synthetic scrollTo):
     the desktop absolute-positioned/centered panel could be taller than
     `.tb-career-panels`' fixed min-height at narrow widths (more text
     wrapping = taller panel), so it visually overflowed upward and
     physically covered the prev/next buttons, blocking real clicks. Fixed
     by dropping the desktop peek-carousel positioning entirely on mobile
     — there is nothing to peek at anyway, since prev/next are hidden here
     — in favour of plain normal-flow layout that can never overlap
     anything, with only the active panel ever in flow. */
  .js-tb .tb-career-panels { position: relative; min-height: 0; }
  /* Matching the [data-rel="…"] attribute selector's specificity (0,3,0)
     here — not just the plain .tb-career-panel (0,2,0) — was the actual
     fix: without it, the desktop rule's `transform: translate(-50%,-54%)
     scale(1)` on [data-rel="active"] still won the cascade even though
     `position` correctly flipped to static, leaving the panel skewed
     up-left off a now-static box (caught from an actual screenshot, not
     just the earlier click-target check). */
  .js-tb .tb-career-panel,
  .js-tb .tb-career-panel[data-rel] {
    position: static;
    width: 100%; max-width: none;
    transform: none;
    display: none;
    opacity: 1;
    box-shadow: none;
    z-index: auto;
  }
  .js-tb .tb-career-panel[data-rel="active"] { display: block; }
}

/* ------------------------------------------------------------------ *
 * 4. Selected Work Stage
 * ------------------------------------------------------------------ */

/* Top trimmed for the same reason as .tb-career's bottom padding above —
   less empty space to cross before Selected Work reads as "arrived".
   Bottom stays generous (Selected Work→Current Focus isn't part of this
   issue). */
.tb-work { padding-top: clamp(1.5rem, 3vw, 2.25rem); padding-bottom: clamp(3rem, 6vw, 5rem); }

.tb-work-stage {
  border-radius: var(--tb-radius-xl);
  padding: clamp(1.5rem, 3vw, 2.75rem);
  transition: background 400ms ease;
}
.tb-work-stage[data-active="trpg"] { background: var(--tb-stage-dark); }
.tb-work-stage[data-active="legal"] { background: var(--tb-stage-light-alt); }

.tb-work-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.tb-work-tabs { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.tb-work-tab {
  font-size: 0.85rem; padding: 0.55em 1.1em; border-radius: 999px;
  border: 1px solid var(--tb-rule);
  color: var(--tb-ink-soft);
}
[data-active="trpg"] .tb-work-tab { border-color: var(--tb-dark-rule); color: var(--tb-dark-ink-soft); }
.tb-work-tab[aria-selected="true"] {
  color: var(--tb-ink); border-color: var(--tb-lime-ink);
  background: color-mix(in srgb, var(--tb-lime) 22%, transparent);
  font-weight: 600;
}
[data-active="trpg"] .tb-work-tab[aria-selected="true"] { color: var(--tb-dark-ink); }

.tb-work-panels {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  display: grid;
  grid-template-areas: "panel";
}
.tb-work-panel {
  grid-area: panel;
  display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(1.5rem, 3vw, 3rem);
  align-items: center;
  transition: opacity 380ms ease, transform 380ms ease;
}
/* Outgoing project recedes (shrinks slightly + settles down) rather than
   a flat opacity swap; incoming project expands from center — same
   "pulled toward/away from the reader" language as the Stage reveal
   system, applied to the tab switch instead of scroll position. */
.tb-work-panel:not(.is-active) { opacity: 0; transform: translateY(10px) scale(0.97); pointer-events: none; }
.tb-work-panel.is-active { opacity: 1; transform: none; }

.tb-work-media { border-radius: var(--tb-radius-lg); overflow: hidden; }
.tb-work-media img { width: 100%; height: 100%; object-fit: cover; }

.tb-work-tag { font-family: var(--tb-font-mono); font-size: 0.75rem; letter-spacing: 0.04em; }
[data-active="trpg"] .tb-work-tag { color: var(--tb-oxide-bright); }
[data-active="legal"] .tb-work-tag { color: var(--tb-lime-ink); }

.tb-work-title { margin-top: 0.5rem; font-size: clamp(1.4rem, 1.2rem + 1vw, 2rem); }
[data-active="trpg"] .tb-work-title { color: var(--tb-dark-ink); }
[data-active="legal"] .tb-work-title { color: var(--tb-ink); }

.tb-work-desc { margin-top: 0.6rem; font-size: 0.95rem; line-height: 1.6; max-width: 34rem; }
[data-active="trpg"] .tb-work-desc { color: var(--tb-dark-ink-soft); }
[data-active="legal"] .tb-work-desc { color: var(--tb-ink-soft); }

.tb-work-flow { margin-top: 1rem; display: flex; flex-wrap: wrap; font-family: var(--tb-font-mono); font-size: 0.78rem; }
[data-active="trpg"] .tb-work-flow { color: var(--tb-dark-ink-soft); }
[data-active="legal"] .tb-work-flow { color: var(--tb-ink-soft); }
.tb-work-flow li:not(:last-child)::after { content: '→'; margin: 0 0.5rem; opacity: 0.5; }
.tb-work-flow li.is-final { color: var(--tb-lime-ink); font-weight: 600; }
[data-active="trpg"] .tb-work-flow li.is-final { color: var(--tb-oxide-bright); }

.tb-work-insight { margin-top: 1rem; font-size: 0.85rem; max-width: 32rem; }
[data-active="trpg"] .tb-work-insight { color: var(--tb-dark-ink); }
[data-active="legal"] .tb-work-insight { color: var(--tb-ink); }

.tb-work-roles { margin-top: 1rem; display: flex; flex-direction: column; gap: 0.6rem; }
.tb-work-role { display: flex; gap: 0.6rem; align-items: baseline; font-size: 0.85rem; }
.tb-work-role-num { font-family: var(--tb-font-mono); color: var(--tb-lime-ink); font-weight: 600; }
[data-active="legal"] .tb-work-role-title { font-weight: 600; }

.tb-work-tech { margin-top: 1rem; }
[data-active="trpg"] .tb-work-tech { color: var(--tb-dark-ink-soft); }
[data-active="legal"] .tb-work-tech { color: var(--tb-ink-soft); }

.tb-work-cta { margin-top: 1.25rem; display: inline-flex; gap: 0.5em; font-weight: 600; border-bottom: 1px solid currentColor; padding-bottom: 2px; }
[data-active="trpg"] .tb-work-cta { color: var(--tb-oxide-bright); }
[data-active="legal"] .tb-work-cta { color: var(--tb-lime-ink); }

@media (max-width: 759.98px) {
  .tb-work-panel { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------------ *
 * 5. Current Focus — asymmetric, not a 3-up card grid
 * ------------------------------------------------------------------ */

/* Top trimmed (report 20 §A) — less empty scroll distance before this
   dark section's content-bearing area arrives, complementing the earlier
   reveal-threshold fix. Bottom stays generous (Focus→Closing spacing
   isn't part of this issue). */
.tb-focus { padding-top: clamp(1.75rem, 3.5vw, 2.75rem); padding-bottom: clamp(3rem, 6vw, 5rem); background: var(--tb-stage-dark); color: var(--tb-dark-ink); }

.tb-focus-grid {
  display: grid; grid-template-columns: 1.7fr 1fr;
  gap: clamp(1.5rem, 3vw, 3rem);
}
.tb-focus-lead {
  border-top: 1px solid var(--tb-dark-rule);
  padding-top: clamp(1.25rem, 2.5vw, 2rem);
}
.tb-focus-lead .tb-focus-name { margin-top: 0.6rem; font-size: clamp(1.75rem, 1.3rem + 2vw, 3rem); font-family: var(--tb-font-display); font-weight: 600; }
.tb-focus-lead .tb-mono { display: block; margin-top: 0.75rem; color: var(--tb-dark-ink-soft); }

.tb-focus-side { display: flex; flex-direction: column; gap: clamp(1.5rem, 3vw, 2rem); }
.tb-focus-item {
  border-top: 1px solid var(--tb-dark-rule);
  padding-top: 1rem;
  transition: transform 180ms ease, border-color 180ms ease;
}
.tb-focus-item .tb-focus-name { margin-top: 0.4rem; font-size: 1.1rem; font-weight: 600; }
.tb-focus-item .tb-mono { display: block; margin-top: 0.5rem; color: var(--tb-dark-ink-soft); }
/* Low-intensity per report §4: a small nudge only, no scale/opacity show. */
.tb-focus-item:hover { transform: translateX(3px); border-color: var(--tb-dark-ink-soft); }

@media (max-width: 759.98px) {
  .tb-focus-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------------ *
 * 6. Closing — echoes the Hero's light Stage
 * ------------------------------------------------------------------ */

.tb-closing { padding-block: clamp(3rem, 6vw, 5rem); }
.tb-closing-stage {
  background: var(--tb-stage-light);
  border-radius: var(--tb-radius-xl);
  padding: clamp(2.5rem, 6vw, 5.5rem);
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: clamp(1.5rem, 3vw, 2.25rem);
}
.tb-closing-statement {
  max-width: 42rem;
  font-size: clamp(1.15rem, 1rem + 0.8vw, 1.6rem);
  line-height: 1.55;
  color: var(--tb-ink);
}
.tb-closing-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; }
.tb-closing-cta {
  display: inline-flex; align-items: center; gap: 0.5em;
  padding: 0.85em 1.6em; border-radius: 999px;
  font-weight: 600;
  background: var(--tb-lime); color: var(--tb-ink);
  transition: background 160ms ease;
}
.tb-closing-cta--secondary { background: transparent; border: 1px solid var(--tb-rule); color: var(--tb-ink); }
.tb-closing-cta:hover { background: var(--tb-lime-bright); }
.tb-closing-cta--secondary:hover { border-color: var(--tb-lime-ink); background: transparent; }

/* ------------------------------------------------------------------ *
 * 7. Footer
 * ------------------------------------------------------------------ */

.tb-footer { padding-block: 2rem; border-top: 1px solid var(--tb-rule); }
.tb-footer-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; font-size: 0.85rem; color: var(--tb-ink-soft); }
.tb-footer-row nav { display: flex; gap: 1.25rem; }
.tb-footer-row a:hover { color: var(--tb-ink); }

/* ------------------------------------------------------------------ *
 * 8. Subpages — shared "Page Intro" Stage (About / Full Career History /
 * Portfolio detail). Echoes the Hero's light Stage register on purpose
 * (same background/radius token) rather than inventing a second visual
 * language for these pages — the brief's "keep as-is" list is explicit
 * that no new v8-style design direction should appear here. This is the
 * one Stage per subpage that carries `.tb-entrance-stage` (medium tier —
 * see v7-tabella-prototype.js §5 `pageIntro`); the rest of each subpage
 * is normal static content, deliberately not re-wrapped in its own
 * entrance Stage per sub-section (constraint: "one content frame expands
 * as a single stage", not a repeating effect down the page).
 * ------------------------------------------------------------------ */
.tb-page-intro { padding-top: calc(var(--tb-header-h) + clamp(1rem, 3vw, 2.5rem)); padding-bottom: clamp(1.5rem, 4vw, 3rem); }
/* Report 21: this was the actual bug — `max-width: 46rem` here capped the
   OUTER Stage frame itself, not just its text, so the settled state could
   never fill the section (measured live: 736px / 38% of a 1920px
   viewport, left-aligned). The frame is now full-width like every other
   Stage on the site; the reading-width cap moved to `.tb-page-intro-
   reading` below, so text still doesn't stretch edge-to-edge. */
.tb-page-intro-stage {
  background: var(--tb-stage-light);
  border-radius: var(--tb-radius-xl);
  padding: clamp(2rem, 4.5vw, 4rem);
  width: 100%;
}
/* Inner reading column — the brief's "outer Stage frame vs. inner reading
   column" split. Left-aligned (not centered) to match the same
   left-aligned-text-in-a-wide-Stage convention the Hero already uses. */
.tb-page-intro-reading { max-width: 46rem; }
.tb-page-intro-heading { margin-top: 0.75rem; font-size: clamp(2rem, 1.5rem + 2.4vw, 3.75rem); }
.tb-page-intro-lead { margin-top: 1rem; font-size: clamp(1rem, 0.92rem + 0.3vw, 1.2rem); line-height: 1.65; color: var(--tb-ink); max-width: 40rem; }
.tb-page-intro-meta { margin-top: 1.25rem; font-size: 0.8rem; color: var(--tb-ink-soft); }

.tb-section { padding-block: clamp(2rem, 4vw, 3.5rem); }
.tb-section-heading { font-size: clamp(1.4rem, 1.2rem + 1vw, 2rem); }
.tb-section-lead { margin-top: 0.75rem; font-size: 0.95rem; line-height: 1.65; color: var(--tb-ink-soft); max-width: 42rem; }

/* ------------------------------------------------------------------ *
 * 9. Full Career History
 * ------------------------------------------------------------------ */
.tb-history-group { padding-block: clamp(1.5rem, 3vw, 2.5rem); }
.tb-history-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; border-bottom: 1px solid var(--tb-rule); padding-bottom: 1rem; }
.tb-history-group-title { font-size: clamp(1.15rem, 1rem + 0.5vw, 1.5rem); }
.tb-history-group-note { font-size: 0.8rem; color: var(--tb-ink-soft); }

.tb-history-list { margin-top: 1.5rem; display: flex; flex-direction: column; gap: 1rem; }
.tb-history-card {
  background: var(--tb-stage-light);
  border-radius: var(--tb-radius-lg);
  padding: clamp(1.25rem, 2.5vw, 2rem);
}
.tb-history-card .tb-scene-message { margin-top: 0.5rem; max-width: 46rem; }
.tb-history-card .tb-scene-tags { margin-top: 0.75rem; }
.tb-history-card .tb-scene-stats { margin-top: 0.9rem; }
.tb-history-card .tb-scene-date { margin-top: 1rem; }
.tb-history-projects { margin-top: 0.9rem; display: flex; flex-direction: column; gap: 0.35rem; }
.tb-history-projects li { font-size: 0.85rem; color: var(--tb-ink); padding-left: 1rem; position: relative; }
.tb-history-projects li::before { content: '—'; position: absolute; left: 0; color: var(--tb-lime-ink); }

/* Compact tier (1999-2014): denser card, collapsed by default on JS-on
   pages via <details>/<summary> — company name/period/title stay in the
   <summary> so they're readable with JS disabled or by a screen reader
   without any interaction (constraint: "핵심 정보는 JS 비활성/접근성 도구에서도
   읽혀야"). No extra script needed — native <details> already handles
   toggle + keyboard + no-JS fallback (open by default via the `open`
   attribute in HTML, since no-JS should show full content, not force a
   click). */
.tb-history-compact-list { margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.75rem; }
.tb-history-compact {
  background: var(--tb-stage-light);
  border-radius: var(--tb-radius-md);
  padding: 0.25rem clamp(1rem, 2vw, 1.5rem);
}
.tb-history-compact summary {
  cursor: pointer; list-style: none;
  padding: 0.9rem 0;
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.tb-history-compact summary::-webkit-details-marker { display: none; }
.tb-history-compact-title { font-family: var(--tb-font-display); font-weight: 600; font-size: 1.05rem; }
.tb-history-compact-title span { font-family: var(--tb-font-body); font-weight: 400; font-size: 0.8rem; color: var(--tb-ink-soft); margin-left: 0.5em; }
.tb-history-compact-period { font-family: var(--tb-font-mono); font-size: 0.78rem; color: var(--tb-ink-soft); display: flex; align-items: center; gap: 0.5em; }
.tb-history-compact-chevron { transition: transform 200ms ease; }
.tb-history-compact[open] .tb-history-compact-chevron { transform: rotate(180deg); }
.tb-history-compact-body { padding-bottom: 1.1rem; border-top: 1px solid var(--tb-rule); padding-top: 0.9rem; }
.tb-history-compact-body p { font-size: 0.85rem; color: var(--tb-ink-soft); }
.tb-history-compact-body .tb-history-projects { margin-top: 0.6rem; }
.tb-history-compact-body .tb-mono { display: block; margin-top: 0.6rem; }

.tb-history-more { padding-top: clamp(1.5rem, 3vw, 2.5rem); text-align: center; }
.tb-history-more a { color: var(--tb-lime-ink); border-bottom: 1px solid currentColor; padding-bottom: 2px; }

/* ------------------------------------------------------------------ *
 * 10. About
 * ------------------------------------------------------------------ */
.tb-about-body { padding-block: clamp(1.5rem, 3vw, 2.5rem); max-width: 44rem; display: flex; flex-direction: column; gap: 1.25rem; }
.tb-about-body p { font-size: clamp(0.98rem, 0.92rem + 0.2vw, 1.1rem); line-height: 1.75; color: var(--tb-ink); }
.tb-about-axis { padding-block: clamp(1.5rem, 3vw, 2.5rem); border-top: 1px solid var(--tb-rule); }
.tb-about-facts { margin-top: 1.5rem; display: flex; flex-wrap: wrap; gap: 1.25rem 2.5rem; }
.tb-about-facts div { display: flex; flex-direction: column; gap: 0.2rem; }
.tb-about-facts dt { font-size: 0.75rem; color: var(--tb-ink-soft); }
.tb-about-facts dd { margin: 0; font-family: var(--tb-font-mono); font-size: 0.9rem; }

/* ------------------------------------------------------------------ *
 * 11. Portfolio detail
 * ------------------------------------------------------------------ */
.tb-detail-media { margin-top: clamp(1.5rem, 3vw, 2.5rem); border-radius: var(--tb-radius-lg); overflow: hidden; background: var(--tb-stage-dark); }
.tb-detail-media img { width: 100%; height: auto; object-fit: cover; }
.tb-detail-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
.tb-detail-aside { display: flex; flex-direction: column; gap: 1.5rem; position: sticky; top: calc(var(--tb-header-h) + 1.5rem); }
.tb-detail-aside-block { padding-top: 1rem; border-top: 1px solid var(--tb-rule); }
.tb-detail-aside-block h3 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--tb-ink-soft); font-family: var(--tb-font-mono); font-weight: 500; }
.tb-detail-aside-block p, .tb-detail-aside-block ul { margin-top: 0.5rem; font-size: 0.88rem; color: var(--tb-ink); line-height: 1.55; }
.tb-detail-aside-block li { padding-left: 0.9rem; position: relative; }
.tb-detail-aside-block li::before { content: '—'; position: absolute; left: 0; color: var(--tb-lime-ink); }
.tb-detail-body { display: flex; flex-direction: column; gap: 2rem; }
.tb-detail-body h2 { font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.7rem); }
.tb-detail-body p { margin-top: 0.65rem; font-size: 0.98rem; line-height: 1.7; color: var(--tb-ink); max-width: 42rem; }
.tb-detail-callout {
  background: var(--tb-stage-light-alt);
  border-radius: var(--tb-radius-lg);
  padding: clamp(1.25rem, 2.5vw, 2rem);
}
.tb-detail-callout p { margin-top: 0; font-weight: 500; }
.tb-detail-tradeoff { margin-top: 0.75rem; display: flex; flex-direction: column; gap: 0.6rem; }
.tb-detail-tradeoff div { display: flex; gap: 0.75rem; font-size: 0.9rem; align-items: baseline; }
.tb-detail-tradeoff dt { flex: none; width: 6.5rem; font-family: var(--tb-font-mono); font-size: 0.78rem; color: var(--tb-lime-ink); }
.tb-detail-tradeoff dd { margin: 0; color: var(--tb-ink); }
.tb-detail-cta { padding-top: 1rem; }

@media (max-width: 900px) {
  .tb-detail-grid { grid-template-columns: 1fr; }
  .tb-detail-aside { position: static; }
}
