/* Toggle AI — landing page.
   Implements Figma "랜딩페이지 1920*1080": 2377:74052 (light) and 2377:73898 (dark).

   THE PAGE IS THE FIGMA FRAME. It is laid out once at a fixed design width and the whole thing
   is scaled to the window — see `.frame`. There are no breakpoints and no reflow: the 1200px
   column keeps its proportions and the screen always sits beside the description it explains.
   A narrower window gets the same picture, smaller.

   Most numbers below are literal Figma pixels. TWO GROUPS DELIBERATELY ARE NOT, and say so
   where they appear (`[off-Figma]`): the TYPE SCALE — Figma draws almost the whole page at
   weight 500 in three sizes, which reads flat once it is type on a screen rather than boxes on
   a canvas — and the VERTICAL SECTION RHYTHM, whose gaps were measured on a 1920 artboard and
   left most of a viewport empty between the last feature row and the closing CTA. Interaction
   states are a third addition but not a departure: Figma draws one resting state per element
   and says nothing about the others, and a page where nothing answers the pointer reads as a
   page that is not wired up yet.
   The two frames are the same layout bound to the same Figma variables, so the whole
   theme swap is the token block below — nothing else in this file branches on theme.
   Icons are drawn as CSS masks over `currentColor` rather than <img>, because the
   exported SVGs bake a single fill/stroke that would be invisible in the other theme. */

:root {
  color-scheme: light dark;

  /* Figma variables, light values */
  --sage-1: #fbfdfc;
  --sage-2: #f7f9f8;
  --sage-3: #eef1f0;
  --sage-4: #e6e9e8;
  --sage-5: #dfe2e0;
  --sage-8: #b8bcba;
  --sage-11: #5f6563;
  --sage-12: #1a211e;
  --sage-alpha-12: rgba(0, 8, 5, 0.9);
  --text: #000000;
  --brand-1: #f4fcfa;
  --brand-10: #008c79;
  --brand-12: #04362f;

  /* raw hexes the design does not bind to a variable */
  --on-brand: #ffffff;        /* label on the brand-filled button */
  --custom-alpha-12: rgba(0, 0, 0, 0.87);
  --kbd-bg: #d4dfdc;
  --chip-bg: rgba(255, 255, 255, 0.34);
  /* Pointer-response values. One step along the same ramp the resting colour came from, never
     a new hue — a hover that changes the hue reads as a different button, not the same one
     under a cursor. */
  --brand-10-hover: #00705f;
  --chip-bg-hover: rgba(255, 255, 255, 0.62);
  /* The carousel chip, straight off Figma's own export of `BUTTON` (2377:74222 light,
     2377:74826 dark). It is a NEUTRAL grey and a translucent one — it belongs to no ramp on
     this page, so it gets its own two values rather than being bent onto the nearest sage. */
  --guide-nav-bg: #e6e6e6;
  --guide-nav-alpha: 0.5;
  /* The dropdown's surface. Figma draws this component in the LIGHT frame only, and its answer
     there — Sage/1 with an offset drop-shadow and no border — is exactly right on a white page.
     On the dark one it is the page's own colour under a black shadow, so the menu disappears.
     Dark therefore lifts the way everything else on this page lifts in the dark: one surface
     step up, with a hairline. Same reasoning as `.chip__desc`. */
  --lnb-bg: var(--sage-1);
  --lnb-edge: transparent;
  /* Frame 293's own fill, and the colour Rectangle 14 fades from — the same value, because
     the rectangle IS that band bleeding down into the page ground below it. */
  --band: #fefefe;
  --discord: #525eed;

  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --sage-1: #101211;
    --sage-2: #171918;
    --sage-3: #202221;
    --sage-4: #272a29;
    /* the ramp's own next step; the light value is Figma's, this is Radix sage dark 5 */
    --sage-5: #2e3130;
    --sage-8: #5b625f;
    --sage-11: #b0b4b2;
    --sage-12: #eceeed;
    --sage-alpha-12: rgba(253, 255, 254, 0.93);
    --text: #ffffff;
    --brand-1: #061916;
    --brand-10: #1ad3b8;
    --brand-12: #e1fcf6;
    --on-brand: #000000;
    --custom-alpha-12: rgba(253, 253, 255, 0.94);
    --kbd-bg: #202624;
    --chip-bg: rgba(0, 0, 0, 0.8);
    --band: #0c0c0c;
    --brand-10-hover: #45e0c9;
    --chip-bg-hover: rgba(0, 0, 0, 0.92);
    --guide-nav-bg: #ffffff;
    --guide-nav-alpha: 0.57;
    --lnb-bg: var(--sage-2);
    --lnb-edge: var(--sage-4);
  }
}

