/* ── PORTAL IFRAME EMBED — framed-only layout overrides (styles/embed.css) ──
   Shared by BOTH framed pages (index.html, tutorial.html). Loaded LAST.

   html.framed is set by each page's init() (app.js / tutorial.js) before the
   first rvo-height is posted, so the corrected layout is what gets measured.
   Standalone pages never get the class and are byte-for-byte unaffected.

   The portal (tools-portal EmbeddedTool) frames each tool with scrolling="no"
   and a height driven by our own rvo-height message. Two consequences:
     1. There is NO local viewport — position:fixed resolves against the FULL
        content height and position:sticky is inert.
     2. Inside the frame, 100vh EQUALS the height we last reported. A
        min-height:100vh on a CHILD of <body> therefore ratchets:
          reported = nav + max(content, 100vh) -> portal grows the frame ->
          100vh grows -> repeat, adding the nav's height every pass.
   Override, never cap: a numeric cap on the posted height clips a legitimately
   tall report (two letter pages is roughly 2300px). */

/* ── 1. the viewport-height ratchet — every offending selector ────── */
/* body's own min-height is stable (an element cannot add height outside
   itself), but zero it too so nothing downstream can reintroduce the loop. */
html.framed body{min-height:0;}
/* hfg-tool-shell.css:284 — #pg2 is a CHILD of body, with .site-nav above it. */
html.framed #pg2{min-height:0;}
/* hfg-tutorial-v2.css:31 — the second framed page brings its own offender,
   plus 104px of padding reserved for the fixed control bar flattened below. */
html.framed #tut-app{min-height:0;padding-bottom:0;}
/* hfg-tool-shell.css:189,193 — the mobile dark shell, if ever framed on a
   touch device. No effect standalone or on desktop (html.mv-mode gates #mv). */
html.framed #mv .mapp,
html.framed #mv .sub{min-height:0;}

/* ── 2. fixed / sticky have nothing to resolve against ────────────── */
/* Flatten to static so both bars sit in normal flow directly under the
   content — a better embedded experience than faking sticky, and it removes
   the need to scroll to reach the tutorial's Prev/Next. */
html.framed .site-nav{position:static;}
/* SPECIFICITY: #tut-app .site-nav is (1,1,0) and BEATS a bare
   html.framed .site-nav at (0,2,0). The ID has to be repeated or the override
   silently does nothing. Same for the control bar. */
html.framed #tut-app .site-nav{position:static;}
html.framed #tut-app .tut-ctrl{position:static;box-shadow:none;border-top:1px solid var(--iv-line);}

/* ── 3. focus-scroll ring suppression ─────────────────────────────── */
/* window.scrollTo is a silent no-op framed (a cross-origin child cannot scroll
   its parent), so the view switch focuses a tabindex="-1" heading instead —
   moving focus is a user-agent action and the UA scrolls every ancestor scroll
   container, crossing the iframe boundary. Suppress the ring for the
   non-keyboard case ONLY, so a real keyboard user keeps their indicator. */
#pg1Heading:focus:not(:focus-visible),
#pg2Heading:focus:not(:focus-visible),
#tut-app .tut-headline:focus:not(:focus-visible){outline:none;}
