/* climbrate landing — /demo (assets/demo.css)
   The interactive demo: the REAL app in an iframe, framed by the same Apple
   bezel PNGs the home page uses, behind an iOS-style glass segmented control
   that picks the device. FLOW idiom — the owner has not drawn this page in
   Figma, so no --u coordinates. Tokens, the four type sets, header, buttons
   and footer come from style.css; nothing here adds a colour or a type set.

   HOW THE FRAMES WORK. One iframe per demo (instructor, student) — an iframe
   moved in the DOM reloads, so it never moves. Picking a device changes the
   `data-device` on .demos, which sets each frame's DISPLAY width and swaps
   which bezel PNG shows; the script sizes the iframe at the device's real CSS
   viewport (so the app's own pad:/desk: breakpoints decide the layout) and
   transform-scales it down to the display width. Layout sizes, chosen against
   tailwind.config.ts: desktop 1280×790 (desk: ≥1180 + fine pointer), iPad
   1176×817 (pad + padx, deliberately under the 1180 desk cut — an iframe on a
   laptop reports a fine pointer), phone 390×844. */

.demo-sec{padding-top:clamp(110px,12vw,150px)}
.demo-head{display:flex; flex-direction:column; align-items:center; text-align:center; gap:14px}
.demo-head h1{font-size:clamp(32px,4.2vw,56px); line-height:1.08; color:#fff; max-width:18ch; text-wrap:balance}
.demo-head p{max-width:46ch; font-size:15px; line-height:1.55; color:var(--text-dim)}

/* ---------- the glass segmented control (iOS-style) ---------- */
/* three columns keep the selector dead centre with the full-screen button
   sitting in the right column beside it */
/* device picker · side picker · full screen — one centred row */
.seg-bar{position:sticky; top:96px; z-index:40; display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:12px; margin-top:36px; pointer-events:none}
.seg-bar > .seg,.seg-bar > .fs-btn{pointer-events:auto}
/* DOCKING (owner, 2026-09-08): at the 1440 frame the logo is centred in the
   header, so the bar's sticky line is the logo's centre line — as the visitor
   scrolls, the pills ride up over the header and dock where the logo was.
   The script fades the logo out as they cross it (back in on the way up) and
   flags html.pills-docked; while docked the header is EVENLY SPACED — the
   script measures the links, the controls and the actions and sets equal
   gaps (--dock-pad on the nav, --dock-shift on the bar) so the nav links
   slide left, Sign in / Buy Now slide right and the controls sit between
   them. Header nav = 34 tall with a 17.77 top margin → centre 34.77, minus
   half the 46px bar = 12. Below 1200 the logo sits left, so the bar keeps
   parking under the header instead. */
@media (min-width:1200px){
  .seg-bar{top:12px; z-index:60; transition:transform .35s ease}
  .nav{transition:padding .35s ease}
  html.pills-docked .nav{padding:0 var(--dock-pad, calc(40*var(--u)))}
  html.pills-docked .seg-bar{transform:translateX(var(--dock-shift, 0px))}
}
.brand{transition:opacity .15s linear}
.seg{
  --n:3; --i:0;
  pointer-events:auto; position:relative; display:grid; grid-template-columns:repeat(var(--n),1fr);
  width:auto; padding:3px; border-radius:999px;
  background:rgba(255,255,255,.08); border:1px solid var(--hair-strong);
  backdrop-filter:blur(20px) saturate(160%); -webkit-backdrop-filter:blur(20px) saturate(160%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10), 0 10px 30px rgba(0,0,0,.35);
}
.seg-knob{
  position:absolute; top:3px; bottom:3px; left:3px; width:calc((100% - 6px)/var(--n));
  border-radius:999px; background:rgba(255,255,255,.16);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26), inset 0 -1px 1px rgba(0,0,0,.14), 0 4px 14px rgba(0,0,0,.30);
  transform:translateX(calc(var(--i)*100%));
  transition:transform .32s cubic-bezier(.2,.7,.2,1);
}
.seg button{
  appearance:none; background:none; border:0; margin:0; position:relative; z-index:1;
  height:38px; padding:0 18px; min-width:112px; border-radius:999px; font:inherit; font-size:13.5px;
  color:rgba(255,255,255,.72); cursor:pointer; transition:color .2s ease; white-space:nowrap;
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
}
.seg button[hidden],.seg[hidden],.fs-btn[hidden]{display:none}
.seg button[aria-selected="true"]{color:#fff}
.seg button:focus-visible{outline:2px solid var(--blue); outline-offset:2px}
.seg svg{width:15px; height:15px; flex:none}

/* ---------- the two demos ---------- */
.demos{position:relative; display:grid; grid-template-columns:1fr; margin-top:52px; justify-items:center}
/* ONE frame shows at a time; the other is parked off-screen, never unmounted
   (an iframe removed from the DOM reloads the app) */
.demo.off{position:absolute; left:-200vw; top:0; height:0; overflow:hidden; visibility:hidden; pointer-events:none}
.demo{display:flex; flex-direction:column; align-items:center; gap:22px; width:100%}
.demo-cap{display:flex; flex-direction:column; align-items:center; text-align:center; gap:5px}
.demo-cap h2{font-size:clamp(22px,2.4vw,28px); line-height:1.15; color:#fff}
.demo-cap p{font-size:13.5px; line-height:1.5; color:var(--text-faint); max-width:40ch}

/* .dev-box reserves the bezel's overhang as padding (percentages of its OWN
   width, since it is exactly the frame's width) so the bezel never covers the
   caption above or the note below. The frame box IS the device's screen; the
   bezel hangs outside it via the Figma component's negative insets (style.css
   header lists them). */
.dev-box{position:relative; flex:none}
.frame{position:relative; width:100%; background:#000}
.frame .screen{position:absolute; inset:0; overflow:hidden; background:#000}
.frame iframe{display:block; border:0; background:var(--page); transform-origin:0 0}
.bezel{position:absolute; pointer-events:none; display:none}
.bezel img{width:100%; height:100%; max-width:none; display:block}
.bezel-mac{left:0; top:0; width:98.86%; height:100%}
.bezel-mac > div{position:absolute; inset:-11.11% -17.43% -16.67% -17.29%}
/* iPad PORTRAIT: the PNG is landscape, so a landscape box (H×W) sits centred
   in the portrait screen and turns 90° — the day section's recipe — carrying
   the component's insets. */
.bezel-ipad{inset:0; align-items:center; justify-content:center}
.bezel-ipad .rot{position:relative; flex:none; width:143.9%; height:69.49%; transform:rotate(90deg)}
.bezel-ipad .rot > div{position:absolute; inset:-8.48% -5.93% -8.6% -5.93%}
.bezel-phone{inset:-3.95% -8.55%}

/* desktop: MacBook Air 13" — screen 614×379 in the frame, 1280×790 inside */
/* Each box keeps its width in --bw so the padding that reserves the bezel's
   overhang is computed from the box's OWN width (percentage padding would
   resolve against the parent's) — then every device's top edge lands on the
   same line when the picker switches. Overhang = bezel inset × screen aspect. */
.demos[data-device="desktop"] .dev-box{--bw:min(880px, calc((100vw - 80px)/1.35)); width:var(--bw); padding:calc(var(--bw)*.0686) 0 calc(var(--bw)*.1029)}
.demos[data-device="desktop"] .frame{aspect-ratio:1280/790; border-radius:1% / 1.6%}
.demos[data-device="desktop"] .frame .screen{border-radius:inherit}
.demos[data-device="desktop"] .bezel-mac{display:block}
/* iPad Air PORTRAIT (820×1180 inside) — sized so the whole device fits the
   window height: (1180/820 + the 8.5% bezel top and bottom) ≈ 1.61 × width.
   The rotated bezel overhangs 8.5% of the width each side. */
.demos[data-device="ipad"] .dev-box{--bw:min(460px, calc((100vw - 80px)/1.17), calc((100vh - 150px)/1.61)); width:var(--bw); padding:calc(var(--bw)*.0853) 0}
.demos[data-device="ipad"] .frame{aspect-ratio:820/1180; border-radius:2.4% / 1.7%}
.demos[data-device="ipad"] .frame .screen{border-radius:inherit}
.demos[data-device="ipad"] .bezel-ipad{display:flex}
/* iPhone 17 Pro Max — screen 440×956 inside the 14's bezel art (the closest
   PNG we have); at 1:1 when the whole phone fits the window height, else
   zoomed down to fit it: (956/440 + 8.6% top and bottom) ≈ 2.35 × width */
.demos[data-device="mobile"] .demo{width:auto}
.demos[data-device="mobile"] .dev-box{--bw:min(440px, calc((100vw - 80px)/1.171), calc((100vh - 150px)/2.35)); width:var(--bw); padding:calc(var(--bw)*.0858) 0}
.demos[data-device="mobile"] .frame{aspect-ratio:440/956; border-radius:11.5% / 5.3%}
.demos[data-device="mobile"] .frame .screen{border-radius:inherit}
.demos[data-device="mobile"] .bezel-phone{display:block}

/* while a session is being minted, or when the app can't be reached */
.frame .veil{
  position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:14px; padding:24px; text-align:center; background:var(--page); color:var(--text-dim);
  transition:opacity .4s ease; pointer-events:none;
}
.frame .veil img{width:40px; height:auto; opacity:.9}
.frame .veil span{font-size:15px; line-height:1.4}
.frame.ready .veil{opacity:0}


/* ---------- touch viewers (iPad, iPhone): no bezel, the app fills the screen ----------
   html.touch is set by the script from the pointer query; the frame becomes the
   real viewport at 1:1 (no transform), full-bleed on the viewer's own device,
   and a centred 390px column when an iPad tries the phone. */
html.touch .demo-sec{padding-top:96px}
html.touch .demo-head h1{font-size:clamp(28px,6vw,40px)}
html.touch .seg-bar{position:static; margin-top:22px}
html.touch .demos{display:block; position:relative; margin-top:26px}
html.touch .demo{gap:14px}
html.touch .demo-cap p{display:none}
html.touch .demos .bezel{display:none}
html.touch .demos[data-device] .dev-box{width:100vw; margin-left:calc(50% - 50vw); padding:0}
html.touch .demos[data-device] .frame{aspect-ratio:auto; height:calc(100svh - 64px); border-radius:0}
html.touch .demos[data-device] .frame .screen{border-radius:inherit}
html.touch .demos[data-device="mobile"] .dev-box{width:min(390px, 100vw); margin:0 auto}
html[data-viewer="ipad"] .demos[data-device="mobile"] .frame{border-radius:14px}
html.touch .demo-note{margin-top:32px; padding:0 24px}

/* ---------- full browser (desktop viewers) ----------
   "Full screen" pins the frame over the whole window (fixed, not the OS
   fullscreen API): the bezel steps aside, the screen fills it on black and
   the script sizes the iframe at true size — so it reads as being IN the
   app, its own blue demo strip included — and that strip carries the way
   back (a postMessage handshake, see the script); Esc works too. */
/* Sized to the device picker's TRACK (38px buttons + 3px padding + 1px
   border = 46px) with the same glass, so the two read as one family. */
.fs-btn{
  display:inline-flex; align-items:center; gap:7px; height:46px; padding:0 18px; border-radius:999px;
  background:rgba(255,255,255,.08); border:1px solid var(--hair-strong); color:rgba(255,255,255,.8);
  backdrop-filter:blur(20px) saturate(160%); -webkit-backdrop-filter:blur(20px) saturate(160%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10), 0 10px 30px rgba(0,0,0,.35);
  font:inherit; font-size:13.5px; cursor:pointer; transition:background .2s ease, color .2s ease;
}
.fs-btn:hover{background:rgba(255,255,255,.14); color:#fff}
.fs-btn:focus-visible{outline:2px solid var(--blue); outline-offset:2px}
.fs-btn svg{width:15px; height:15px; flex:none}
html.touch .fs-btn{display:none}
/* [data-device] in the selector so these outrank the per-device frame rules */
.demos[data-device] .frame.full{position:fixed; inset:var(--fs-strip-h, 38px) 0 0 0; z-index:200; width:100vw; height:calc(100vh - var(--fs-strip-h, 38px)); aspect-ratio:auto; border-radius:0; background:#000}
.demos[data-device] .frame.full .screen{border-radius:0}
.demos[data-device] .frame.full .bezel{display:none}
html.fs-open{overflow:hidden}
/* the page's own strip ABOVE the full frame (owner, 2026-09-08): it sits at
   the top of the window and the frame starts below it (--fs-strip-h, set by
   the script from the strip's real height), so it never covers the app */
.fs-strip{
  position:fixed; left:0; right:0; top:0; z-index:300;
  display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:6px 16px;
  padding:calc(7px + env(safe-area-inset-top)) 16px 7px; background:#426eb5; color:#fff; font-size:12.5px; font-weight:500;
  box-shadow:0 2px 12px rgba(0,0,0,.35);
}
.fs-strip[hidden]{display:none}
.fs-strip-btn{display:inline-flex; align-items:center; height:24px; padding:0 12px; border-radius:8px; font:inherit; font-size:12px; font-weight:600; cursor:pointer}
.fs-strip-solid{background:#fff; color:#2f4f85}
.fs-strip-ghost{background:none; border:1px solid rgba(255,255,255,.6); color:#fff}
.fs-strip-ghost:hover{background:rgba(255,255,255,.12)}
html.fs-open .seg-bar{visibility:hidden}
/* the strip's touch-only pieces: a short label, the small side switch and
   an ✕; desktop keeps its sentence and "Back to the demo page" */
.fs-short,.fs-roles{display:none}
html.touch .fs-strip{flex-wrap:nowrap; justify-content:space-between; gap:8px; padding:calc(6px + env(safe-area-inset-top)) 10px 6px}
html.touch .fs-long{display:none}
html.touch .fs-short{display:inline}
html.touch .fs-roles{display:inline-flex; padding:2px; border-radius:999px; background:rgba(255,255,255,.18)}
.fs-roles button{height:22px; padding:0 11px; border:0; border-radius:999px; background:none; color:#fff; font:inherit; font-size:12px; font-weight:600; cursor:pointer}
.fs-roles button[aria-selected="true"]{background:#fff; color:#2f4f85}
html.touch .fs-exit{padding:0 8px}
/* a touch viewer's full frame: dvh, so Safari's collapsing toolbar can't
   leave the bottom of the app under it */
html.touch .demos[data-device] .frame.full{height:calc(100dvh - var(--fs-strip-h, 38px)); background:var(--page)} /* the app's ink, not black — what Safari shows under its toolbar */
html.touch.fs-open, html.touch.fs-open body{background:var(--page)}
/* the parked side (.off) must not cover the shown one when both are full */
html.touch .demo.off .frame.full{visibility:hidden}

.demo-note{margin-top:56px; text-align:center; font-size:13px; line-height:1.55; color:var(--text-faint)}
.demo-note a{color:var(--text-dim); border-bottom:1px solid var(--hair-strong)}
.demo-note a:hover{color:#fff}

@media (max-width:1199px){
  .seg-bar{top:60px}
  .demos{margin-top:40px}
}
@media (prefers-reduced-motion:reduce){ .seg-knob{transition:none} }