/* explicit override, so the theme can be forced without touching the media query */
:root[data-theme="dark"] {
  --sage-1: #101211;
  --sage-2: #171918;
  --sage-3: #202221;
  --sage-4: #272a29;
  /* the ramp's own next step; the light value is Figma's, this is Radix sage dark 5 */
  --sage-5: #2e3130;
  --sage-8: #5b625f;
  --sage-11: #b0b4b2;
  --sage-12: #eceeed;
  --sage-alpha-12: rgba(253, 255, 254, 0.93);
  --text: #ffffff;
  --brand-1: #061916;
  --brand-10: #1ad3b8;
  --brand-12: #e1fcf6;
  --on-brand: #000000;
  /* Missing here while the media query above had it, so forcing dark with the attribute left
     the stage's bezel drawn in the LIGHT theme's near-black — on a near-black page. */
  --custom-alpha-12: rgba(253, 253, 255, 0.94);
  --kbd-bg: #202624;
  --chip-bg: rgba(0, 0, 0, 0.8);
  --band: #0c0c0c;
  --brand-10-hover: #45e0c9;
  --chip-bg-hover: rgba(0, 0, 0, 0.92);
  --guide-nav-bg: #ffffff;
  --guide-nav-alpha: 0.57;
  --lnb-bg: var(--sage-2);
  --lnb-edge: var(--sage-4);
}

* { box-sizing: border-box; }

/* ONE focus ring for the whole page. Every interactive element here paints its own background,
   so the browser's default outline lands on top of a shape it knows nothing about; a brand ring
   held off the edge reads the same on a pill, a square button and a bare icon. `:where()` keeps
   it at zero specificity, so any component that wants its own can simply say so. */
:where(a, button, summary):focus-visible {
  outline: 2px solid var(--brand-10);
  outline-offset: 3px;
}

/* Nothing on this page moves on its own — every transition below is an answer to a pointer,
   and they are short enough to read as "this is live" rather than as animation. The one
   exception is the smooth scroll, which moves without being touched, so it comes off here too. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* The frame is 1920 wide whatever the window is, and one transform brings it down to size.
   It is never scaled UP: past 1920 the design is drawn at its own size and centred, because
   enlarging it past what it was drawn at only softens the screenshots and inflates the type.
   A transform does not occupy layout, so the holder is given the scaled height in script, and
   the same script sets `left` — that is the only thing the page needs JavaScript for.

   `is-scaled` is put on <html> by the page itself, and only when it is actually going to
   scale. That is deliberate: the picture-of-a-page mode is the ENHANCEMENT, and everything
   below `html:not(.is-scaled)` is the plain page it falls back to — on a phone, and on any
   browser where the script did not run. Without that the absolute frame leaves the holder
   0px tall behind `overflow: hidden`, and the whole page is blank. */
.is-scaled .frame-holder { position: relative; overflow: hidden; }
.is-scaled .frame {
  position: absolute;
  top: 0;
  left: 0;
  /* Figma's canvas is 1920, and almost nobody browses at 1920: a 13" laptop is 1440 logical,
     so the whole page came out at 0.75 and its 16px body text landed at 12. The COLUMN is what
     the design actually fixes — 1200px — and the 360px gutters either side of it were a choice
     made for a 1920 artboard. Laying the frame out at 1512 keeps the column at its drawn size
     and puts the scale at ~1 on the laptops people are actually on, at the price of narrower
     margins. The number lives here and nowhere else; the script reads it off the element. */
  width: 1512px;
  transform-origin: top left;
  transform: scale(var(--frame-scale, 1));
}

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--sage-1);
  color: var(--text);
  font: 400 16px/1.5 Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

img { display: block; max-width: 100%; }

.container {
  width: 1200px;
  margin: 0 auto;
}

/* An exported icon carries one baked colour, so it is used as a mask and the colour
   comes from `currentColor` — the same file then works in both themes. */
.icon {
  display: inline-block;
  flex: none;
  width: 24px;
  height: 24px;
  background: currentColor;
  -webkit-mask: var(--i) center / contain no-repeat;
  mask: var(--i) center / contain no-repeat;
}

/* ---------- logo ---------- */

.logo { display: inline-flex; align-items: center; padding: 4px; }
/* only the header's, which is a link — the footer draws the same lockup in a <span> */
.logo[href] { transition: opacity 120ms ease; }
.logo[href]:hover { opacity: 0.72; }
.logo__mark { position: relative; width: 26px; height: 26px; overflow: hidden; flex: none; }
/* the export is a 208px artboard cropped to the 26px mark — offsets are Figma's */
.logo__mark img { position: absolute; width: 208.306px; height: 208.306px; max-width: none; left: -96.8px; top: -90.75px; }
.logo__word {
  width: 122px;
  height: 23px;
  background: var(--text);
  -webkit-mask: url(assets/logo-text.svg) center / contain no-repeat;
  mask: url(assets/logo-text.svg) center / contain no-repeat;
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 47px;
  width: 213px;
  padding: 10px;
  border: 0;
  border-radius: var(--radius);
  font-weight: 700;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, transform 120ms ease;
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--brand-10); color: var(--on-brand); }
.btn--primary:hover { background: var(--brand-10-hover); }
.btn--soft { background: var(--sage-2); color: var(--text); }
.btn--soft:hover { background: var(--sage-3); }
.btn--discord { background: transparent; color: var(--text); border: 1px solid var(--discord); gap: 8px; }
/* The outline fills with the brand it is outlined in. `#fff` is literal rather than a token
   because Discord's blue is the SAME value in both themes, so its foreground is too —
   `--on-brand` would flip to black here and disappear. */
.btn--discord:hover { background: var(--discord); color: #fff; }

/* ---------- header ---------- */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 20px;
  padding-bottom: 20px;
}
/* GNB (2377:74057) is a centred row of GNB_chips, 78px apart. The chips themselves
   (2377:73865) are 14/regular/`leading: normal` — 17px tall — with Brand 12 on hover AND
   pressed. Direct children only: LNB_chip keeps Colors/text in every state. */
