/* ==========================================================================
   THE GRID LAW — one grid, every Royal page.  Generated 2026-08-02.

   Bryan: "Everything must always be on the same exact grid throughout the
   entire website. That is what makes it Royal. That is the Royal standard."

   THE STANDARD IS royalai.ai/index.html. Every number here was MEASURED off
   that page in the browser at 1280px, not chosen:

       ROYAL ink box    x 429   y 53    w 284   h 58
       the ask bar      x 322   y 242   w 620   h 57
       the bubble grid  x 322   y 319   w 620
       column centres   392 · 552 · 712 · 872     4 tracks of 140px, gap 20
       row centres      373 · 522                 cell 149px, row-gap 18
       the coin         108px

   The content column is 620px centred, so ROYAL's left edge is 107px into it
   and ROYAL is 284/620 = 45.8065% of it.

   🚨 DO NOT EDIT A COPY OF THIS FILE. It is generated byte-identical into every
   site by scratchpad\\apply_grid_law.py. Change the grid there, re-run, and
   every store changes together. Editing one copy is how the family drifts apart
   again, which is the exact fault this file exists to fix.

   🚫 royalai.ai/index.html DOES NOT LINK THIS FILE and must not. It IS the
   standard — it already measures correctly, and it is the only page whose
   ROYAL sits inside a one-row lockup, so these rules would not describe it.
   ========================================================================== */
:root{
  --rg-col:620px;        /* the content column, centred                       */
  --rg-royal-top:53px;   /* ROYAL's ink top, from the top of the document     */
  --rg-royal-left:17.2581%;  /* 107 / 620                                     */
  --rg-royal-w:45.8065%;     /* 284 / 620                                     */
  --rg-head:162px;       /* ROYAL's seat + the slogan's empty seat            */
  --rg-bar-gap:80px;     /* header band -> ask bar   = bar top 242            */
  --rg-grid-gap:20px;    /* ask bar     -> bubbles   = grid top 319           */
  --rg-track:140px;
  --rg-colgap:20px;
  --rg-rowgap:18px;
  --rg-cell:149px;
  --rg-coin:108px;
}

/* --------------------------------------------------------------------------
   ROW 0 — ONE SCROLLBAR, AND IT LIVES ON <html>.

   THE CONTINUITY LAW, restated here so it is uniform by construction: the
   gutter is reserved on every page so nothing slides sideways the instant a
   scrollbar appears.

   🔑 AND THE SECOND SCROLLBAR IS THE ONE THAT ACTUALLY BIT. front-door.css
   leaves <body> at overflow-y:auto. On a SHORT page nothing happens. On a TALL
   page — royalxpress.ai is the only one — the body grows its OWN scrollbar
   INSIDE the one on <html>, which eats ~15.7px out of the body's content box.
   Everything centred inside then re-centres on a narrower box and the whole
   page slides 7px left. ROYAL at 422 instead of 429; every column at 385/545/
   705/865 instead of 392/552/712/872. Small enough to look like nothing in a
   screenshot and unmistakable the moment you surf between two pages.
   So: the document scrolls, the body never does.
   -------------------------------------------------------------------------- */
html{scrollbar-gutter:stable !important;overflow-y:scroll !important}

/* 🔑 overflow-x:clip, NOT hidden, AND THE DIFFERENCE IS THE WHOLE FIX.
   front-door.css sets body{overflow-x:hidden} to stop sideways scroll. The CSS
   spec then FORCES the other axis: overflow-y:visible beside a hidden/scroll/
   auto sibling computes to auto. So "body{overflow-y:visible}" silently became
   "auto" and the body kept its own scrollbar — the first attempt at this fix
   changed nothing and measured identically. `clip` is the one value that
   suppresses sideways scroll WITHOUT dragging the other axis into auto, so the
   body stops being a scroll container and its content box is the full 1265px
   on a tall page and a short one alike. */
body{overflow-x:clip !important;overflow-y:visible !important}

