/* ════════════════════════════════════════════════════════════════════════════
   PORTAL IFRAME EMBED — layout overrides for html.framed
   ════════════════════════════════════════════════════════════════════════════
   Linked LAST by BOTH served pages (index.html, tutorial.html). It cannot live
   in app.css: tutorial.html does not load app.css, and duplicating these rules
   into a second stylesheet guarantees drift. Rules naming a region absent from
   the current page are harmless no-ops.

   THE CLASS IS SET IN JS, and without it every rule here is dead CSS:
       if (window.self !== window.top) document.documentElement.classList.add('framed');
   scripts/app.js init() and scripts/tutorial.js init() both do it, and both run
   BEFORE auth.js calls signalRendered() — so the corrected framed layout is
   what the first rvo-height measures.

   The portal (tools-portal EmbeddedTool) frames each tool with scrolling="no"
   and a height driven by our own rvo-height message. Two consequences drive
   everything below:
     1. the portal page is the ONLY scroll surface — the frame has no local
        viewport, so position:fixed/sticky do not behave;
     2. inside the frame 100vh EQUALS the height we last reported — viewport
        units are self-referential.
   ──────────────────────────────────────────────────────────────────────────── */

/* ── 1. THE VIEWPORT-HEIGHT RATCHET ──
   A min-height:100vh on a CHILD of <body> that has a sibling above it (the nav)
   makes the frame grow without bound:
       reported = nav + max(content, 100vh) = nav + H
       portal sets frame = nav + H   ⇒   100vh becomes nav + H
       reported = nav + (nav + H)    ⇒   ResizeObserver fires ⇒ repeat
   Every pass adds the nav's height. Symptom: dead space below the report that
   keeps growing. OVERRIDE, never cap — a numeric cap on the posted height
   clips a legitimately tall report (two letter pages ≈ 2300px).

   Every offending selector must be covered; one override does not reach a
   second offender, and the symptom is identical so it reads as "the fix didn't
   work". Current offenders (grep 'min-height:100vh' styles/):
     body            hfg-tool-shell.css     (0,0,1)  — stable on its own, but see below
     #pg2            hfg-tool-shell.css     (1,0,0)
     #tut-app        hfg-tutorial-v2.css    (1,0,0)
   #mv .mapp.dk / #mv .sub are deliberately NOT listed: the mobile live screen
   is never framed. */
html.framed body{min-height:0;}
html.framed #pg2{min-height:0;}
html.framed #tut-app{min-height:0;}

/* ⚠ ZEROING body's min-height COLLAPSES THE FRAME WHILE THE GATE IS UP.
   .auth-gate is position:fixed, and a fixed element contributes NOTHING to
   scrollHeight. While the gate shows, every other region is display:none (the
   fail-closed rule) — so before the override above, body{min-height:100vh} was
   ACCIDENTALLY holding the frame open. After it, contentHeight() collapses to
   ~0, the portal sizes the iframe to nothing, and the officer sees an empty tab
   instead of a sign-in button. Give the gate its own flow height when framed:
   inset:0 goes inert once it is static, and the flex centering still works.
   Nothing local reproduces this — the gate needs real Entra credentials. */
html.framed .auth-gate{position:static;min-height:420px;}

/* ── 2. position:fixed AND sticky DO NOT WORK FRAMED ──
   sticky has no scroll viewport to stick to (inert); fixed resolves against the
   iframe viewport, which EQUALS the full content height — so a bottom:0 bar
   pins to the bottom of the entire tall frame instead of floating over the
   reader. Flatten both, and drop the padding that reserved space for the bar.

   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 #tut-app .tut-ctrl. */
html.framed .site-nav{position:static;}
html.framed #tut-app .site-nav{position:static;}
html.framed #tut-app .tut-ctrl{position:static;}
html.framed #tut-app{padding-bottom:30px;}   /* was 104px, reserved for the fixed bar */

/* ── 3. FOCUS-SCROLL RING SUPPRESSION ──
   window.scrollTo is a silent no-op framed (a cross-origin child cannot scroll
   its parent), so showPage()/show() move FOCUS instead: that is a user-agent
   action, and the UA scrolls every ancestor scroll container — across the
   iframe boundary — to reveal the target. The targets are headings, not
   controls, so suppress the ring for the non-keyboard case ONLY. A real
   keyboard user keeps their focus indicator via :focus-visible. */
#pg1Heading:focus:not(:focus-visible),
#pg2Heading:focus:not(:focus-visible),
#dealSection:focus:not(:focus-visible),
.tut-headline:focus:not(:focus-visible){outline:none;}