.gnb { display: flex; align-items: center; justify-content: center; gap: 78px; }
.gnb > a, .dropdown summary {
  display: inline-flex;
  align-items: flex-end;
  gap: 4px;
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  transition: color 120ms ease;
}
.gnb > a:hover, .gnb > a:active,
.dropdown summary:hover, .dropdown[open] summary { color: var(--brand-12); }
/* Pricing has no page behind it yet. It keeps its resting look — it IS a real nav item — but
   it must not answer the pointer like the ones that go somewhere. */
.gnb a[aria-disabled="true"] { cursor: default; }
.gnb a[aria-disabled="true"]:hover { color: inherit; }
.gnb .icon { width: 13px; height: 13px; }
.header-actions { display: flex; align-items: center; gap: 16px; }
/* Figma: `flex items-center justify-center` on a fixed 110px box. Without the centering
   the 110px width just left-aligns the label and leaves dead space to its right. */
.header-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  font-weight: 500;
  font-size: 16px;
  line-height: 19px;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease;
}
.header-btn:hover { background: var(--sage-2); }
/* after the plain rule, and at the same specificity, so the filled button wins on source order */
.header-btn--strong { width: 110px; background: var(--sage-12); color: var(--sage-1); }
.header-btn--strong:hover { background: var(--sage-11); }

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

/* One ground for the whole page. `See how it works` is a Sage/2 button and has to read as a
   pill against it, so this band is NOT Sage/2 — that is what made it look grey up top. */
/* [off-Figma] 210 → 156. Measured on a 1920 artboard; at the width this frame is actually
   drawn at it opened a gap the eye reads as the end of the page. */
.hero-band { padding-bottom: 156px; }

.hero { text-align: center; padding-top: 127px; }
.pill {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  border: 1px solid var(--sage-2);
  border-radius: 999px;
  background: var(--sage-2);
  color: var(--sage-12);
  font-size: 14px;
}
/* [off-Figma] type scale. Figma: 44px/500/1.2. A headline is the one place on a page that is
   allowed to be loud, and at 44/500 this one was the same voice as everything under it. Bigger,
   heavier, and set tight — 1.2 is a body-text leading and it left the two lines drifting apart.
   The width goes with it: the break has to stay after "ideas,", and 54px needs more room to
   land there. */
.hero h1 {
  max-width: 780px;
  margin: 12px auto 0;
  font-weight: 600;
  font-size: 54px;
  line-height: 1.08;
  letter-spacing: -0.022em;
  color: var(--text);
}
/* [off-Figma] 16/500/1.5 → 17/400/1.65. Five lines of 500 is a wall; dropping it to 400 under a
   600 headline is what makes the two read as heading and body rather than as two paragraphs. */
.hero__lead {
  max-width: 751px;
  margin: 20px auto 0;
  font-size: 17px;
  line-height: 1.65;
  color: var(--sage-12);
}
.hero__cta { display: flex; justify-content: center; gap: 24px; margin-top: 24px; }

/* ---------- hero stage: the product shot plus the four floating chips ---------- */

/* The stage is one fixed 1200x582 composition — the shot and the four chips around it — and
   it is scaled as a piece. Placing the chips in percentages instead put them outside the
   viewport somewhere around 900px wide, because a chip is a fixed-width object hung off a
   proportional offset: the offset shrinks, the chip does not. */
.stage {
  position: relative;
  width: 1200px;
  height: 582px;
  margin: 76px auto 0;
}
/* Figma's own box, bezel included: a 7px near-black frame, which is why the shot inside gets
   1021x568 of the 1035x582. */
.stage__shot {
  position: absolute;
  left: 83px;
  top: 0;
  width: 1035px;
  height: 582px;
  border: 7px solid var(--custom-alpha-12);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 10px 10px 21px 0 rgba(0, 0, 0, 0.1);
}
.stage__shot img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius); }

.chip {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 8px 18px;
  border-radius: 999px;
  background: var(--chip-bg);
  color: var(--brand-12);
  font-weight: 500;
  font-size: 14px;
  line-height: 1.5;
  white-space: nowrap;
  box-shadow: 3px 6px 11px 0 rgba(4, 54, 47, 0.1);
  border: 0;
  font-family: inherit;
  cursor: help;
  /* Hidden by default — stage hover reveals them with float animation */
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 240ms ease, transform 240ms ease, background-color 120ms ease, box-shadow 120ms ease;
}
/* Stage hover — chips appear with floating animation */
.stage:hover .chip { opacity: 1; transform: translateY(0); }
.chip:hover, .chip:focus-visible {
  background: var(--chip-bg-hover);
  box-shadow: 3px 8px 16px 0 rgba(4, 54, 47, 0.16);
  transform: translateY(-1px);
}
/* Figma's own offsets inside the 1200x582 stage, and they are meant to sit ON the shot — the
   two on the left half off its edge, the low one on its bottom rail. Each is 160x40 over a
   1035x582 shot, so four small patches of the picture take a chip's click. That is the trade
   the design makes, and it is the design. Their CARDS are the part that must stay off:
   covering the thing being explained is what makes an explanation useless. */