/* --------------------------------------------------------------------------
   ROW 1 — THE HEADER BAND, AND WHY IT IS A FIXED HEIGHT.
   The lockups are 318 to 365px tall depending on the site. Stacking margins
   under a mark of varying height is what pushed the ask bar 61-72px down the
   page on every subdomain. A fixed band means rows 3 and 4 start at the same y
   no matter which mark is on the page.
   -------------------------------------------------------------------------- */
.markwrap,
header.royal-header{
  position:relative !important;
  box-sizing:border-box;
  width:min(var(--rg-col),100%) !important;
  height:var(--rg-head) !important;
  margin:0 auto !important;
  padding:0 !important;
  /* 🔑 flex:0 0 auto IS LOAD-BEARING, DO NOT DROP IT. front-door.css makes
     <body> a full-height COLUMN flex container, so this band is a flex ITEM on
     the main axis. Its only child is absolutely positioned, so its min-content
     height is 0 — and a flex item with flex-shrink:1 collapses its stated
     height straight to 0. That is exactly what happened on royalxpress.ai: the
     162px band measured 0px and the ask bar sat at y=80 instead of y=242.
     Locking the flex basis is what makes the fixed band actually hold. */
  flex:0 0 auto !important;
}

/* THE WORD IS PINNED, NOT THE IMAGE. In all six subdomain lockups ROYAL is the
   top row and occupies the file's full width (x 0-944, y 0-193, measured from
   each PNG's alpha). So sizing the anchor to 284px and topping it at 53px puts
   ROYAL itself exactly where the front door puts it — and the WORD below it and
   the .Ai ride along wherever the artwork puts them. That is his rule: "the
   only thing that will change is where the AI logo is placed."
   ASPECT IS STILL SACRED: one dimension is set, the other is auto. */
.markwrap > a,
header.royal-header > a{
  position:absolute !important;
  top:var(--rg-royal-top) !important;
  left:var(--rg-royal-left) !important;
  width:var(--rg-royal-w) !important;
  margin:0 !important;
  padding:0 !important;
  min-height:0 !important;
  display:block !important;
}
img.brandmark{
  display:block !important;
  width:100% !important;
  height:auto !important;
  max-width:none !important;
}

/* ROW 2 — THE SLOGAN'S SEAT, HELD OPEN AND DELIBERATELY EMPTY.
   Bryan: "we will not have the slogan below it." The seat is not removed,
   because removing it is what floats the ask bar up and breaks row 3. It is
   inside the 162px band above. Nothing is drawn in it on a subdomain. */

/* --------------------------------------------------------------------------
   ROW 3 — THE ASK BAR.  Lands at y 242, width 620, on every page.
   -------------------------------------------------------------------------- */
/* THE STAGE CARRIES NO HORIZONTAL PADDING. royalxpress.ai had padding:0 20px
   40px, which narrowed its content box to 1249px against everyone else's 1265
   and slid ROYAL, the bar and every column 7px left — small enough to look like
   nothing and large enough to be visible when you surf between two pages. The
   centred boxes below own their own width; the stage must not offset them.
   Breathing room on a phone is handed to those boxes in the media query. */
.stage{
  padding-top:0 !important;padding-left:0 !important;padding-right:0 !important;
  /* AND IT MUST STRETCH THE FULL BODY WIDTH. royalxpress.ai's stage measured
     1249px where every sibling's measured 1265 — a 16px shortfall, invisible on
     its own page and worth 7px of sideways jump the moment you surf onto it,
     because everything inside is centred on the stage's midpoint. It is a flex
     item on the body's cross axis, so it is pinned to stretch rather than left
     to be sized by whatever its content happens to be. */
  width:100% !important;max-width:none !important;align-self:stretch !important;
}
.searchbox{
  width:min(var(--rg-col),100%) !important;
  margin:var(--rg-bar-gap) auto 0 !important;
}

