/* =====================================================================
   THE ROYAL FRONT DOOR  ·  front-door.css
   The intro screen only. Never link this on a deep page.

   WHAT THIS FILE IS
   Nothing here was invented. Every rule below is lifted verbatim from
   royalai.ai/index.html - the file Bryan reviewed and approved without a
   single change to the graphics or the branding. This file exists for two
   reasons and only two:

     1. THE PARTS royal-system.css DOES NOT HAVE
        .bubbles / .bubble          (the system calls its grid .coins/.cell)
        .coin > .inner              (the system calls it .coin-inner)
        .answer                     (the system calls it .askout)
        .nest / .nestrow            (the tray behind the deep door)
        .a2hs                       (the iPhone home-screen pill)
        @keyframes rise
        .prodmark                   (the portal product line)
        .g8 .l2 .l3 .l4 .l5         (the five funnel grids, section 7a)
        .nolabel                    (no-label ball mode, section 7b)

   THE LEAVING NOTICE IS GONE (Bryan, 7/29/2026). Section 13 carried the
   .rlv-* card for the external-link interstitial and it is deleted, along
   with the script that opened it. Every Royal link is an ordinary same-tab
   link now. Do not restore these rules. THIS IS THIS TREE'S OWN COPY and
   it diverges on purpose from the shared master.

     2. THE FIVE PLACES the front door and the shared system genuinely
        disagree. Each one is marked  == OVERRIDE ==  below with the reason.
        This sheet MUST load second or those five silently lose.

   LOAD ORDER, and it is load-bearing:
     <link rel="stylesheet" href="_royal-system/royal-system.css">
     <link rel="stylesheet" href="_royal-system/front-door/front-door.css">

   NEVER also link a per-site css/royal.css. It collides with
   royal-system.css on 49 selectors including :root, body, .coin, .stage,
   .searchbox and footer. One system per page, never both.

   Royal Mortgage LLC · NMLS #2059962
   ===================================================================== */


/* ---------------------------------------------------------------------
   0. THE FRONT-DOOR COLUMN

   == OVERRIDE 1 ==  THE ONE WIDTH LAW.
   royal-system.css widens --col to 680px at 768 and 720px at 1280. That is
   correct for a marketing page and WRONG here: the front door is one room
   at min(620px, 94-100vw) on every screen, and the mark, the ask bar, the
   coin row, the answer panel and the tray all resolve to it. Let --col
   through and the intro quietly grows on a laptop while the phone stays
   put, and the five sites stop matching each other.

   So the front door rides its own token and never reads --col.
   --------------------------------------------------------------------- */
:root{
  --fd-col:min(620px,100%);   /* ask bar, coin row, answer, tray */
  --fd-mark:min(620px,94vw);  /* the wordmark, which may bleed 3vw wider */
}


/* ---------------------------------------------------------------------
   1. THE PAGE

   == OVERRIDE 2 ==  the front door is a full-height flex column so the
   footer rests on the bottom edge of a phone with no scroll, and .stage
   absorbs whatever is left over. royal-system.css leaves body in normal
   flow because its pages are long. The font-family is restated with the
   fallback INSIDE the var(): --royal-font is defined by royal-system.css,
   but a bare var() with a missing token is invalid at computed-value time
   and would drop the whole page to the UA serif if the sheet ever failed
   to load. Belt and braces, one line.
   --------------------------------------------------------------------- */