.chip--a { left: 1023px; top: 226px; }
.chip--b { left: 863px;  top: 571px; }
.chip--c { left: 48px;   top: 427px; }
.chip--d { left: 10px;   top: 139px; }

/* What each chip is naming. The cards live in the 360px gutter beside the stage, never over
   it — the thing under the chip is the thing being explained, so covering it defeats the
   point. They are siblings of the chips rather than children, which is what lets them sit
   outside while still opening from a hover on the chip. */
.chip__desc {
  position: absolute;
  width: 220px;
  padding: 12px 14px;
  border: 1px solid var(--sage-4);
  border-radius: var(--radius);
  /* one step off the ground rather than on it — a shadow does no lifting on a dark page */
  background: var(--sage-2);
  color: var(--text);
  font-size: 13px;
  line-height: 1.55;
  text-align: left;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.14);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease, visibility 0.12s;
}
.chip__desc b { display: block; margin-bottom: 4px; font-weight: 600; }
.chip__desc kbd { font-size: 12px; padding: 1px 6px; }

/* Each card is hung off its own chip with the same 20px of air, never over the shot (x83 to
   x1118). The three beside it go into the gutter; the Input Area's chip sits ON the shot's
   bottom edge, so its card goes straight down — below the shot, which is the nearest place
   that is not on top of the thing being explained. */
/* Beside the shot, level with the chip that opens it.
   Putting all four under the shot was wrong: hovering a chip at the TOP of the app made its
   explanation appear 460px lower, off the bottom of most windows. The room beside the shot is
   not the 156px gutter alone — the stage keeps 83px of its own to the left of the shot and 82
   to the right, so there is ~238px each side. A 220px card clears the shot by 12px and the
   frame's edge by 7.
   Stage 1200 in a 1512 frame; shot x83..1118, y0..582. */
.desc--d { left: -149px; top: 131px; }
.desc--c { left: -149px; top: 419px; }
.desc--a { left: 1126px; top: 218px; }
/* this chip is on the shot's bottom rail, so its card goes under — and a visitor reaching it
   has already scrolled the bottom of the shot into view */
.desc--b { left: 863px;  top: 623px; }

.chip--a:hover ~ .desc--a, .chip--a:focus-visible ~ .desc--a,
.chip--b:hover ~ .desc--b, .chip--b:focus-visible ~ .desc--b,
.chip--c:hover ~ .desc--c, .chip--c:focus-visible ~ .desc--c,
.chip--d:hover ~ .desc--d, .chip--d:focus-visible ~ .desc--d { opacity: 1; visibility: visible; }

/* ---------- the middle band ----------
   Figma "Frame 293": full-bleed, from the first divider dots to just above the closing CTA.
   In light it is a hair brighter than the ground and reads as one white page; in dark it is
   near-black against the ground's Sage/1, which is the whole reason it exists. */
.band {
  background: var(--band);
  /* Past 1920 the frame is centred and narrower than the window, so the band would stop at
     its edges and leave the ground showing beside it. The bleed is what keeps it full-width;
     the holder clips whatever hangs over. */
  margin-inline: -2000px;
  padding-inline: 2000px;
}

/* ---------- section divider dots ---------- */

.dots {
  width: 63px;
  height: 5px;
  margin: 0 auto;
  background: var(--brand-10);
  -webkit-mask: url(assets/dots.svg) center / contain no-repeat;
  mask: url(assets/dots.svg) center / contain no-repeat;
}

/* ---------- feature rows ---------- */

/* [off-Figma] the whole vertical rhythm of this section, 185/160/180 → 140/104/128.
   These were Figma's, and on the artboard they are fine. On a screen they stack: a row's copy
   is centred in a 600px box, so it already finishes well short of the row's bottom edge, and
   the gap was then added to THAT. Below the last row the padding, the dots' margin and the
   CTA's own top padding ran together into most of a viewport with nothing in it — which reads
   as the page having ended, not as breathing room. */
.features { padding: 140px 0 104px; }
.dots--lower { margin-top: 60px; }
.feature + .feature { margin-top: 128px; }
/* the box keeps the row's 1201x600 ratio, so its height follows the scale with no JS.
   `min-height`, not `height`: the visual half is a fixed 641x600 and sets the row's size on its
   own, so this is now only a floor — and one the copy column cannot spill out of if it grows. */
.feature {
  position: relative;
  width: 1201px;
  min-height: 600px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 96px;
}
.feature--flip { flex-direction: row-reverse; }