/* --------------------------------------------------------------------------
   ROW 4 — THE BUBBLES.  FOUR TRACKS, ALWAYS, ON EVERY PAGE.

   🔑 THIS IS THE HEART OF THE RULING. His words: "the only thing that should
   change from one click to the next click is that the fourth column ... should
   be removed. The first three columns should all remain in the same exact
   place." A three-track grid re-centres itself and slides columns A, B and C
   right by half a pitch. A four-track grid holds them still and simply leaves
   column D empty. Never change this to repeat(3,...).
   -------------------------------------------------------------------------- */
.bubbles,
nav.coins{
  display:grid !important;
  grid-template-columns:repeat(4,var(--rg-track)) !important;
  column-gap:var(--rg-colgap) !important;
  row-gap:var(--rg-rowgap) !important;
  width:var(--rg-col) !important;
  max-width:100% !important;
  margin:var(--rg-grid-gap) auto 0 !important;
  justify-content:center !important;
}

/* 🔑 THREE PER ROW, IN A FOUR-TRACK GRID. This is the other half of the ruling
   and without it the four tracks make things WORSE, not better: six balls left
   to flow freely fill A B C D then A B — a 4+2 page where his slate says 3+3.
   Pinning each item to a named column keeps the wrap at three AND keeps column
   D permanently, deliberately empty. His words: "the only thing that should
   change from one click to the next click is that the fourth column ... should
   be removed."
   🚫 royalai.ai/index.html does not link this file, so the front door still
   fills all four columns with its eight balls. That is the one page that owns
   column D. */
.bubbles > *:nth-child(3n+1),
nav.coins > *:nth-child(3n+1){grid-column:1 !important}
.bubbles > *:nth-child(3n+2),
nav.coins > *:nth-child(3n+2){grid-column:2 !important}
.bubbles > *:nth-child(3n+3),
nav.coins > *:nth-child(3n+3){grid-column:3 !important}

/* THE CELL. 149px tall with the coin pinned to its top edge is what sets the
   row pitch to 167. The subdomains were running a 44px centred cell, which is
   where the ~100px row drift came from.

   🔑 131 -> 149, 2026-08-03. The cell is not the coin - it is the coin PLUS the
   label's seat, and the seat is TWO lines (.cell .label{min-height:2.5em}),
   because titles wrap: "HELOC Equity Calculator", "First-Time Buyer". 131 was
   arithmetic for a ONE-line label and was never measured. When the sixteen
   doors got their words back on royalai.ai/app.html, its row 2 moved to 486
   while every subdomain sat at 468 - an 18px jump when you surf between them,
   which is the exact fault this file exists to kill. Measured after, all eight
   pages: row 1 = 319, row 2 = 486. */
.bubbles > .bubble,
.bubbles > a,
.bubbles > div,
nav.coins > .cell{
  min-height:var(--rg-cell) !important;
  justify-content:flex-start !important;
  align-self:start !important;
}
.bubbles .coin,
nav.coins .coin{max-width:var(--rg-coin) !important}

/* --------------------------------------------------------------------------
   THE PHONE. The grid stays FOUR TRACKS below the breakpoint too — uniformity
   is not a desktop-only promise — but the tracks go proportional so 620px of
   fixed columns cannot overflow a narrow screen.
   -------------------------------------------------------------------------- */
@media (max-width:719px){
  .bubbles,
  nav.coins{
    grid-template-columns:repeat(4,1fr) !important;
    column-gap:12px !important;
  }
  /* the side breathing room the stage used to supply, handed to the boxes
     themselves so they stay centred on the same axis as on desktop */
  .markwrap,
  header.royal-header,
  .searchbox,
  .bubbles,
  nav.coins{ width:calc(100% - 32px) !important; }
}

/* THE HOME ICON. The house replaced an inline <svg> that the page sized at
   59%; an <img> needs the same seat stated or it falls back to intrinsic
   size and blows out of the coin. THE SEATING LAW, unchanged. */
.wayhome .homebubble .coin .inner img{width:59%;height:auto;display:block}

/* THE CALCULATOR — the seat he settled on for royalheloc.ai, carried over
   verbatim so the same mark is the same size on both pages. */
.bubbles .bubble .coin .inner img[src$="calc-gold.png"]{
  max-width:70%;max-height:70%;width:70%;height:auto}