html,body{margin:0;height:100%}
body{
  background:var(--paper,#FFFFFF);
  color:var(--ink,#1B2140);
  font-family:var(--royal-font,'Montserrat','Segoe UI','Avenir Next','Helvetica Neue',system-ui,sans-serif);
  -webkit-font-smoothing:antialiased;
  /* 100dvh with the 100vh fallback (7/31/2026): inside a phone webview
     100vh includes the browser chrome and overshoots; dvh is the honest
     viewport. Older engines skip the second line and keep vh. */
  display:flex;flex-direction:column;min-height:100vh;min-height:100dvh;
  overflow-x:hidden;
}


/* ---------------------------------------------------------------------
   2. THE WORDMARK
   Deliberately STATIC. Bryan's ruling 7/24: no motion on the home page
   mark. Do not add a draw-on, a shimmer, or a hover.
   --------------------------------------------------------------------- */
.markwrap{padding:clamp(28px,6vh,64px) 16px 0;display:flex;justify-content:center}
.mark{width:var(--fd-mark);overflow:visible;display:block}

/* VARIANT B, the castle + words sitemark. royal-system.css already styles
   .sitemark, .castle and .words; it is centred here because the front door
   has no brandbar to sit inside. */
.markwrap .sitemark{width:var(--fd-mark);justify-content:center;text-decoration:none}

/* The portal product line. The ONLY element allowed between the mark and
   the anchor line, and only on a portal that must name its product. */
.prodmark{font-size:clamp(20px,3.6vw,30px);font-weight:800;color:var(--navy);
  letter-spacing:.01em;line-height:1.1;margin:clamp(10px,2vh,18px) 0 10px;
  text-align:center}
.prodmark em{font-style:italic;color:var(--gold-deep)}


/* ---------------------------------------------------------------------
   3. CENTRE STAGE

   == OVERRIDE 3 ==  royal-system.css gives .stage a var(--sec) bottom pad
   (up to 84px) and a var(--gutter) side pad, both sized for a long page.
   The front door has a fixed 40px floor and a 20px gutter so the coin row
   and the footer stay in one viewport on a phone.
   --------------------------------------------------------------------- */
.stage{flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:flex-start;padding:clamp(18px,4vh,44px) 20px 40px;width:100%}


/* ---------------------------------------------------------------------
   4. THE ANCHOR LINE

   == OVERRIDE 4 ==  royal-system.css sets .anchorline as a HEADLINE -
   17px, weight 700, full --ink, capped at 36ch - because on a marketing
   page it is the headline. On the front door it is a quiet line under a
   large mark: 15.5px, weight 600, --muted, 56ch. Bryan approved the
   quieter one. Restated here in full so a future edit to the system's
   marketing anchor cannot reach into the intro screen.
   --------------------------------------------------------------------- */
.anchorline{font-size:clamp(13px,1.9vw,15.5px);color:var(--muted);font-weight:600;
  margin:0 0 18px;text-align:center;max-width:56ch;line-height:1.5}


/* ---------------------------------------------------------------------
   5. THE ASK BAR
   This bar IS the assistant (Bryan, 7/28/2026). There is no gold seat on
   the left and no sleeping ball below - do not clone either from live
   royalai.ai.

   == OVERRIDE 5 ==  royal-system.css positions the send orb through a
   .btns wrapper and puts the gold gradient on a .go class, because its bar
   can carry a microphone as well. The front door's bar is one button,
   absolutely positioned, and the gradient is on the button itself. Both
   selector shapes are covered below so the branded-placeholder variant
   (which does use .btns/.go) drops in without a second edit.
   --------------------------------------------------------------------- */
.searchbox{width:var(--fd-col);position:relative;margin:0}
.searchbox input{width:100%;border:1.5px solid var(--line);border-radius:999px;
  background:var(--card);padding:17px 58px 17px 26px;font-size:16.5px;font-family:inherit;
  color:var(--ink);box-shadow:0 10px 30px rgba(21,43,107,.10);outline:none;
  transition:box-shadow .2s,border-color .2s}
.searchbox input:focus{border-color:var(--gold);box-shadow:0 12px 34px rgba(202,162,95,.28)}
/* The plain front-door placeholder is a real one and must stay visible.
   royal-system.css turns every .searchbox placeholder transparent for the
   .phold overlay; put it back unless this page actually ships .phold. */
.searchbox input::placeholder{color:var(--muted);opacity:1}
.searchbox:has(.phold) input::placeholder{color:transparent}

/* THE GOLD SEND ORB. The gradient is the coin's own material - the same
   light source, at orb scale. Never re-mix it. */
.searchbox button,
.searchbox .btns{position:absolute;right:8px;top:50%;transform:translateY(-50%)}
.searchbox .btns{display:flex;align-items:center;gap:6px}
.searchbox .btns button{position:static;transform:none}
.searchbox button,
.searchbox .go{width:40px;height:40px;min-height:40px;border-radius:50%;border:none;
  cursor:pointer;padding:0;display:grid;place-items:center;flex:none;
  background:radial-gradient(circle at 32% 26%,#fdf6e3 0%,#f0d9a6 22%,#d5b271 45%,#ab854a 70%,#7d6238 100%);
  box-shadow:0 3px 8px rgba(21,27,60,.25)}
.searchbox button svg,
.searchbox .go svg{width:17px;height:17px;stroke:var(--navy-deep);stroke-width:2.4;fill:none}
/* Sending. The orb dims while the engine is streaming and comes back on
   its own - no spinner, nothing new on screen. */
.searchbox button[aria-busy="true"]{opacity:.55;cursor:default}


/* ---------------------------------------------------------------------
   6. THE ANSWER PANEL
   The system's equivalent is .askout. The front door keeps the name
   .answer because that is what shipped and what every clone already has.
   --------------------------------------------------------------------- */
.answer{width:var(--fd-col);background:var(--card);border:1px solid var(--line);
  border-radius:18px;margin-top:14px;padding:18px 22px;font-size:14.5px;line-height:1.6;
  color:var(--ink);box-shadow:0 10px 30px rgba(21,43,107,.08);display:none;text-align:left}
.answer.show{display:block;animation:rise .28s ease}
@keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.answer .q{color:var(--muted);font-size:13px;margin:0 0 8px}
.answer .a{margin:0;white-space:pre-wrap}
.answer .hook{margin:12px 0 0;padding-top:10px;border-top:1px dashed var(--line);
  font-size:11.5px;color:var(--muted)}
.answer .hook:empty{display:none}
/* The beat between the send and the first word of a streamed answer -
   three gold dots, and only while .a is genuinely still empty. */
.answer.thinking .a:empty::after{content:"\25CF\00a0\25CF\00a0\25CF";color:var(--gold-deep);
  letter-spacing:.2em;animation:fd-pulse 1.1s ease-in-out infinite}
@keyframes fd-pulse{0%,100%{opacity:.35}50%{opacity:1}}


/* ---------------------------------------------------------------------
   7. THE GOLDEN CIRCLES

   THE ONE COIN LAW. 108px max. .inner is 68% of the coin. The mark is
   capped at 59% of .inner. 0.68 x 0.59 = 40.1% of the coin diameter -
   Bryan's own correction after he caught the R sitting ~14% oversize.
   These two numbers are the whole law.

   THE CANON GRADIENT below is reproduced verbatim. Its 52% stop is
   #c9a15f and it stays #c9a15f - that is the coin's own material, not a
   brand token, and it is the one hex on this page that is NOT #CBA260.

   The coin is FLUID here (width 100%, capped at 108) rather than the
   system's rigid 108x108, because every grid below is a row that has to
   hold its balls across a 375px phone without overflowing.
   --------------------------------------------------------------------- */
.bubbles{display:grid;grid-template-columns:repeat(4,1fr);
  gap:clamp(10px,2vw,20px);margin-top:clamp(26px,5vh,52px);width:var(--fd-col)}

.bubble{display:flex;flex-direction:column;align-items:center;gap:9px;
  text-decoration:none;color:var(--ink);min-width:0;background:none;border:none;
  padding:0;font-family:inherit;cursor:pointer}

.coin{width:100%;max-width:108px;height:auto;aspect-ratio:1;border-radius:50%;position:relative;
  background:
    radial-gradient(circle at 32% 24%, #fdf6e3 0%, #f5e2b4 16%, #e2c283 34%, #c9a15f 52%, #a5814a 70%, #7d6238 86%, #6a5330 100%);
  box-shadow:
    0 10px 24px rgba(21,27,60,.22),
    inset 0 2px 6px rgba(255,255,255,.65),
    inset 0 -6px 12px rgba(90,66,30,.45);
  display:grid;place-items:center;flex:none;
  transition:transform .18s ease, box-shadow .18s ease}
.coin::after{content:"";position:absolute;inset:0;border-radius:50%;
  background:linear-gradient(135deg,rgba(255,255,255,.55) 0%,rgba(255,255,255,0) 38%,rgba(255,255,255,0) 62%,rgba(255,255,255,.28) 100%);
  pointer-events:none}
.bubble:hover .coin,
.bubble:focus-visible .coin{transform:translateY(-4px) scale(1.04);
  box-shadow:0 16px 32px rgba(21,27,60,.30),
    inset 0 2px 6px rgba(255,255,255,.65),
    inset 0 -6px 12px rgba(90,66,30,.45)}

/* THE SEATING LAW - the white medallion and its 59% cap. */
.coin .inner{width:68%;height:68%;border-radius:50%;background:rgba(255,255,255,.92);
  display:grid;place-items:center;box-shadow:inset 0 1px 4px rgba(90,66,30,.35);overflow:hidden}
.coin .inner svg{width:72%;height:auto;display:block}
.coin .inner img{max-width:59%;max-height:59%;width:auto;height:auto;display:block}
.coin .inner img.r{max-width:59%;max-height:59%}
/* A coin whose face is set in type rather than art. */
.coin .brandtxt{font-weight:800;color:var(--navy);text-align:center;line-height:1.05;
  letter-spacing:.02em;font-size:clamp(9px,1.7vw,12.5px)}
.coin .brandtxt small{display:block;font-weight:700;color:var(--gold-deep);
  font-size:.72em;letter-spacing:.14em;margin-top:2px}

.bubble .label{font-size:clamp(12px,1.6vw,12.5px);font-weight:700;color:var(--muted);
  text-align:center;letter-spacing:.04em;line-height:1.25}
.bubble .label b{color:var(--navy);font-weight:800}
.bubble .label em{font-style:italic;color:var(--gold-deep);font-weight:800}
.bubble:hover .label{color:var(--navy)}
/* AN AUDIENCE DOOR names who it is for and nothing else - no verb, no
   dash. Navy caps so it reads as a title, not a caption. */
.bubble .label.aud{color:var(--navy);font-weight:800;text-transform:uppercase;
  letter-spacing:.13em;font-size:clamp(11px,1.5vw,12px)}


/* ---------------------------------------------------------------------
   7a. THE FIVE FUNNEL GRIDS - ONE NAMING SCHEME, AND ONLY ONE

     .g8   L1  index.html   8 balls, 4 + 4
     .l2   L2  start.html   6 balls, 3 + 3      intent
     .l3   L3  stand.html   4 balls, 2 + 2      situation
     .l4   L4  ready.html   2 balls             readiness
     .l5   L5  door.html    1 ball, centred     apply

   RETIRED, AND NOT COMING BACK: .g6 .g5 .g4 .g2 .g1. The layer math is
   8-6-4-2-1 and a five-up row is not a shape in it. A hub whose markup
   still says class="bubbles g6" predates this kit: its nav is REBUILT to
   .g8, never restyled back. (royal-system.css keeps its own .coins.g3
   and .coins.g5 for the SYSTEM's coin grid - different component,
   different file, and not ours to touch.)

   WHY THE LAYER GRIDS CAP THEIR TRACKS INSTEAD OF TAKING 1fr.
   At the 620 column the home grid's track is (620 - 3x20) / 4 = 140px
   carrying a 108px coin, so ball edge to ball edge reads 16 + 20 + 16 =
   52px. Give .l2 three plain 1fr tracks and the same six-ball page reads
   85px of air between balls - a different room on the same site.
   minmax(0,140px) plus centring puts every layer on the flagship's exact
   52px rhythm with no magic numbers, and below the cap the tracks shrink
   together so the coin still lands on the same size the home grid paints.

   NONE OF THESE ROWS EVER FOLDS. Four-up holds to 375px - that is the
   shape Bryan signed off on - and three-up, two-up and one-up all have
   more room than four-up has.
   --------------------------------------------------------------------- */
.bubbles.g8{grid-template-columns:repeat(4,1fr);row-gap:clamp(16px,3.6vw,26px)}
/* 🔑 FOUR TRACKS, NOT THREE — CORRECTED 2026-08-04, AND THIS IS THE GRID LAW.
   Bryan, comparing x.html against royalreverse.ai: "just make it look like
   royal reverse bubble location."

   MEASURED, both pages, 1265px content box:
                              col A   col B   col C   tracks
     royalreverse.ai (his ref)  331     491     651    4 x 140
     x.html BEFORE              419     579     739    3 x 140
     x.html AFTER               331     491     651    4 x 140

   A THREE-TRACK GRID RE-CENTRES ITSELF and slides A, B and C right by half a
   pitch — exactly 88px here. A four-track grid holds them still and simply
   leaves column D empty. THE GRID LAW says it in one line: "ALWAYS 4 tracks,
   only col D disappears. Never change this to repeat(3,...)." The subdomains
   already obey it because grid-law.css pins them; royalai.ai does not link
   that file, so this sheet has to carry the same rule itself.

   The paragraph above about "three plain 1fr tracks" reads 85px of air — that
   reasoning still holds and is NOT what this changes. minmax(0,140px) keeps
   the 52px ball-to-ball rhythm; only the TRACK COUNT changes, so the coins
   keep their spacing and stop sliding sideways between sites.

   🚨 PINNING EACH ITEM IS THE OTHER HALF AND IT IS LOAD-BEARING. Four tracks
   alone make it worse, not better: six balls left to flow freely fill
   A B C D then A B — a 4+2 page where the slate says 3+3. Pinning the wrap to
   three keeps the shape AND keeps column D deliberately empty. */
.bubbles.l2{grid-template-columns:repeat(4,minmax(0,140px));justify-content:center;
  row-gap:clamp(16px,3.6vw,26px)}
.bubbles.l2 > *:nth-child(3n+1){grid-column:1}
.bubbles.l2 > *:nth-child(3n+2){grid-column:2}
.bubbles.l2 > *:nth-child(3n+3){grid-column:3}

/* THE RESERVED SCROLLBAR, the other half of the same 8px. THE CONTINUITY LAW.
   royalreverse.ai measures its ask bar at x=315 and x.html measured 323: a
   short page has no scrollbar, a tall one does, and the whole page slides
   sideways the instant that changes. index.html and app.html each declare this
   inline; the five .l2 pages — door, ready, stand, start, x — declared it
   nowhere, so it goes here once and covers all of them.
   overflow-y:scroll is the FALLBACK and is not redundant: measured on 8/2,
   scrollbar-gutter alone did not reserve the track on the short page. */
html{scrollbar-gutter:stable;overflow-y:scroll}
.bubbles.l3{grid-template-columns:repeat(2,minmax(0,140px));justify-content:center;
  row-gap:clamp(16px,3.6vw,26px)}
.bubbles.l4{grid-template-columns:repeat(2,minmax(0,140px));justify-content:center}
/* THE TERMINAL BALL. One ball, centred, at the full canon 108px. The
   nest's 84px cap is a TRAY rule (section 8) and it never reaches a
   layer page - the last ball in the funnel is not a tray chip. */
.bubbles.l5{grid-template-columns:minmax(0,108px);justify-content:center}


/* ---------------------------------------------------------------------
   7b. NO-LABEL BALL MODE - the sanctioned variant

   THE RULING: no title text under any ball on a hub home or on any of
   the four layer pages. The accessible name rides aria-label ON THE
   ANCHOR and nowhere else, so a screen reader still gets a real name
   while the screen stays clean.

     <a class="bubble" href="start.html" aria-label="Where do you stand">
       <span class="coin coin-awake-default"><span class="inner">
         <img src="..." alt="">
       </span></span>
     </a>

   THREE THINGS THIS MODE OWES THE VISITOR, and all three are below:

     1. NO SLEEPING COIN. A funnel ball with no label under it and no
        face in it is a blank gold disc - the exact thing Bryan killed on
        7/25. Faces are readable from the FIRST PAINT here. Hub grids
        write .coin-awake-default; the rule below also makes that class
        work with this sheet's .inner as well as the system's
        .coin-inner, and it refuses .coin-asleep outright inside a
        .bubbles grid. Sleeping is a deep-page behaviour. Not here.
     2. THE 44px TAP FLOOR. With the label gone the coin is the whole
        target, so the cell keeps a 44px minimum height of its own even
        if a coin ever paints smaller than that.
     3. A FOCUS RING A KEYBOARD VISITOR CAN ACTUALLY SEE. The house ring
        is gold, and gold on a gold ball is invisible - so on a bare
        coin the ring is NAVY and it is drawn on the coin itself, where
        border-radius makes it a true circle around the ball. That is an
        accessibility requirement, not a design change.

   The label rules in section 7 stay exactly as they are: the nest tray
   and every non-funnel grid still label their coins. This mode is
   markup - you leave the <span class="label"> OUT. Nothing here hides a
   label you left in, on purpose: a stray label must stay visible so the
   publish check catches it instead of the sheet swallowing it.
   --------------------------------------------------------------------- */
.bubbles.nolabel .bubble{gap:0;min-height:44px;justify-content:center}
/* the sanctioned awake class, honoured for both inner namings */
.coin.coin-awake-default .inner,
.coin.coin-awake-default .coin-inner{opacity:1;transform:none;transition:none}
/* NO SLEEPING COIN on a funnel grid, whatever the markup says */
.bubbles .coin.coin-asleep .inner,
.bubbles .coin.coin-asleep .coin-inner{opacity:1;transform:none;transition:none}
/* the ring, on the ball, in navy */
.bubbles.nolabel .bubble:focus-visible{outline:none}
.bubbles.nolabel .bubble:focus-visible .coin{outline:3px solid var(--navy);
  outline-offset:4px}


/* ---------------------------------------------------------------------
   8. THE NEST - bubbles inside a bubble.
   The deep door's tray. CLOSED on load and only a touch opens it: nothing
   on this page moves by itself.
   --------------------------------------------------------------------- */
.nest{width:var(--fd-col);margin-top:clamp(14px,2.6vh,22px);
  border:1.5px solid var(--line);border-radius:22px;background:var(--card);
  box-shadow:0 10px 30px rgba(21,43,107,.08);padding:18px 18px 20px;display:none}
.nest.open{display:block;animation:rise .26s ease}
.nest .nesthead{font-size:11.5px;font-weight:800;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);text-align:center;margin:0 0 15px}
.nest .nesthead b{color:var(--navy)}
.nest .nesthead em{font-style:italic;color:var(--gold-deep)}
.nestrow{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(10px,2.4vw,20px)}
/* 84px, and it is a TRAY number. A tray chip sits inside a card inside
   the room, so it steps down from the 108 canon. It has no business on a
   layer page: .l5's single terminal ball is the full 108 (section 7a). */
.nestrow .coin{max-width:84px}
.nestrow .bubble .label{font-size:clamp(11px,1.5vw,12px)}


/* ---------------------------------------------------------------------
   9. THE FOOTER

   == OVERRIDE 5 ==  royal-system.css puts a border-top and a var(--sec)
   margin above the footer, which is right at the end of a long page and
   wrong here: on the front door the footer is the quiet last line of a
   single-screen room, with no rule drawn across it.

   This is the ENTIRE standard footer style. No state list, no licensing
   block, no second disclaimer - RULING 14.
   --------------------------------------------------------------------- */
footer{padding:22px 16px 26px;text-align:center;font-size:11.5px;
  color:var(--muted);line-height:1.6;border-top:none;margin-top:0}
footer b{color:var(--ink)}
footer .brandword{color:var(--navy)}
footer .brandword em{font-style:italic;color:var(--gold-deep)}
footer a{color:var(--muted)}
footer a:hover{color:var(--navy)}
.ehl{width:13px;height:13px;vertical-align:-2px;fill:currentColor}

/* THE NUDGE MUST NOT SIT ON THE NMLS LINE. This page is exactly one
   viewport tall on a phone, so the footer rests on the bottom edge - and
   .a2hs is fixed 16px above that same edge. On the only device that ever
   shows the pill, an iPhone in Safari, it landed squarely across
   "#2059962 (nmlsconsumeraccess.org) · Equal Housing Lender". Reserve its
   height ONLY while it is actually on screen: hidden - every other device,
   and every visit after it is waved away - the footer is untouched. .stage
   is flex:1 and absorbs the difference, so nothing new scrolls. */
body:has(.a2hs:not([hidden])) footer{padding-bottom:82px}


/* ---------------------------------------------------------------------
   10. THE iPHONE HOME-SCREEN PILL - one sunny line.
   Off-flow, hidden on every other device, and remembered once waved away.
   --------------------------------------------------------------------- */
.a2hs{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:40;
  display:flex;align-items:center;background:var(--card);border:1.5px solid var(--gold);
  border-radius:99px;padding:7px 4px 7px 15px;box-shadow:0 12px 30px rgba(14,29,73,.20);
  max-width:94vw;white-space:nowrap}
.a2hs[hidden]{display:none}
.a2hs .dot{width:18px;height:18px;border-radius:50%;flex:none;margin-right:9px;
  background:radial-gradient(circle at 32% 26%,#fdf6e3 0%,#f0d9a6 25%,#d5b271 50%,#ab854a 78%,#7d6238 100%);
  box-shadow:inset 0 1px 2px rgba(255,255,255,.6)}
.a2hs a{color:var(--ink);text-decoration:none;font-size:13px;font-weight:600;
  min-width:0;overflow:hidden;text-overflow:ellipsis}
.a2hs a b{color:var(--navy);font-weight:800}
.a2hs a b em{font-style:italic;color:var(--gold-deep)}
.a2hs .x{background:none;border:none;color:var(--muted);font-size:18px;font-weight:700;
  cursor:pointer;padding:6px 12px;line-height:1;font-family:inherit}
.a2hs .x:hover{color:var(--navy)}


/* ---------------------------------------------------------------------
   11. THE TOAST
   royal-system.css already carries .toast and .toast.show at z-index 90.
   Nothing to restate; front-door.js drives it. Every tap gets an answer,
   never a dead click.
   --------------------------------------------------------------------- */


/* ---------------------------------------------------------------------
   12. NARROW PHONES

   THE PHONE FLOOR, and it was missing. royal-system.css caps a coin at
   72px from 390 down, but it writes that rule for .coin.coin-fluid and
   a front-door coin does not carry that class - so the cap never reached
   this sheet and a 375px phone painted a 78px ball where every other
   Royal surface paints a 72px one. It is restated below for the front
   door's own coin, which is what finally makes "the coin reads the same
   size on every site at every width" true rather than nearly true.

   THE OLD FIVE-AND-SIX-UP FOLD IS GONE, with .g5 and .g6. The layer math
   is 8-6-4-2-1 and not one of those rows needs to fold: four-up holds to
   375px (Bryan's signed-off shape), and three-up, two-up and one-up all
   have more room than four-up. One rule fewer on every page.

   MEASURED, at the two widths that matter, 16px gutter and 10px gap:
     375  four-up track (375-32-30)/4 = 78.25 -> coin 72   no overflow
     390  four-up track (390-32-30)/4 = 82.00 -> coin 72   no overflow
   --------------------------------------------------------------------- */
@media (max-width:390px){
  .stage{padding-left:16px;padding-right:16px}
  .searchbox input{padding:15px 52px 15px 20px;font-size:16px}
  /* the family-wide phone floor - the same 72 royal-system.css sets */
  .bubbles .coin,.nestrow .coin{max-width:72px}
  /* ...except the terminal ball. It is alone on the page, it is the one
     coin the whole funnel exists to hand over, and there is nothing on a
     375px screen for it to crowd. It keeps the full 108. FLAGGED: this
     is the one place the layer grids and the 390 floor disagree, and it
     is a deliberate call, not an oversight. */
  .bubbles.l5 .coin{max-width:108px}
}


/* ---------------------------------------------------------------------
   14. MOTION, FOCUS, PRINT
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .nest.open,.answer.show{animation:none}
  .coin{transition:none}
  .bubble:hover .coin,.bubble:focus-visible .coin{transform:none}
  .answer.thinking .a:empty::after{animation:none}
}
/* A visible ring on every focusable thing. The coins are links and the
   send orb is a button; a keyboard visitor must be able to see where they
   are without a mouse. */
.bubble:focus-visible,
.searchbox input:focus-visible,
.searchbox button:focus-visible,
.a2hs a:focus-visible,
.a2hs .x:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:8px}
@media print{
  .a2hs,.toast,.searchbox button{display:none}
  body{display:block;min-height:0}
  .coin{box-shadow:none}
}


/* =====================================================================
   15. THE ENTRY LAW — 2026-08-03.  WHERE A LAYER STARTS.

   Bryan, 2026-08-03: "On layer 3 and every layer after it, the bubbles /
   content start too far down the page. The continuity objective is
   broken: moving from layer 2 to layer 3 should feel like the same page
   continuing, not like a jump to a new document. The vertical entry
   point must be consistent from layer to layer."

   THIS SECTION IS THE ONE OWNER OF THAT NUMBER. Before it, four
   mutually-ignorant mechanisms decided where a layer started: grid-law
   .css (8 pages), the CONTINUITY LAW block inside royalai.ai/index.html
   (1 page), sections 2/3/6 of this file (every layer page, in vh), and
   roughly sixty per-page bespoke headers. Nothing below is a new number
   and nothing below may be restated in a page.

   THE TARGET IS LAYER 1, AND THREE FILES ALREADY AGREE ON IT:

       header band bottom ....... 162    grid-law.css --rg-head
       ask bar top .............. 242    = band + 80   --rg-bar-gap
       ask bar bottom ........... 299    the bar is 57 tall
       row 1 of coins ........... 319    = bar  + 20   --rg-grid-gap

   royalai.ai/index.html states all four in THE CONTINUITY LAW and builds
   them out of 50 + 64 + 22 + 26 + 80. grid-law.css measured the same
   four off that page in the browser at 1280px. And royalmortgage-ai/
   index.html says it a third way: "the TARGET is 128px mark-ink-bottom
   to bar-top" — 128 = 22 stage pad + 26 slogan seat + 80.

   WHY LAYERS 2-5 MISSED IT. Two causes, both measured, not guessed:

     1. THE UNIT WAS WRONG. Layer 1 is fixed px. Sections 2, 3 and 6
        above put .markwrap, .stage and .bubbles on vh-relative clamps,
        so every layer under the front door moved with the WINDOW HEIGHT
        while the front door stood still. Those two can never agree at
        any viewport, at any value.
     2. THE QUESTION HAD NO SEAT. .layerq / .anchorline were sized by
        their own string. "What brings you here?" is one line; "Where
        are you right now?" wraps to two. That single wrap IS the ~35px
        step between layer 2 and layer 3. door.html's second ruled
        sentence is another ~65 on top of it, which is how layer 5's
        coins reached 421 against the front door's 319.
        royalai.ai/index.html:1481 solved this exact problem for layer 1
        with h1.tagline{height:26px} and the fix was never carried down.
        This section carries it down.

   SO THE LAW IS: the header is a FIXED 162px band, the question rides
   in a RESERVED 80px seat under it, and the ask bar's own top margin
   goes to zero. Whatever the question says, however many lines it wraps
   to, and however tall this store's lockup is — the bar lands at 242
   and row 1 lands at 319.

   🔑 IT FIRES ONLY ON A LAYER PAGE, BY CONSTRUCTION, SO NO PAGE HAD TO
   BE EDITED TO OPT IN OR OUT. The body:has() guard on every rule means
   the whole section is inert unless a question sits IMMEDIATELY before
   the ask bar. royalai.ai/index.html carries .tagline (excluded by
   name) and a .chat box between it and the bar, so the front door never
   sees these rules and keeps its own CONTINUITY LAW block untouched.
   The subdomain front doors carry no question at all, so they never see
   them either. That is deliberate: the front door IS the standard and
   must not be re-derived from it.

   🔑 IT YIELDS TO grid-law.css ON PURPOSE. Exactly one declaration
   below is !important — see it for why. Everything else loses to the
   Grid Law's !important rules, so on the pages that link the Law the
   Law still owns the band, the columns and the cells. Both files say
   162 / 80 / 20, so they agree by value as well as by rank.

   🚨 DO NOT RE-EXPRESS ANY OF THESE FOUR NUMBERS IN A PAGE. That is the
   fault this section exists to end. If a layer has to move, move it
   here, in the token block, once, and every layer in every store moves
   with it.
   --------------------------------------------------------------------- */
:root{
  --el-band:162px;  /* header band bottom      = grid-law --rg-head      */
  --el-seat:80px;   /* band bottom -> bar top  = grid-law --rg-bar-gap   */
  --el-row1:20px;   /* bar bottom  -> row 1    = grid-law --rg-grid-gap  */
  --el-lift:2px;    /* see .markwrap                                     */
}

/* THE HEADER BAND. A fixed height, not a padding chain, because the
   lockups are NOT the same height from store to store — 64 on
   royalai.ai, 106 on royalmortgage-ai, 122 on royalheloc.ai. Stacking
   margins under marks of different heights is exactly what put the ask
   bar 40-70px apart from one store to the next. A fixed band means the
   bar and the coins land in the same place whichever mark is on it.

   🔑 flex:0 0 auto IS LOAD-BEARING, DO NOT DROP IT. Section 1 makes
   <body> a full-height COLUMN flex container, so this band is a flex
   ITEM on the main axis and a stated height with flex-shrink:1
   collapses under pressure. grid-law.css learned this the hard way on
   royalxpress.ai, where a 162px band measured 0px and the ask bar sat
   at y=80. Locking the basis is what makes the band actually hold.

   THE 2px LIFT. The mark is centred in the band, and centring a 64px
   lockup inside 162px lands its ink top at 49 — one pixel above layer
   1's measured 50. 2px of top padding inside a border-box moves the
   centre line down by exactly one: (162 - 2 - 64) / 2 + 2 = 50. Taller
   lockups centre lower in the same band and never overflow it. */
body:has(.stage > :is(.layerq,.anchorline:not(.tagline)) + .searchbox) .markwrap{
  height:var(--el-band);
  box-sizing:border-box;
  padding:var(--el-lift) 16px 0;
  flex:0 0 auto;
  display:flex;
  align-items:center;
  justify-content:center;
}

/* THE STAGE ADDS NOTHING ON TOP. The band above already ends at 162 and
   every pixel between there and the bar belongs to the seat below.
   Only padding-top is touched: section 3's horizontal and bottom
   padding stand, and the 390px phone rule that narrows the gutters
   still applies because it is a different property. */
body:has(.stage > :is(.layerq,.anchorline:not(.tagline)) + .searchbox) .stage{
  padding-top:0;
}

/* THE QUESTION'S SEAT. 80px, reserved, whatever the question says. One
   line centres in it, two lines fill it, and three lines of the 21px
   phone size (76.9) still fit inside it. This is index.html's
   h1.tagline{height:26px} carried down to the layers, which is where it
   always belonged. */
body:has(.stage > :is(.layerq,.anchorline:not(.tagline)) + .searchbox) .stage > .layerq,
body:has(.stage > :is(.layerq,.anchorline:not(.tagline)) + .searchbox) .stage > .anchorline:not(.tagline){
  min-height:var(--el-seat);
  margin:0;
  display:flex;
  align-items:center;
  justify-content:center;
  text-align:center;
}

/* THE ONE PAGE WITH TWO BLOCKS. royalai.ai/door.html carries a ruled
   second sentence under its question; no other layer page in the family
   does. The two SHARE the one seat rather than each taking a full one —
   44% to the question, 56% to the sentence, summing to exactly 80.
   THE MEASURED RESIDUAL, STATED RATHER THAN HIDDEN: at 1280px the
   question's own line box is 35.4 against its 35.2 share and the
   sentence's two lines are 46.5 against 44.8, so that one page's bar
   sits at 243.9 instead of 242 and its ball at 320.9 instead of 319.
   1.9px. It was 319 against 421 before this section existed. On a phone
   both blocks fit inside their shares and the page is exact. */
body:has(.stage > .layerq + .anchorline + .searchbox) .stage > .layerq{
  min-height:calc(var(--el-seat) * .44);
}
body:has(.stage > .layerq + .anchorline + .searchbox) .stage > .layerq + .anchorline{
  min-height:calc(var(--el-seat) * .56);
}

/* THE BAR CARRIES NO MARGIN OF ITS OWN. Its distance from the header is
   the seat above it and nothing else.

   🚨 THIS IS THE ONE !important IN THE SECTION AND IT IS REQUIRED.
   grid-law.css:148-151 sets .searchbox{margin:80px auto 0 !important} —
   correct on a front door, where the bar is the stage's FIRST child,
   and wrong on a layer page, where a question sits in front of it. That
   is a MARGIN, not a position, so it stacks on top of the question
   instead of absorbing it. It is why royalheloc.ai/dsx.html and
   home-value.html measured a 283px bar with the Grid Law linked and
   working. This selector is (0,4,0) against the Law's (0,1,0), so it
   wins the single declaration it has to and leaves the Law's band,
   column, cell and coin rules completely untouched. */
body:has(.stage > :is(.layerq,.anchorline:not(.tagline)) + .searchbox) .stage > :is(.layerq,.anchorline) + .searchbox{
  margin-top:0 !important;
}

/* ROW 1 OF COINS, 20px UNDER THE BAR. The same value grid-law.css sets,
   so this changes nothing on a page that links it; on every layer page
   it replaces section 6's margin-top:clamp(26px,5vh,52px), which is the
   other half of the window-height drift.
   The ~ combinator is deliberate: .answer sits between the bar and the
   coins and is display:none at rest. */
body:has(.stage > :is(.layerq,.anchorline:not(.tagline)) + .searchbox) .stage > .searchbox ~ .bubbles{
  margin-top:var(--el-row1);
}