.feature__copy { width: 463px; flex: none; display: flex; flex-direction: column; gap: 24px; }
.feature__head { display: flex; flex-direction: column; gap: 16px; }
.feature__title { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
/* [off-Figma] 14/500 → 12/600 uppercase, tracked out. This is a label on a section, not a
   sentence in it; at 14px sitting next to 16px body it was neither. Small and spaced is what
   makes it read as an index rather than as more copy. `text-transform` only — the markup keeps
   its own capitalisation. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--brand-1);
  color: var(--brand-12);
  font-weight: 600;
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* [off-Figma] 32/500/1.5 → 38/600/1.18, and the body up a point with more leading. */
.feature h2 { margin: 0; font-weight: 600; font-size: 38px; line-height: 1.18; letter-spacing: -0.018em; color: var(--text); }
.feature__body { margin: 0; font-size: 17px; line-height: 1.65; color: var(--text); }

.bullets { display: flex; flex-direction: column; gap: 16px; }
.bullet {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 13px 10px 13px 20px;
  border-radius: var(--radius);
  background: var(--brand-1);
}
.bullet .icon { color: var(--brand-12); }
.bullet p { margin: 0; }
.bullet__sub { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.bullet__sub span { display: inline-flex; align-items: center; gap: 4px; }
kbd {
  font-family: inherit;
  padding: 2px 8px;
  border-radius: 4px;
  background: var(--kbd-bg);
  color: var(--text);
  font-weight: 400;
  /* [off-Figma] 16 → 14. A key cap set at the body's own size stops reading as a key. */
  font-size: 14px;
  line-height: 1.5;
}

/* The visual half — Figma "가이드 1-1 / 2-1 / 3-1". Each guide is a 641×600 carousel of full
   Figma frame exports. Carousel structure: slides container + individual slides + pager. */
.feature__visual {
  position: relative;
  width: 641px;
  height: 600px;
  flex: none;
  border: 1px solid var(--sage-3);
  border-radius: var(--radius);
  background: var(--sage-2);
  /* NOT `overflow: hidden`. Figma hangs the advance chip off this box's right edge — 21px
     inside it and 26px outside (`BUTTON` 2377:74222, x 619.5..667.25 of a 641-wide guide) —
     and a clipping ancestor made the whole chip invisible on all three guides. Nothing needs
     the clip any more: the slides are `width/height: 100%` with `object-fit: contain`, so
     they cannot exceed this box, and their rounded corners come from their own
     `border-radius`. */
  overflow: visible;
  box-shadow: inset 2px 2px 12px 0 rgba(0, 0, 0, 0.01);
}

/* Carousel pager — click to advance, positioned bottom-right */
.guide__pager {
  position: absolute;
  /* Figma `Frame 296`: the count reads 25px in from the right edge and 16px up from the
     bottom. The 10px padding is part of that box, so the offsets carry it. */
  right: 15px;
  bottom: 6px;
  padding: 10px;
  border: 0;
  background: transparent;
  color: var(--sage-11);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.45;
  z-index: 100;
  transition: opacity 120ms ease;
  pointer-events: none;
}
.guide__pager:hover { opacity: 0.8; }
.guide__pager:active { opacity: 0.6; }

/* Circular next button (Figma 2377:74826) — primary carousel advance control */
/* The advance chips. Figma draws exactly ONE — on guide 1's right edge — and draws it in both
   the light frame (`BUTTON` 2377:74222) and the dark one (2377:74826). Its own export is the
   spec, and it is short enough to quote:

     light   <g opacity="0.5">  <rect rx="23.75" fill="#E6E6E6"/> <path stroke="black" stroke-width="2" .../>
     dark    <g opacity="0.57"> <rect rx="23.75" fill="white"/>   <path stroke="black" stroke-width="2" .../>

   Three things that are easy to get wrong by looking at a 47px screenshot instead, and were:
   the chip is TRANSLUCENT (the opacity is on the group, so the chevron composites through it
   too, which is why `opacity` sits on the element here rather than being baked into two rgba
   values); its disc is a NEUTRAL grey, not one of this page's sage steps; and its chevron is
   BLACK in both themes — only the disc changes.

   Geometry is Figma's: 47.75x47.5 rounded to a circle, straddling the guide box at ~22px
   inside and ~25px out, level with the middle. `margin-top` does the centring so `transform`
   stays free for the press.

   The BACK chip is not in Figma. It has to exist because these ends are real ends: advancing
   no longer wraps, so without it the last slide is a dead end. Same chip, mirrored. */
.guide__nav {
  position: absolute;
  top: 50%;
  margin-top: -24px;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--guide-nav-bg);
  /* Revealed by the pointer on hover-capable devices. Figma draws the chip at rest because a
     static frame has no other way to show it exists; on a page it can wait until someone is
     actually looking at the guide. The revealed value is still Figma's own alpha — this only
     changes WHEN it is there, never what it looks like once it is. A device with no hover
     (phone, tablet) has no pointer to wait for and no swipe, and the pager is a read-out
     (`pointer-events: none`), so those chips stay at Figma's alpha — see `(hover: none)`. */
  opacity: 0;
  cursor: pointer;
  transition: opacity 120ms ease, transform 120ms ease;
}
/* the path, stroke and box are the export's, unaltered */
.guide__nav::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #000;
  -webkit-mask: var(--chevron) center / 100% 100% no-repeat;
  mask: var(--chevron) center / 100% 100% no-repeat;
  --chevron: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 47.75 47.5" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 35.5L29.75 23.75L18 12"/></svg>');
}
.guide__nav--next { right: -26px; }
.guide__nav--prev { left: -26px; }
.guide__nav--prev::before { transform: scaleX(-1); }
/* Hovering anywhere on the guide brings both chips up to Figma's alpha; the one actually under
   the cursor goes all the way. `:focus-visible` reveals it too, or tabbing to it would move
   focus to something invisible. The compound selector is deliberate: hovering the chip also
   hovers the box that contains it, so the plain `.guide__nav:hover` would lose to the
   descendant rule on specificity and the chip would never reach full. */
.feature__visual:hover .guide__nav,
.guide__nav:focus-visible { opacity: var(--guide-nav-alpha); }
.guide__nav:hover,
.feature__visual:hover .guide__nav:hover { opacity: 1; }
.guide__nav:active { transform: scale(0.95); }
/* No hover means the chips never appear unless they start visible. The pager stays a
   read-out — this does not give it pointer-events. */
@media (hover: none) {
  .guide__nav { opacity: var(--guide-nav-alpha); }
  .guide__nav:active { opacity: 1; }
}
/* it is `hidden` at both ends, and nothing above sets a `display` that would outrank that */
.guide__nav[hidden] { display: none; }

/* The stage. It clips — the app shots inside are far wider than it — while `.feature__visual`
   above deliberately does not, so the advance chips can hang off its edge. */
.guide__slides {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: var(--radius);
}
.guide__slide {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  visibility: hidden;
  transition: opacity 300ms ease, visibility 0ms 300ms;
}
.guide__slide--active {
  opacity: 1;
  visibility: visible;
  transition: opacity 300ms ease, visibility 0ms;
}

/* ---------- the guide slides ----------
   Each slide is Figma's own composition rebuilt as layers, NOT a flattened export of it. The
   flat 641x600 PNGs this replaces were exported at 1x, so on a 2x display every one of them was
   upscaled two-fold and the UI text inside went soft — which is what "슬라이드가 안 선명하다"
   was. The source fills behind them are 3840x2160; laying them out here instead means the
   browser has real pixels to work with at any density, and there is nothing to re-export when
   a 3x screen turns up.

   EVERY OFFSET IS A PERCENTAGE of Figma's 641x600 stage, computed from its pixel value. That
   is what lets the same composition serve the phone: the stage keeps its ratio and the layers
   ride it, so there is no second set of mobile rules and no scaling script. Radii and shadows
   stay in px on purpose — they are surface qualities, not layout.

   Order in the markup is z-order, exactly as in the Figma layer list. */
.guide__layer { position: absolute; margin: 0; }
.guide__layer img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Figma crops this shot rather than fitting it: the picture is wider than the frame it sits in
   and is pinned to its left edge. */
.g1s1-app img,
.g1s2-app img { width: 130.88%; object-fit: fill; max-width: none; }

/* 가이드 1-1 — 2377:74228 */
.g1s1-app      { left: 6.864%; width: 95.008%; height: 74.667%; top: 50%; transform: translateY(-50%); border-radius: 14px; overflow: hidden; box-shadow: -1px 2px 10px 0 rgba(0, 0, 0, 0.12); }
.g1s1-menu     { left: 15.913%; top: 70.833%; width: 82.371%; height: 14.500%; }
.g1s1-cur      { left: 91.732%; top: 74.500%; width: 4.368%; height: 4.667%; }
/* 가이드 1-2 — 2377:74270 */
.g1s2-app      { left: 6.708%; width: 95.008%; height: 74.667%; top: 50%; transform: translateY(-50%); border-radius: 14px; overflow: hidden; box-shadow: -1px 2px 10px 0 rgba(0, 0, 0, 0.12); }
.g1s2-menu     { left: 15.757%; top: 70.667%; width: 82.371%; height: 14.500%; }
.g1s2-cur      { left: 91.576%; top: 74.333%; width: 4.368%; height: 4.667%; }
.g1s2-after    { left: 6.708%; top: 12.500%; width: 124.181%; height: 74.667%; border-radius: 14px; overflow: hidden; }
.g1s2-cur2     { left: 39.626%; top: 45.167%; width: 4.368%; height: 4.667%; }
/* 가이드 2-1 — 2377:74233 */
.g2s1-app      { left: 7.644%; top: 13.167%; width: 160.842%; height: 96.667%; border-radius: 14px; overflow: hidden; box-shadow: -1px 2px 10px 0 rgba(0, 0, 0, 0.12); }
.g2s1-node     { left: 15.601%; top: 40.667%; width: 27.769%; height: 8.333%; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12); }
.g2s1-cur      { left: 41.186%; top: 47.667%; width: 4.368%; height: 4.667%; }
/* 가이드 2-2 — 2377:74263 */
.g2s2-app      { left: 7.488%; top: 13.000%; width: 160.842%; height: 96.667%; border-radius: 14px; overflow: hidden; box-shadow: -1px 2px 10px 0 rgba(0, 0, 0, 0.12); }
.g2s2-node     { left: 15.445%; top: 40.500%; width: 27.769%; height: 8.333%; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12); }
.g2s2-after    { left: 7.488%; top: 13.000%; width: 160.842%; height: 96.667%; border-radius: 14px; overflow: hidden; box-shadow: -1px 2px 10px 0 rgba(0, 0, 0, 0.12); }
.g2s2-tab      { left: 45.086%; top: 18.833%; width: 24.025%; height: 3.333%; box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.12); }
.g2s2-cur      { left: 63.963%; top: 20.500%; width: 4.368%; height: 4.667%; }
/* 가이드 3-1 — 2377:74244 */
.g3s1-crumb    { left: 48.986%; top: 20.500%; width: 73.479%; height: 2.333%; }
.g3s1-badge    { left: 43.058%; top: 27.667%; width: 3.432%; height: 2.667%; box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.12); }
.g3s1-app      { left: 19.813%; width: 120.593%; height: 72.500%; top: 50.083%; transform: translateY(-50%); }
.g3s1-outline  { left: 15.445%; top: 8.333%; width: 33.697%; height: 81.000%; box-shadow: 2px 2px 12px 0 rgba(0, 0, 0, 0.1); }
.g3s1-badge2   { left: 43.214%; top: 27.833%; width: 3.432%; height: 2.667%; box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.12); }
.g3s1-cur      { left: 45.710%; top: 29.167%; width: 4.368%; height: 4.667%; }
/* 가이드 3-2 — 2377:74238 */
.g3s2-app      { left: 19.657%; width: 120.593%; height: 72.500%; top: 50.083%; transform: translateY(-50%); }
.g3s2-crumb    { left: 48.986%; top: 20.500%; width: 73.479%; height: 2.333%; }
.g3s2-outline  { left: 15.289%; top: 8.167%; width: 33.697%; height: 81.000%; box-shadow: 2px 2px 12px 0 rgba(0, 0, 0, 0.1); }
.g3s2-cur      { left: 42.902%; top: 46.333%; width: 4.368%; height: 4.667%; }
/* 가이드 3-3 — 2377:74252 */
.g3s3-app      { left: 19.657%; width: 120.593%; height: 72.500%; top: 50.083%; transform: translateY(-50%); }
.g3s3-pins     { left: 45.398%; top: 17.833%; width: 69.735%; height: 57.667%; }
.g3s3-cur      { left: 80.343%; top: 36.000%; width: 4.368%; height: 4.667%; }
.g3s3-outline  { left: 15.289%; top: 8.167%; width: 33.697%; height: 81.000%; box-shadow: 2px 2px 12px 0 rgba(0, 0, 0, 0.1); }
/* 가이드 3-4 — 2377:74258 */
.g3s4-app      { top: 13.500%; width: 120.593%; height: 72.500%; left: 26.131%; transform: translateX(-50%); }
.g3s4-panel    { left: 60.218%; top: 8.500%; width: 29.329%; height: 84.667%; box-shadow: 2px 2px 12px 0 rgba(0, 0, 0, 0.1); }
.g3s4-cur      { left: 68.799%; top: 12.000%; width: 4.368%; height: 4.667%; }

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

/* Rectangle 14: a fade that sits behind the CTA and dies out downward. */
/* [off-Figma] 136/282 → 104/176. */
.cta {
  position: relative;
  padding: 104px 0 176px;
  text-align: center;
}
.cta::before {
  content: "";
  position: absolute;
  /* THIS NUMBER IS COUPLED to `.dots--lower`'s margin and the dots' own 5px height: the fade
     has to begin exactly where `.band` stops, or a seam shows between the two. 60 + 5 = 65.
     Change the dots' margin and change this with it. */
  inset: -65px -2000px auto;   /* same bleed as .band — it is that band running out */
  height: 470px;
  background: linear-gradient(to bottom, var(--band), transparent);
  pointer-events: none;
}
.cta > * { position: relative; }
/* [off-Figma] 44/500/1.5 → 48/600/1.12. It sits a step under the hero on purpose: this is the
   close, not a second opening. */
.cta h2 { margin: 0; font-weight: 600; font-size: 48px; line-height: 1.12; letter-spacing: -0.02em; color: var(--text); }
.cta p { max-width: 524px; margin: 24px auto 0; font-weight: 500; }
.cta__actions { display: flex; justify-content: center; gap: 24px; margin-top: 24px; }

/* ---------- footer ---------- */

.site-footer { border-top: 1px solid var(--sage-4); padding: 40px 0; }
.site-footer__top { display: flex; align-items: center; justify-content: space-between; gap: 40px; }
.site-footer__brand { width: 284px; display: flex; flex-direction: column; gap: 9px; }
.site-footer__brand p { margin: 0; line-height: 1.5; color: var(--sage-alpha-12); }
.socials { display: flex; align-items: center; gap: 25px; color: var(--sage-alpha-12); }
.socials a { transition: color 120ms ease; }
.socials a:hover { color: var(--brand-10); }
.socials .icon--x { width: 27px; }
.site-footer__legal {
  display: flex;
  align-items: center;
  gap: 60px;
  /* [off-Figma] 97 → 60 */
  margin-top: 60px;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.5;
}
.site-footer__legal .copyright { opacity: 0.7; }

/* ---------- the plain page ----------
   No `is-scaled` means the frame is not a picture: a phone, or a browser that did not run the
   script. Everything here undoes a Figma pixel that only makes sense at 1920 and lets the
   content be a normal, readable column. The desktop rules above are untouched — this is a
   different drawing, not the same one squeezed. */


html:not(.is-scaled) .frame { width: auto; }
html:not(.is-scaled) .container { width: auto; padding: 0 20px; }

/* the band's ±2000px bleed is for a centred frame; here it would just overflow */
html:not(.is-scaled) .band { margin-inline: 0; padding-inline: 0; }
html:not(.is-scaled) .cta::before { inset: -60px 0 auto; height: 320px; }

html:not(.is-scaled) .site-header { padding: 16px 0; }
html:not(.is-scaled) .gnb,
html:not(.is-scaled) .header-btn:not(.header-btn--strong) { display: none; }

html:not(.is-scaled) .hero { padding-top: 44px; }
html:not(.is-scaled) .hero h1 { max-width: none; font-size: 30px; line-height: 1.15; }
html:not(.is-scaled) .hero__lead { max-width: none; margin-top: 14px; font-size: 15px; line-height: 1.6; }
html:not(.is-scaled) .hero__cta { flex-direction: column; align-items: stretch; gap: 12px; margin-top: 28px; }
html:not(.is-scaled) .btn { width: 100%; }

/* the same 20px inset the column has — rounded corners running off the screen edge
   read as a crop, not as a screen */
html:not(.is-scaled) .stage { width: auto; height: auto; margin: 32px 20px 0; }
html:not(.is-scaled) .stage__shot { position: static; width: auto; height: auto; }
html:not(.is-scaled) .stage__shot img { height: auto; }
html:not(.is-scaled) .chip,
html:not(.is-scaled) .chip__desc { display: none; }

html:not(.is-scaled) .features { padding: 56px 0 64px; }
html:not(.is-scaled) .dots--lower { margin-top: 40px; }

html:not(.is-scaled) .feature,
html:not(.is-scaled) .feature--flip {
  position: static;
  flex-direction: column;
  width: auto;
  height: auto;
  gap: 24px;
}
html:not(.is-scaled) .feature + .feature { margin-top: 56px; }
html:not(.is-scaled) .feature__copy { width: auto; }
html:not(.is-scaled) .feature h2 { font-size: 24px; line-height: 1.25; }
html:not(.is-scaled) .feature__body { font-size: 15px; }

/* the guide is a composition of absolutely-placed layers at 641x600; on a phone it is just
   the screenshot it is built on, and the annotation layers step aside */
/* `width: 100%`, not `auto`. The row is `align-items: center` here, so an auto-width item is
   sized by its contents — and every layer inside the stage is absolutely positioned now, so
   there are no contents to measure and the box collapsed to nothing. The height comes from the
   stage's aspect-ratio below. */
html:not(.is-scaled) .feature__visual { width: 100%; height: auto; border-radius: var(--radius); }
/* The stage is percentage-laid-out, so the phone needs only its ratio back — the fixed
   641x600 came off with `.feature__visual`'s width above. */
html:not(.is-scaled) .guide__slides { aspect-ratio: 641 / 600; height: auto; }
html:not(.is-scaled) .guide__pager { bottom: 12px; right: 12px; }
html:not(.is-scaled) .guide__nav--prev { left: 8px; }
html:not(.is-scaled) .guide__nav--next { right: 8px; }

html:not(.is-scaled) .cta { padding: 64px 0 72px; }
html:not(.is-scaled) .cta h2 { font-size: 27px; line-height: 1.18; }
html:not(.is-scaled) .cta p { margin-top: 16px; font-size: 15px; }
html:not(.is-scaled) .cta__actions { flex-direction: column; align-items: stretch; gap: 12px; }

html:not(.is-scaled) .site-footer { padding: 32px 0; }
html:not(.is-scaled) .site-footer__top { flex-direction: column; align-items: flex-start; gap: 24px; }
html:not(.is-scaled) .site-footer__brand { width: auto; }
html:not(.is-scaled) .site-footer__legal { margin-top: 32px; flex-wrap: wrap; gap: 14px 24px; }

/* ---------- Resources dropdown ----------
   The design draws a chevron on this nav item; these are the pages behind it. */
.dropdown { position: relative; }
.dropdown summary {
  cursor: pointer;
  list-style: none;
}
.dropdown summary::-webkit-details-marker { display: none; }
/* `dropdown, pressed` flips the chevron rather than swapping in a second icon (`-scale-y-100`). */
.dropdown summary .icon { transition: transform 120ms ease; }
.dropdown[open] summary .icon { transform: scaleY(-1); }
/* LNB — 2377:73864 / the instance at 2377:73881. Hung off the chip's LEFT edge, not centred
   under it, and 8px below a 17px chip. No border: the design separates it from the page with
   the shadow alone, and the shadow is a `drop-shadow` offset down-right (Gray Alpha/5). */
.dropdown__menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-width: 155px;
  padding: 5px;
  border-radius: var(--radius);
  background: var(--lnb-bg);
  /* the hairline is a spread shadow rather than a border so it costs the box no width — Figma's
     155 stays 155, and in light the colour is transparent so nothing is drawn at all */
  box-shadow: 0 0 0 1px var(--lnb-edge);
  filter: drop-shadow(4px 4px 6px #0000001f);
  z-index: 2;
}
/* LNB_chip — 2377:73857. Full-width row, 4/8 padding, radius 5. Hover Sage/4, pressed Sage/5.
   Text stays Colors/text in every state — the GNB Brand 12 hover must not leak in. */
.dropdown__menu a {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 4px 8px;
  border-radius: 5px;
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  color: var(--text);
  white-space: nowrap;
  transition: background-color 120ms ease;
}
.dropdown__menu a:hover, .dropdown__menu a:focus-visible { background: var(--sage-4); color: var(--text); }
.dropdown__menu a:active { background: var(--sage-5); color: var(--text); }
/* An item with nowhere to go keeps its resting look — it IS in the menu — but must not answer
   the pointer like the one that works. Same rule as Pricing in the bar above. */
.dropdown__menu a[aria-disabled="true"] { cursor: default; }
.dropdown__menu a[aria-disabled="true"]:hover,
.dropdown__menu a[aria-disabled="true"]:active { background: transparent; }
