/* ══ gate5 · tokens ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · DESIGN TOKENS — the shared vocabulary for the gate rebuild.
   ───────────────────────────────────────────────────────────────────────────
   Ten files build on this. Every colour, radius, shadow, easing and type step
   lives here and NOWHERE else, so ten independent passes still read as one
   page. No raw hex, no ad-hoc cubic-bezier, no magic radii outside this file.

   The palette is AON's own — sampled from client/assets/royal/ and the
   hud-* art, not invented. This is a medieval strategy game: aged gold,
   forged iron, deep night, parchment. Nothing neon.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* ── GOLD — the empire's colour. Five steps, used for hierarchy. ─────── */
  --g5-gold-1:  #fff4d2;   /* specular highlight on a bevel               */
  --g5-gold-2:  #ffe9a8;   /* lit face                                    */
  --g5-gold-3:  #e8c05e;   /* THE gold — rims, headings, primary accents  */
  --g5-gold-4:  #a97f33;   /* shaded face                                 */
  --g5-gold-5:  #6d4f1c;   /* deep shadow / engraved line                 */

  /* ── IRON & NIGHT — the surfaces everything sits on ─────────────────── */
  --g5-night:   #070a0d;
  --g5-iron-1:  #1b2028;
  --g5-iron-2:  #12161d;
  --g5-iron-3:  #0b0e13;
  --g5-well:    #05070a;   /* sunk inputs, insets                          */

  /* ── INK ── */
  --g5-ink:     #f3e9cf;
  --g5-ink-2:   #cbbb99;
  --g5-ink-3:   #9c8d72;
  --g5-ink-4:   rgba(156,141,114,.45);
  --g5-ink-on:  #1a1206;   /* text ON gold */

  /* ── SEMANTIC ── */
  --g5-ok:      #7fd6a0;
  --g5-warn:    #e8a94a;
  --g5-err:     #e08272;
  --g5-blood:   #8e2f24;   /* the register/danger side */

  /* ── SURFACES ── panels are FORGED, not glass. Near-opaque by design:
     the 3D kingdom is the background, not a texture to read text through. */
  --g5-plate:   linear-gradient(177deg, rgba(24,29,37,.965) 0%, rgba(13,17,23,.975) 58%, rgba(8,11,15,.98) 100%);
  --g5-plate-hi:linear-gradient(177deg, rgba(32,39,49,.97), rgba(17,22,30,.98));
  --g5-sunk:    linear-gradient(180deg, rgba(4,6,9,.88), rgba(9,12,17,.86));
  --g5-scrim:   radial-gradient(ellipse at 50% 42%, rgba(6,9,13,.72), rgba(2,3,5,.93));

  /* ── LINES ── */
  --g5-line:      rgba(232,192,94,.30);
  --g5-line-2:    rgba(232,192,94,.55);
  --g5-line-hot:  rgba(255,233,168,.9);
  --g5-bevel:     inset 0 1px 0 rgba(255,240,200,.14);
  --g5-engrave:   inset 0 -1px 0 rgba(0,0,0,.55);

  /* ── ELEVATION ── */
  --g5-e1: 0 2px 8px rgba(0,0,0,.5), var(--g5-bevel);
  --g5-e2: 0 10px 28px rgba(0,0,0,.6), var(--g5-bevel);
  --g5-e3: 0 22px 54px rgba(0,0,0,.7), var(--g5-bevel);
  --g5-e4: 0 40px 90px rgba(0,0,0,.82), 0 0 0 1px rgba(232,192,94,.12), var(--g5-bevel);
  --g5-glow-gold: 0 0 22px rgba(232,192,94,.35);
  --g5-glow-hot:  0 0 34px rgba(255,214,120,.55);

  /* ── RADII ── the painted frames are cut to these ── */
  --g5-r-xs: 4px; --g5-r-sm: 8px; --g5-r-md: 12px;
  --g5-r-lg: 16px; --g5-r-xl: 22px; --g5-r-pill: 999px;

  /* ── SPACING · 4px grid ── */
  --g5-s1:4px; --g5-s2:6px; --g5-s3:8px; --g5-s4:12px;
  --g5-s5:16px; --g5-s6:20px; --g5-s7:28px; --g5-s8:38px;

  /* ── TYPE ──
     display : Cinzel — the empire's voice. Headings, wordmark, CTAs.
     ui      : Inter  — labels, fields, everything functional.
     Both are already loaded by index.php. Do not add a third family. */
  --g5-f-display: 'Cinzel', Georgia, serif;
  --g5-f-ui:      'Inter', system-ui, sans-serif;

  --g5-t-hero:    700 clamp(34px,5.4vw,72px)/1.02 var(--g5-f-display);
  --g5-t-title:   700 22px/1.15 var(--g5-f-display);
  --g5-t-sub:     600 10px/1.4  var(--g5-f-ui);
  --g5-t-label:   600 12.5px/1.2 var(--g5-f-ui);
  --g5-t-body:    500 13.5px/1.5 var(--g5-f-ui);
  --g5-t-cta:     700 16px/1.2  var(--g5-f-display);
  --g5-track:     .06em;
  --g5-track-2:   .22em;   /* the wide engraved-caps look */

  /* ── MOTION ── */
  --g5-t-fast: .13s; --g5-t-base: .22s; --g5-t-slow: .38s; --g5-t-cine: .9s;
  --g5-ease:        cubic-bezier(.22,1,.36,1);
  --g5-ease-in-out: cubic-bezier(.65,0,.35,1);
  --g5-spring:      cubic-bezier(.34,1.56,.64,1);

  /* ── LAYERS ── one scale, so ten files never fight ── */
  --g5-z-scene:   0;    /* the 3D canvas + poster        */
  --g5-z-grade:   1;    /* colour grade / vignette       */
  --g5-z-amb:     2;    /* embers, god rays, particles   */
  --g5-z-ui:      3;    /* the gate itself               */
  --g5-z-float:  50;    /* online chip, discord, badges  */
  --g5-z-modal: 1000;
  --g5-z-toast: 1200;

  /* ── ART ── generated into assets/login5/art/ by tools/gate5_art/*.py ── */
  --g5-art: '/assets/login5/art';
}

@media (prefers-reduced-motion: reduce){
  :root{ --g5-t-fast:.001s; --g5-t-base:.001s; --g5-t-slow:.001s; --g5-t-cine:.001s; }
}

/* ══ gate5 · base ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   AGE OF NATIONS — GATE 5 "CITADEL"                    assets/login5/login5.css
   ───────────────────────────────────────────────────────────────────────────
   A real-DOM gate over the game's own LIVE 3D kingdom (gate3d.js — the same
   beffio city the game itself renders, resurrected from the v6 landing).
   Panels are the game's own painted art:
     · panel plate  = /client/assets/ui/hud-card-frame-v10-alpha.png (9-slice)
     · CTA buttons  = /client/assets/royal/btn_cta*.png
   Wiring is untouched: login2.js binds by id, and every id it expects exists
   in the new DOM (form-login, nation-grid, modals, m-*, gsi-*, toast…).

   fit() in login2.js still writes an inline transform on #stage — the block
   marked NEUTRALIZE below cancels it with !important (author !important beats
   inline styles), so the gate is normal responsive DOM.

   Revert: index_gate4_backup_20260810.php is a byte copy of the previous
   gate; ?gate4=1 serves it live for comparison.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --g5-gold:      #e8c05e;
  --g5-gold-hi:   #ffe9a8;
  --g5-gold-deep: #8a6a2a;
  --g5-ink:       #f3e9cf;
  --g5-ink-dim:   #bfae8c;
  --g5-night:     #0b0e10;
  --g5-pane:      rgba(12,14,15,.55);
  --g5-line:      rgba(232,192,94,.42);
  --g5-red:       #a03a2e;
  --g5-ease:      cubic-bezier(.22,1,.36,1);
  --g5-frame:     url("/assets/login5/panel-frame.png");
  --g5-btn:       url("/client/assets/royal/btn_cta.png");
  --g5-btn-red:   url("/client/assets/royal/btn_cta_red.png");
  --g5-btn-fr:    url("/client/assets/royal/btn_cta_fr.png");
}

html, body{ margin:0; padding:0; background:var(--g5-night); }
body{ font-family:'Inter',system-ui,sans-serif; color:var(--g5-ink); }

/* ── NEUTRALIZE the legacy 1930×815 stage machinery ─────────────────────── */
#vp{
  position:relative!important; inset:auto!important;
  width:100%!important; height:auto!important; min-height:100vh;
  display:block!important; overflow:visible!important;
  background:none!important;
}
#stage{
  position:relative!important; inset:auto!important;
  width:100%!important; height:auto!important; min-height:100vh;
  transform:none!important; margin:0!important;
  background:none!important; box-shadow:none!important; filter:none!important;
  isolation:auto!important;
  display:flex; flex-direction:column;
}
#stage::before, #stage::after{ content:none!important; }

/* ══ THE LIVING KINGDOM — canvas + poster fallback ══════════════════════ */
#bg3d, #g5-poster{
  position:fixed; inset:0; width:100vw; height:100vh; z-index:0;
  pointer-events:none;
}
#bg3d{ display:block; }
/* A REAL FRAME OF THE SCENE, not a gradient approximation of it: rendered out
   of gate3d.js itself (headless, d3d11) so the poster and the live 3D are the
   same kingdom. It is what phones get (they never load the FBX pack), what
   shows while three.js boots, and the fallback if the CDN or WebGL fails.
   The gradient stays underneath as the last resort. */
#g5-poster{
  background:
    image-set(url("/assets/login5/gate-poster.jpg") 1x) 50% 42% / cover no-repeat,
    linear-gradient(180deg,#3e6e9e 0%,#769cc4 34%,#8aa87e 60%,#4c5c40 100%);
  transition:opacity 1.2s var(--g5-ease);
}
@media (max-aspect-ratio:1/1){
  #g5-poster{
    background:
      image-set(url("/assets/login5/gate-poster-portrait.jpg") 1x) 50% 46% / cover no-repeat,
      linear-gradient(180deg,#3e6e9e 0%,#769cc4 34%,#8aa87e 60%,#4c5c40 100%);
  }
}
/* the module adds .g3d-live on its first rendered frame → poster fades off */
html.g3d-live #g5-poster{ opacity:0; }
/* cinematic grade over the scene — never over the UI */
#g5-grade{
  position:fixed; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(180deg, rgba(4,6,8,.52) 0%, transparent 18%, transparent 62%, rgba(3,4,5,.62) 100%),
    radial-gradient(ellipse at 50% 46%, transparent 46%, rgba(2,3,4,.42) 100%);
}

/* everything interactive floats above the scene */
#g5-top, #g5-hero, #g5-panels, #g5-feats{ position:relative; z-index:3; }

/* ══ TOP BAR ════════════════════════════════════════════════════════════ */
#g5-top{
  display:flex; align-items:center; gap:26px;
  padding:14px 30px 0;
}
#g5-crest{
  display:flex; align-items:center; gap:12px; text-decoration:none;
}
#g5-crest .g5-shield{
  width:44px; height:44px; border-radius:10px;
  background:linear-gradient(160deg,#2a2015,#0e0b07);
  border:1px solid var(--g5-line);
  box-shadow:0 4px 14px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,230,160,.25);
  display:flex; align-items:center; justify-content:center;
  font-size:24px;
}
#g5-crest .g5-wordmark{
  font-family:'Cinzel',serif; font-weight:700; font-size:17px; letter-spacing:2.5px;
  background:linear-gradient(180deg,var(--g5-gold-hi),var(--g5-gold) 55%,var(--g5-gold-deep));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  text-shadow:0 2px 8px rgba(0,0,0,.65);
  white-space:nowrap;
}
#g5-nav{ display:flex; gap:6px; margin-left:8px; }
#g5-nav .nhot{
  all:unset; cursor:pointer; padding:9px 14px; border-radius:9px;
  font:600 13px/1 'Inter',sans-serif; letter-spacing:.4px; color:var(--g5-ink-dim);
  transition:color .15s, background .15s;
}
#g5-nav .nhot:hover{ color:var(--g5-gold-hi); background:rgba(232,192,94,.08); }
#g5-nav .nhot:focus-visible{ outline:2px solid var(--g5-gold); outline-offset:2px; }
#g5-top .g5-spacer{ flex:1; }
/* the language switcher mounts into #g5-lang-slot (aon-lang.js) */
#g5-lang-slot{ min-width:120px; min-height:38px; position:relative; }

/* ══ HERO ═══════════════════════════════════════════════════════════════ */
#g5-hero{
  text-align:center; margin:clamp(10px,4.5vh,46px) 0 clamp(8px,2.6vh,26px);
  pointer-events:none;
}
#g5-hero .g5-title{
  font-family:'Cinzel',serif; font-weight:700;
  font-size:clamp(34px,5.6vw,74px); line-height:1.02; letter-spacing:6px;
  margin:0;
  background:linear-gradient(180deg,#fff3cf 0%,var(--g5-gold-hi) 28%,var(--g5-gold) 58%,#a77f33 82%,#6d4f1c 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:
    drop-shadow(0 2px 0 rgba(60,40,8,.9))
    drop-shadow(0 6px 18px rgba(0,0,0,.72))
    drop-shadow(0 0 34px rgba(232,192,94,.28));
}
#g5-hero .g5-tag{
  margin:12px 0 0; display:inline-flex; align-items:center; gap:14px;
  font:600 clamp(11px,1.15vw,15px)/1 'Cinzel',serif; letter-spacing:6px; color:var(--g5-ink);
  text-shadow:0 2px 8px rgba(0,0,0,.85);
}
#g5-hero .g5-tag i{
  width:clamp(40px,6vw,110px); height:1px;
  background:linear-gradient(90deg,transparent,var(--g5-gold));
}
#g5-hero .g5-tag i:last-child{ transform:scaleX(-1); }

/* ══ THE TWO PANELS ═════════════════════════════════════════════════════ */
#g5-panels{
  /* NOT flex:1 — inside the column #stage that would make the row fill the
     whole leftover viewport and `stretch` would then blow both panels out to
     full height with dead space inside. Content height + stretch equalises the
     two panels to the TALLER one, which is the intended composition. */
  flex:0 0 auto; display:flex; justify-content:center; align-items:stretch;
  gap:clamp(22px,4vw,72px);
  padding:0 26px; margin:0 0 clamp(10px,2.2vh,24px);
}
/* the gate floats in the middle of the scene rather than sitting on the fold */
#g5-hero{ margin-top:auto; }
#g5-feats{ margin-top:auto; }
.g5-panel{
  width:min(430px,44vw);
  display:flex; flex-direction:column;
  /* THE GAME'S OWN painted window frame, re-cut as a true 9-slice sheet
     (tools/… → assets/login5/panel-frame.png, 154², 54 KB): the source art is
     1536×1024 with a 66px transparent margin, and stretching that margin into
     the border ring left a faint 10px halo box around every panel — measured,
     and it survived with the 3D off. The sheet is cropped to the opaque bbox,
     the never-drawn interior is punched out and the flat edge runs collapsed,
     so the corners keep full detail at 3% of the weight. */
  border:26px solid transparent;
  border-image:var(--g5-frame) 65 / 26px / 0 stretch;
  background:
    radial-gradient(ellipse at 50% 0%, rgba(70,52,20,.32), transparent 58%),
    linear-gradient(180deg, rgba(16,13,9,.93), rgba(8,7,5,.95));
  background-clip:padding-box;
  box-shadow:0 30px 70px rgba(0,0,0,.72);
  padding:6px 14px 16px;
  min-height:0;
}
.g5-panel h2{
  margin:2px 0 1px; text-align:center;
  font-family:'Cinzel',serif; font-weight:700; font-size:22px; letter-spacing:4px;
  background:linear-gradient(180deg,var(--g5-gold-hi),var(--g5-gold) 60%,var(--g5-gold-deep));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  text-shadow:0 2px 6px rgba(0,0,0,.6);
}
.g5-panel .g5-sub{
  margin:0 0 12px; text-align:center;
  font:600 10px/1.4 'Inter',sans-serif; letter-spacing:2.6px; color:var(--g5-ink-dim);
}
.g5-rule{
  height:10px; margin:2px 26px 10px; border:0;
  background:
    radial-gradient(circle at 50% 50%, var(--g5-gold) 0 2px, transparent 3px),
    linear-gradient(90deg, transparent, rgba(232,192,94,.55) 18%, rgba(232,192,94,.55) 82%, transparent);
  background-size:auto, 100% 1px; background-position:center, center;
  background-repeat:no-repeat;
}

/* ── fields ── */
.g5-field{
  display:flex; align-items:center; gap:10px;
  margin:0 6px 12px; padding:0 13px; height:46px;
  background:linear-gradient(180deg, rgba(4,3,2,.82), rgba(14,11,7,.82));
  border:1px solid rgba(232,192,94,.25); border-radius:9px;
  box-shadow:inset 0 2px 8px rgba(0,0,0,.66), inset 0 -1px 0 rgba(255,225,150,.06);
  transition:border-color .16s, box-shadow .16s;
  position:relative;
}
.g5-field:focus-within{
  border-color:var(--g5-gold);
  box-shadow:inset 0 2px 8px rgba(0,0,0,.6), 0 0 0 1px rgba(232,192,94,.35), 0 0 18px rgba(232,192,94,.22);
}
.g5-field .gi{ font-size:15px; opacity:.8; flex:0 0 auto; }
.g5-field input{
  all:unset; flex:1; min-width:0; height:100%;
  font:500 14.5px/1 'Inter',sans-serif; color:var(--g5-ink);
}
.g5-field input::placeholder{ color:rgba(191,174,140,.55); }
.g5-field .eyehot{
  all:unset; cursor:pointer; flex:0 0 auto; font-size:15px; opacity:.62;
  padding:6px; border-radius:6px;
}
.g5-field .eyehot:hover{ opacity:1; }
.g5-field .eyehot:focus-visible{ outline:2px solid var(--g5-gold); }

.g5-row{
  display:flex; align-items:center; justify-content:space-between;
  margin:0 8px 13px; font:500 12.5px/1 'Inter',sans-serif; color:var(--g5-ink-dim);
}
.g5-check{ display:flex; align-items:center; gap:8px; cursor:pointer; user-select:none; }
.g5-check input{ position:absolute; opacity:0; width:0; height:0; }
.g5-check i{
  width:17px; height:17px; border-radius:4px; font-style:normal;
  background:linear-gradient(180deg,#050403,#151006);
  border:1px solid rgba(232,192,94,.4);
  box-shadow:inset 0 1px 4px rgba(0,0,0,.7);
  display:flex; align-items:center; justify-content:center;
  font-size:12px; color:var(--g5-gold-hi); line-height:1;
}
.g5-check i::before{ content:'✓'; opacity:0; transform:scale(.5); transition:.14s var(--g5-ease); }
.g5-check input:checked + i::before{ opacity:1; transform:scale(1); }
.g5-check input:focus-visible + i{ outline:2px solid var(--g5-gold); outline-offset:2px; }
.g5-link{
  all:unset; cursor:pointer; color:var(--g5-gold); font-weight:600;
  border-bottom:1px solid transparent; transition:.14s;
}
.g5-link:hover{ color:var(--g5-gold-hi); border-bottom-color:var(--g5-gold-hi); }
.g5-link:focus-visible{ outline:2px solid var(--g5-gold); outline-offset:2px; }

/* ── the ROYAL CTA — the game's own painted button plate ── */
.g5-cta{
  all:unset; cursor:pointer; display:block; box-sizing:border-box;
  width:calc(100% - 12px);
  margin:2px 6px 0; height:56px; text-align:center;
  /* the painted plate fills the WHOLE box (border-box origin) and the ornate
     pewter frame is 9-sliced on top of the edges — two real pieces of the
     game's own button art, not a CSS approximation of one */
  background:var(--g5-btn) center / 100% 100% no-repeat;
  background-origin:border-box; background-clip:border-box;
  border:15px solid transparent;
  border-image:var(--g5-btn-fr) 30 / 15px stretch;
  font-family:'Cinzel',serif; font-weight:700; font-size:16px; letter-spacing:3px;
  color:#f7e7bd; text-shadow:0 1px 0 rgba(0,0,0,.9), 0 2px 6px rgba(0,0,0,.8);
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.55));
  transition:filter .15s, transform .12s;
  line-height:24px;
}
.g5-cta:hover{ filter:drop-shadow(0 8px 18px rgba(0,0,0,.6)) brightness(1.18); }
.g5-cta:active{ transform:translateY(2px); filter:brightness(.94); }
.g5-cta:focus-visible{ outline:2px solid var(--g5-gold-hi); outline-offset:3px; }
.g5-cta[disabled], .g5-cta.is-busy{ cursor:default; filter:saturate(.4) brightness(.7); }
.g5-cta.red{ background-image:var(--g5-btn-red); }

.omsg, .mmsg{
  margin:10px 8px 0; min-height:18px; text-align:center;
  font:600 12.5px/1.4 'Inter',sans-serif; color:#ff9e89;
}
.omsg.ok, .mmsg.ok{ color:#9fe8b0; }

/* ── socials — pushed to the panel's foot so equal-height panels read as
   deliberate composition rather than a gap under the login form ── */
.g5-socrow{ display:flex; align-items:center; gap:12px; justify-content:center; margin:auto 0 4px; }
.g5-socrow .g5-or{
  font:700 9.5px/1 'Inter',sans-serif; letter-spacing:2px; color:var(--g5-ink-dim);
}
.g5-socrow .sochot{
  all:unset; cursor:pointer; width:42px; height:42px; border-radius:50%;
  background:linear-gradient(180deg,#1d1812,#0b0906);
  border:1px solid rgba(232,192,94,.35);
  box-shadow:0 4px 12px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,230,160,.14);
  display:flex; align-items:center; justify-content:center; font-size:17px;
  transition:.15s;
}
.g5-socrow .sochot:hover{ border-color:var(--g5-gold); box-shadow:0 4px 16px rgba(0,0,0,.6), 0 0 14px rgba(232,192,94,.3); }
.g5-socrow .sochot:focus-visible{ outline:2px solid var(--g5-gold); outline-offset:2px; }
#gsi-desktop{ display:flex; justify-content:center; margin-top:10px; }

/* ══ NATION GALLERY (register panel) ════════════════════════════════════ */
#nation-grid{
  flex:1; min-height:200px; max-height:328px; overflow-y:auto;
  margin:0 2px; padding:2px 8px 6px;
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:9px;
  align-content:start;
  scrollbar-width:thin; scrollbar-color:rgba(232,192,94,.55) rgba(0,0,0,.4);
  -webkit-mask-image:linear-gradient(180deg,#000 0,#000 calc(100% - 26px),transparent 100%);
          mask-image:linear-gradient(180deg,#000 0,#000 calc(100% - 26px),transparent 100%);
}
#nation-grid::-webkit-scrollbar{ width:9px; }
#nation-grid::-webkit-scrollbar-track{ background:rgba(0,0,0,.42); border-radius:8px; }
#nation-grid::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,var(--g5-gold),var(--g5-gold-deep));
  border-radius:8px; border:2px solid rgba(0,0,0,.5);
}
.ng-region{
  grid-column:1/-1; margin:6px 2px 0;
  font:700 10px/1 'Cinzel',serif; letter-spacing:2.6px; color:var(--g5-gold);
  display:flex; align-items:center; gap:10px;
}
.ng-region::after{ content:''; flex:1; height:1px; background:linear-gradient(90deg,rgba(232,192,94,.5),transparent); }
.ng-tile{
  all:unset; cursor:pointer; box-sizing:border-box; position:relative;
  display:flex; flex-direction:column; align-items:center; gap:5px;
  padding:8px 6px 7px; border-radius:10px; text-align:center;
  background:linear-gradient(180deg, rgba(26,20,12,.92), rgba(10,8,5,.94));
  border:1px solid rgba(232,192,94,.22);
  box-shadow:0 3px 10px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,230,160,.07);
  transition:transform .14s var(--g5-ease), border-color .14s, box-shadow .14s;
}
.ng-tile:hover{
  transform:translateY(-2px);
  border-color:var(--g5-gold);
  box-shadow:0 8px 20px rgba(0,0,0,.6), 0 0 16px rgba(232,192,94,.28);
}
.ng-tile:focus-visible{ outline:2px solid var(--g5-gold-hi); outline-offset:2px; }
.ng-tile.sel{ border-color:var(--g5-gold-hi); box-shadow:0 0 0 1px var(--g5-gold-hi), 0 0 22px rgba(232,192,94,.5); }
.ng-tile[disabled]{ cursor:default; opacity:.55; }
.ng-flag{
  position:relative; width:58px; height:38px; border-radius:5px; overflow:hidden;
  border:1px solid rgba(0,0,0,.65);
  box-shadow:0 2px 6px rgba(0,0,0,.55), 0 0 0 1px rgba(232,192,94,.28);
  background:#0a0805;
}
.ng-flag img{ width:100%; height:100%; object-fit:cover; display:block; }
.ng-flag-fallback{
  position:absolute; inset:0; display:none; align-items:center; justify-content:center; font-size:22px;
}
.ng-flag.is-fallback img{ display:none; }
.ng-flag.is-fallback .ng-flag-fallback{ display:flex; }
.ng-tile .nname{
  font:700 11px/1.15 'Inter',sans-serif; letter-spacing:.3px; color:var(--g5-ink);
  max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.ng-tile .nperk{
  font:600 9px/1.2 'Inter',sans-serif; color:var(--g5-gold);
  max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.ng-tos{
  margin:10px 10px 0; text-align:center;
  font:500 10px/1.5 'Inter',sans-serif; color:rgba(191,174,140,.6);
}

#nation-grid.locked, #m-nation-grid.locked{ opacity:.55; pointer-events:none; }

/* ══ FEATURE STRIP ══════════════════════════════════════════════════════ */
#g5-feats{
  display:flex; justify-content:center; gap:12px; flex-wrap:wrap;
  padding:0 26px 26px;
}
.fcard{
  all:unset; cursor:pointer; box-sizing:border-box;
  display:flex; align-items:center; gap:10px;
  padding:11px 16px; border-radius:11px;
  background:linear-gradient(180deg, rgba(16,13,9,.78), rgba(7,6,4,.85));
  border:1px solid rgba(232,192,94,.26);
  box-shadow:0 6px 18px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,230,160,.09);
  -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
  font:600 12.5px/1.2 'Inter',sans-serif; color:var(--g5-ink);
  transition:transform .15s var(--g5-ease), border-color .15s, box-shadow .15s;
}
.fcard b{ font-size:17px; font-weight:400; }
.fcard:hover{
  transform:translateY(-2px); border-color:var(--g5-gold);
  box-shadow:0 10px 24px rgba(0,0,0,.6), 0 0 16px rgba(232,192,94,.25);
}
.fcard:focus-visible{ outline:2px solid var(--g5-gold); outline-offset:2px; }
#feat-glow{ display:none; }

/* ══ MODALS (forgot / reset / claim) — repainted on the same art ════════ */
.modal{
  position:fixed; inset:0; z-index:1000; display:none;
  align-items:center; justify-content:center;
  background:radial-gradient(ellipse at 50% 40%, rgba(8,6,3,.72), rgba(2,1,1,.9));
  -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
}
.modal.open{ display:flex; }
.mbox{
  position:relative; width:min(440px,92vw); box-sizing:border-box;
  border:26px solid transparent;
  border-image:var(--g5-frame) 65 / 26px / 0 stretch;
  background:linear-gradient(180deg, rgba(16,13,9,.97), rgba(8,7,5,.98));
  background-clip:padding-box;
  box-shadow:0 40px 90px rgba(0,0,0,.85);
  padding:10px 18px 20px; text-align:center;
  animation:g5rise .28s var(--g5-ease);
}
@keyframes g5rise{ from{ transform:translateY(16px) scale(.97); opacity:0; } }
@media (prefers-reduced-motion:reduce){ .mbox{ animation:none; } }
.mbox h3{
  margin:4px 0 8px; font-family:'Cinzel',serif; font-weight:700; font-size:19px; letter-spacing:3px;
  background:linear-gradient(180deg,var(--g5-gold-hi),var(--g5-gold) 60%,var(--g5-gold-deep));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.mbox p{ margin:0 0 14px; font:500 13px/1.55 'Inter',sans-serif; color:var(--g5-ink-dim); }
.mbox input{
  all:unset; display:block; box-sizing:border-box; width:100%; height:46px;
  margin:0 0 12px; padding:0 14px; border-radius:9px; text-align:left;
  background:linear-gradient(180deg, rgba(4,3,2,.85), rgba(14,11,7,.85));
  border:1px solid rgba(232,192,94,.25);
  box-shadow:inset 0 2px 8px rgba(0,0,0,.66);
  font:500 14.5px/1 'Inter',sans-serif; color:var(--g5-ink);
}
.mbox input:focus{ border-color:var(--g5-gold); box-shadow:inset 0 2px 8px rgba(0,0,0,.6), 0 0 14px rgba(232,192,94,.25); }
.mbox input::placeholder{ color:rgba(191,174,140,.55); }
.mbox .mbtn{
  all:unset; cursor:pointer; display:block; box-sizing:border-box; width:100%;
  height:54px; text-align:center;
  background:var(--g5-btn) center / 100% 100% no-repeat;
  background-origin:border-box; background-clip:border-box;
  border:15px solid transparent;
  border-image:var(--g5-btn-fr) 30 / 15px stretch;
  font-family:'Cinzel',serif; font-weight:700; font-size:14px; letter-spacing:2.4px;
  color:#f7e7bd; text-shadow:0 2px 4px rgba(0,0,0,.8); line-height:20px;
  transition:filter .15s, transform .12s;
}
.mbox .mbtn:hover{ filter:brightness(1.16); }
.mbox .mbtn:active{ transform:translateY(2px); }
.mbox .mbtn.red{ background-image:var(--g5-btn-red); }
.mbox .mx{
  all:unset; cursor:pointer; position:absolute; top:-16px; right:-12px;
  width:34px; height:34px; border-radius:50%;
  background:linear-gradient(180deg,#241c11,#0c0906);
  border:1px solid var(--g5-line); color:var(--g5-ink-dim);
  display:flex; align-items:center; justify-content:center; font-size:14px;
  box-shadow:0 4px 10px rgba(0,0,0,.6);
}
.mbox .mx:hover{ color:var(--g5-gold-hi); border-color:var(--g5-gold); }
.mbox.claim .claim-badge{ font-size:38px; margin-top:2px; filter:drop-shadow(0 4px 10px rgba(0,0,0,.6)); }
.mbox.claim .claim-arrow{
  margin:2px 0 12px; font:800 12px/1 'Inter',sans-serif; letter-spacing:1px; color:var(--g5-gold-hi);
  animation:g5bob 1.4s ease-in-out infinite;
}
@keyframes g5bob{ 0%,100%{ transform:translateY(0);} 50%{ transform:translateY(4px);} }
@media (prefers-reduced-motion:reduce){ .mbox.claim .claim-arrow{ animation:none; } }
.claim-skip{
  all:unset; cursor:pointer; margin-top:12px;
  font:600 12px/1 'Inter',sans-serif; color:var(--g5-ink-dim); border-bottom:1px solid transparent;
}
.claim-skip:hover{ color:var(--g5-ink); border-bottom-color:var(--g5-ink-dim); }

/* toast */
#toast{
  position:fixed; left:50%; bottom:34px; transform:translateX(-50%) translateY(20px);
  z-index:1200; max-width:min(520px,90vw); box-sizing:border-box;
  padding:13px 22px; border-radius:12px; opacity:0; pointer-events:none;
  background:linear-gradient(180deg, rgba(22,17,10,.97), rgba(10,8,5,.97));
  border:1px solid var(--g5-line);
  box-shadow:0 14px 40px rgba(0,0,0,.7), 0 0 18px rgba(232,192,94,.2);
  font:600 13.5px/1.45 'Inter',sans-serif; color:var(--g5-ink); text-align:center;
  transition:.25s var(--g5-ease);
}
#toast.show{ opacity:1; transform:translateX(-50%) translateY(0); }

/* ══ RESPONSIVE ═════════════════════════════════════════════════════════ */
@media (max-width:1180px){
  .g5-panel{ width:min(400px,46vw); }
  #g5-nav .nhot{ padding:9px 9px; }
}
@media (max-width:1020px){
  #g5-nav{ display:none; }
}
/* stacked panels — tablet portrait band between desktop and the #mob column */
@media (max-width:940px) and (min-width:869px){
  #g5-panels{ flex-direction:column; align-items:center; gap:26px; }
  .g5-panel{ width:min(460px,92vw); }
}
@media (max-height:780px){
  #g5-hero{ margin-top:8px; }
  #g5-hero .g5-title{ font-size:clamp(30px,4.6vh,52px); }
  #nation-grid{ max-height:min(300px, 34vh); }
  .g5-panel{ padding-bottom:10px; }
  #g5-feats{ display:none; }
}

/* ══ MOBILE COLUMN (#mob — same wiring, regate art) ═════════════════════ */
#mob{ display:none; }
html.mob #vp{ display:none!important; }
html.mob #mob{ display:block; position:relative; z-index:2; }
html.mob #bg3d{ display:none; }
html.mob #g5-poster{ opacity:1!important; }
html.mob #g5-grade{
  background:linear-gradient(180deg, rgba(4,6,8,.32) 0%, rgba(4,5,6,.55) 46%, rgba(2,3,4,.86) 100%);
}
#mob{ padding:14px 14px 96px; }
#mob .bgm{ display:none; }
#mob .m-hero{ text-align:center; margin:44px 0 18px; }
#mob .m-hero img{ display:none; }
#mob .m-hero::before{
  content:'AGE OF NATIONS';
  display:block; font-family:'Cinzel',serif; font-weight:700;
  font-size:clamp(30px,9vw,42px); line-height:1.05; letter-spacing:4px;
  background:linear-gradient(180deg,#fff3cf,var(--g5-gold-hi) 30%,var(--g5-gold) 62%,#8a6a2a);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 2px 0 rgba(60,40,8,.9)) drop-shadow(0 5px 14px rgba(0,0,0,.75));
}
#mob .m-hero::after{
  content:'BUILD · CONQUER · RULE';
  display:block; margin-top:8px;
  font:600 11px/1 'Cinzel',serif; letter-spacing:5px; color:var(--g5-ink);
  text-shadow:0 2px 6px rgba(0,0,0,.9);
}
.mcard{
  box-sizing:border-box; margin:0 auto 18px; width:min(520px,100%);
  border:26px solid transparent;
  border-image:var(--g5-frame) 65 / 26px / 0 stretch;
  background:linear-gradient(180deg, rgba(16,13,9,.94), rgba(8,7,5,.96));
  background-clip:padding-box;
  box-shadow:0 22px 54px rgba(0,0,0,.7);
  padding:6px 10px 14px;
}
.mcard h2{
  margin:2px 0 2px; text-align:center;
  font-family:'Cinzel',serif; font-weight:700; font-size:20px; letter-spacing:3.6px;
  background:linear-gradient(180deg,var(--g5-gold-hi),var(--g5-gold) 60%,var(--g5-gold-deep));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.mcard .msub{
  margin:0 0 12px; text-align:center;
  font:600 9.5px/1.4 'Inter',sans-serif; letter-spacing:2.2px; color:var(--g5-ink-dim);
}
.mf{
  display:flex; align-items:center; gap:10px;
  margin:0 2px 11px; padding:0 12px; height:48px;
  background:linear-gradient(180deg, rgba(4,3,2,.82), rgba(14,11,7,.82));
  border:1px solid rgba(232,192,94,.25); border-radius:9px;
  box-shadow:inset 0 2px 8px rgba(0,0,0,.66);
  position:relative;
}
.mf:focus-within{ border-color:var(--g5-gold); box-shadow:inset 0 2px 8px rgba(0,0,0,.6), 0 0 14px rgba(232,192,94,.22); }
.mf .mi{ font-size:15px; opacity:.8; }
.mf input{ all:unset; flex:1; min-width:0; font:500 16px/1 'Inter',sans-serif; color:var(--g5-ink); }
.mf input::placeholder{ color:rgba(191,174,140,.55); }
.mf .meye{ all:unset; cursor:pointer; font-size:15px; opacity:.62; padding:6px; }
.mrow{
  display:flex; align-items:center; justify-content:space-between;
  margin:0 4px 12px; font:500 12.5px/1 'Inter',sans-serif; color:var(--g5-ink-dim);
}
.mchk{ display:flex; align-items:center; gap:8px; cursor:pointer; }
.mchk input{ position:absolute; opacity:0; width:0; height:0; }
.mchk i{
  width:18px; height:18px; border-radius:4px; font-style:normal;
  background:linear-gradient(180deg,#050403,#151006);
  border:1px solid rgba(232,192,94,.4);
  display:flex; align-items:center; justify-content:center;
  font-size:12px; color:var(--g5-gold-hi);
}
.mchk i::before{ content:'✓'; opacity:0; }
.mchk input:checked + i::before{ opacity:1; }
.mlink{ all:unset; cursor:pointer; color:var(--g5-gold); font-weight:600; }
.mbtn{
  all:unset; cursor:pointer; display:block; box-sizing:border-box; width:100%;
  height:56px; text-align:center;
  background:var(--g5-btn) center / 100% 100% no-repeat;
  background-origin:border-box; background-clip:border-box;
  border:15px solid transparent;
  border-image:var(--g5-btn-fr) 30 / 15px stretch;
  font-family:'Cinzel',serif; font-weight:700; font-size:15px; letter-spacing:2.6px;
  color:#f7e7bd; text-shadow:0 2px 4px rgba(0,0,0,.8); line-height:20px;
}
.mbtn:active{ transform:translateY(2px); }
.mbtn.red{ background-image:var(--g5-btn-red); }
#m-nation-grid{
  max-height:340px; overflow-y:auto; padding:2px 4px 6px;
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:9px; align-content:start;
  scrollbar-width:thin; scrollbar-color:rgba(232,192,94,.55) rgba(0,0,0,.4);
}
.m-ngtos{
  margin:10px 6px 0; text-align:center;
  font:500 10px/1.5 'Inter',sans-serif; color:rgba(191,174,140,.6);
}
.m-feats{ width:min(520px,100%); margin:4px auto 0; display:flex; flex-direction:column; gap:9px; }
.mft{
  padding:11px 14px; border-radius:11px;
  background:linear-gradient(180deg, rgba(16,13,9,.8), rgba(7,6,4,.86));
  border:1px solid rgba(232,192,94,.24); border-left:3px solid var(--g5-gold);
  box-shadow:0 5px 14px rgba(0,0,0,.5);
}
.mft b{ display:block; font:700 13.5px/1.3 'Inter',sans-serif; color:var(--g5-ink); }
.mft span{ font:500 12px/1.45 'Inter',sans-serif; color:var(--g5-ink-dim); }
.m-copy{ margin:20px 0 0; text-align:center; font:500 11px/1 'Inter',sans-serif; color:rgba(191,174,140,.5); }
#gsi-mobile-wrap{ margin-top:4px; }

/* ── SEO footer stays below everything, over solid ground ── */
#seo-footer{ position:relative; z-index:3; }

/* ══ gate5 · parts/02-atmosphere.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PASS 02 — ATMOSPHERE            assets/login5/parts/02-atmosphere.css
   ───────────────────────────────────────────────────────────────────────────
   THE COMPOSITING PASS. Everything between the live 3D kingdom and the UI.
   Pass 01 owns the geometry and the lighting; this file is the colourist:
   grade → haze → shafts → vignette → embers → grain, in that order, which is
   the order a real plate is assembled in.

   WHY THE OLD IDS.  index.php is off limits and already carries five decorative
   full-screen nodes from the two earlier skins (#g5-grade, #g6-rays,
   #g6-vignette, #g6-grain, #g7-fog) plus the #g6-fx canvas. Adding six MORE
   full-screen layers on top of those would double the compositor's work for no
   picture. So this pass REPURPOSES them — one job each, named in the block
   comments — and injects only what has no home: the ember field.

   WHY EVERY SELECTOR STARTS `html.g5-atm`.  login5-imperial.css and
   login5-aoe.css are linked AFTER gate5.css.php in index.php, and both style
   these same ids with `!important`. `html.g5-atm #x` is (1,1,1) against their
   (1,0,0), so this pass wins cleanly — and `.g5-atm` is only set by
   02-atmosphere.js, so if the script is skipped (?nogate5=02) or throws, the
   page falls back to the previous look instead of to nothing.

   COST.  Six full-screen layers, THREE of them blended (soft-light, screen,
   screen) and none of them repainted: every animation here is transform /
   opacity only, so the compositor re-blends but the rasteriser never runs.
   The embers are 22 elements of ≤16px, each one its own tiny composited
   layer — cheaper per frame than one line of the canvas particle system this
   replaces, which re-uploaded a 1920×1080 texture 60 times a second.
   Nothing here runs on mobile, and nothing runs while the tab is hidden.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* LIGHT, not paint — channel triplets so one hue carries many alphas.
     Each is anchored to a tokens.css colour; the atmosphere may not invent
     hues, only intensities of the ones the empire already owns. */
  --g5-atm-sun:   255,233,168;   /* --g5-gold-2  · the key                   */
  --g5-atm-fire:  255,199,116;   /* --g5-gold-3 lifted · low-sun spill       */
  --g5-atm-haze:  216,206,188;   /* warm dust hanging at the horizon         */
  --g5-atm-cold:   46, 92,112;   /* the shade side. Teal — never blue-grey.  */
  --g5-atm-deep:    5,  8, 12;   /* --g5-night · where the frame goes out    */
  --g5-atm-soot:   14, 11,  9;   /* warm black for the ground crush          */
  --g5-atm-gold:  232,192, 94;   /* --g5-gold-3 · the one line of the mount  */
  --g5-atm-spark: 255,244,214;   /* --g5-gold-1 · the white-hot core of a spark */
  --g5-atm-coal:  255,148, 56;   /* the cooling body of one — the only orange */
}

/* ── shared geometry for every atmosphere layer ─────────────────────────── */
html.g5-atm #g5-grade,
html.g5-atm #g6-grain,
html.g5-atm #g7-fog,
html.g5-atm #g6-rays,
html.g5-atm #g6-vignette,
html.g5-atm #g5-atm{
  position:fixed; pointer-events:none;      /* NEVER eat a click on the form */
}

/* ═══════════════════════════════════════════════════════════════════════════
   1 · THE GRADE — #g5-grade, plain alpha, painted once.
   Shape only: where the frame is dark and where the light gets in. The tone
   comes next, in its own blended layer, because alpha compositing can tint
   toward a colour but can never lift a highlight.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-atm #g5-grade{
  inset:0; z-index:var(--g5-z-grade);
  background:
    /* the sun's own spill, upper left — gate3d.js puts the key at
       (-55,130,75) with the camera at (95,45,130), so the light comes over
       the viewer's left shoulder and this is where it lands. */
    radial-gradient(ellipse 48% 36% at 9% -8%,
      rgba(var(--g5-atm-fire),.22), rgba(var(--g5-atm-fire),.06) 46%, transparent 74%),
    /* a warm bounce off the field, low and centre — stops the bottom third
       reading as a black bar under the panels */
    radial-gradient(ellipse 60% 24% at 46% 86%,
      rgba(var(--g5-atm-fire),.07), transparent 72%),
    /* THE WARMING FILTER, sat on the horizon rather than over the whole sky:
       the photographer's 85 filter, applied where the light actually is. */
    linear-gradient(180deg,
      transparent 20%,
      rgba(var(--g5-atm-fire),.09) 38%,
      rgba(var(--g5-atm-fire),.13) 46%,
      rgba(var(--g5-atm-fire),.06) 56%,
      transparent 68%),
    /* THE SHAPE, and the single most important gradient in this pass.
       The sky has to go DEEP. A light shaft is `screen`, and screen over a
       bright backdrop is a no-op — the reason god-rays looked like nothing
       until this ramp existed. Dark sky at the top, one clear band of air at
       the horizon where the kingdom and the light both are, then a long crush
       into the footer. That is also the composition: the two panels sit in
       the lit band with darkness above and below them. */
    linear-gradient(180deg,
      rgba(var(--g5-atm-deep),.92)  0%,
      rgba(var(--g5-atm-deep),.80)  8%,
      rgba(var(--g5-atm-deep),.66) 16%,
      rgba(var(--g5-atm-deep),.52) 24%,
      rgba(var(--g5-atm-deep),.36) 31%,
      rgba(var(--g5-atm-deep),.18) 38%,
      transparent                  46%,
      transparent                  54%,
      rgba(var(--g5-atm-soot),.26) 64%,
      rgba(var(--g5-atm-soot),.60) 79%,
      rgba(var(--g5-atm-deep),.88) 92%,
      rgba(var(--g5-atm-deep),.96) 100%) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   2 · THE TONE — #g6-grain, `soft-light`. THE colour grade.
   Warm on the key side, teal in the shade: the split-tone every game trailer
   in this genre is graded with. soft-light is the correct operator — it tints
   and rolls off instead of painting over, so the castle's own stone keeps its
   value and only its HUE moves.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-atm #g6-grain{
  inset:0; z-index:var(--g5-z-grade);
  opacity:.88;
  mix-blend-mode:soft-light;
  animation:none;                 /* imperial jittered this 3×/s — see grain */
  background:
    /* the key itself, hot at the source */
    radial-gradient(ellipse 74% 54% at 6% -8%,
      rgba(var(--g5-atm-sun),.66), rgba(var(--g5-atm-fire),.28) 44%, transparent 82%),
    /* THE SPLIT. Warm and cold have to separate ALONG THE LIGHT AXIS, not in
       concentric rings — 122deg is the sun's own direction through frame, so
       everything the key touches goes gold and everything it misses goes teal.
       This one gradient is most of the difference between "darkened" and
       "graded". */
    linear-gradient(122deg,
      rgba(var(--g5-atm-fire),.26)  0%,
      rgba(var(--g5-atm-fire),.10) 26%,
      transparent 46%,
      transparent 56%,
      rgba(var(--g5-atm-cold),.26) 80%,
      rgba(var(--g5-atm-cold),.40) 100%),
    /* and the ground, which never sees the key at all */
    linear-gradient(180deg,
      transparent 46%,
      rgba(var(--g5-atm-cold),.30) 76%,
      rgba(var(--g5-atm-cold),.48) 100%);
}

/* ═══════════════════════════════════════════════════════════════════════════
   3 · THE HAZE — #g7-fog, `screen`. Depth.
   A band of lit dust sitting exactly on the horizon (~42%), so the far hills
   separate from the near field instead of being pasted on the same plane.
   fog.png is REUSED — it was already painted for the previous skin — but it is
   masked into a band and re-tinted warm, because haze takes the colour of the
   light passing through it, and this light is gold.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-atm #g7-fog{
  left:-6%; right:-6%; top:35%; height:22vh; bottom:auto;
  z-index:var(--g5-z-grade);
  opacity:.44;
  mix-blend-mode:screen;
  background:
    url("/assets/login5/fog.png") center bottom / 100% 100% no-repeat,
    linear-gradient(180deg,
      rgba(var(--g5-atm-haze),0)   0%,
      rgba(var(--g5-atm-haze),.13) 38%,
      rgba(var(--g5-atm-haze),.07) 72%,
      transparent 100%);
  /* feather both edges — an unmasked band has a visible top line. #000 in a
     mask is geometry, not colour: only the alpha channel is read. */
  -webkit-mask-image:linear-gradient(180deg, transparent 0%, #000 30%, #000 62%, transparent 100%);
          mask-image:linear-gradient(180deg, transparent 0%, #000 30%, #000 62%, transparent 100%);
  animation:g5atmHaze 64s var(--g5-ease-in-out) infinite alternate !important;
}
@keyframes g5atmHaze{
  from{ transform:translate3d(-1.4%,0,0) }
  to  { transform:translate3d(1.4%,-1.1%,0) }
}

/* ═══════════════════════════════════════════════════════════════════════════
   4 · THE SHAFTS — #g6-rays, `screen`. Light, so it ADDS.
   A painted sheet (tools/gate5_art/02-atmosphere.py) rather than a
   conic-gradient: a conic wedge has a hard edge and a constant width, a real
   shaft has a hot core, a soft skirt and falls off with distance. Two copies
   at different scales drift past each other at different speeds — that
   parallax, not the shafts themselves, is what stops it looking like a decal.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-atm #g6-rays{
  inset:0; z-index:var(--g5-z-amb);
  opacity:.88 !important;
  mix-blend-mode:screen;
  animation:none;                                   /* imperial scaled this */
  /* the bloom AROUND the sun stays in CSS: the sheet deliberately has its
     root pulled down so the two never double up into a white blob */
  background:
    radial-gradient(ellipse 30% 24% at 10% -5%,
      rgba(var(--g5-atm-sun),.24), rgba(var(--g5-atm-fire),.06) 44%, transparent 72%) !important;
}
html.g5-atm #g6-rays::before,
html.g5-atm #g6-rays::after{
  content:''; position:absolute; inset:0;
  background-image:url("/assets/login5/art/atm-rays.png");
  background-repeat:no-repeat;
}
html.g5-atm #g6-rays::before{
  background-size:132% 124%; background-position:-8vw 0;
  opacity:.55;
  animation:g5atmRayA 38s var(--g5-ease-in-out) infinite alternate;
}
html.g5-atm #g6-rays::after{
  background-size:190% 170%; background-position:-26vw -8vh;
  opacity:.22;
  animation:g5atmRayB 61s var(--g5-ease-in-out) infinite alternate;
}
@keyframes g5atmRayA{
  from{ transform:translate3d(-1.1%,0,0)  scale(1.00) }
  to  { transform:translate3d(1.3%,-.8%,0) scale(1.045) }
}
@keyframes g5atmRayB{
  from{ transform:translate3d(1.6%,-.6%,0) scale(1.03) }
  to  { transform:translate3d(-1.4%,.5%,0) scale(1.00) }
}

/* ═══════════════════════════════════════════════════════════════════════════
   5 · THE VIGNETTE AND THE FRAME — #g6-vignette, plain alpha.
   Two jobs. The ellipse aims the eye at the two panels (centred a little high,
   where they are). The edge treatment turns a browser window into a plate: a
   feathered matte all round and one hairline of gold rule inset from it, the
   way a painting is set inside its mount. Nothing here is animated, so the
   inset shadow is paid for once.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-atm #g6-vignette{
  inset:0; z-index:var(--g5-z-amb);
  background:
    radial-gradient(ellipse 70% 62% at 50% 48%,
      transparent 30%, rgba(var(--g5-atm-deep),.36) 70%, rgba(var(--g5-atm-deep),.70) 100%),
    radial-gradient(ellipse 104% 96% at 50% 50%,
      transparent 56%, rgba(var(--g5-atm-deep),.46) 100%) !important;
  box-shadow:
    inset 0 0 130px 30px rgba(var(--g5-atm-deep),.58),
    inset 0 0 0 1px rgba(var(--g5-atm-deep),.85);
}
/* the mount: one hairline of gold, held off the edge */
html.g5-atm #g6-vignette::before{
  content:''; position:absolute;
  inset:clamp(7px,.78vw,15px);
  border:1px solid rgba(var(--g5-atm-gold),.20);   /* gold at a whisper */
  border-radius:var(--g5-r-xs);
}
/* and a second, tighter one that only reads at the corners */
html.g5-atm #g6-vignette::after{
  content:''; position:absolute;
  inset:calc(clamp(7px,.78vw,15px) + 4px);
  border-radius:var(--g5-r-xs);
  background:
    linear-gradient(90deg, rgba(var(--g5-atm-gold),.42), transparent 58px) left top    / 100% 1px no-repeat,
    linear-gradient(270deg,rgba(var(--g5-atm-gold),.42), transparent 58px) right top   / 100% 1px no-repeat,
    linear-gradient(90deg, rgba(var(--g5-atm-gold),.42), transparent 58px) left bottom / 100% 1px no-repeat,
    linear-gradient(270deg,rgba(var(--g5-atm-gold),.42), transparent 58px) right bottom/ 100% 1px no-repeat,
    linear-gradient(180deg,rgba(var(--g5-atm-gold),.42), transparent 58px) left top    / 1px 100% no-repeat,
    linear-gradient(0deg,  rgba(var(--g5-atm-gold),.42), transparent 58px) left bottom / 1px 100% no-repeat,
    linear-gradient(180deg,rgba(var(--g5-atm-gold),.42), transparent 58px) right top   / 1px 100% no-repeat,
    linear-gradient(0deg,  rgba(var(--g5-atm-gold),.42), transparent 58px) right bottom/ 1px 100% no-repeat;
}

/* ═══════════════════════════════════════════════════════════════════════════
   6 · THE EMBER FIELD — #g5-atm, injected by 02-atmosphere.js.
   The cheapest thing on this page and the one that does the most: a static
   background is a photograph, a background with three sparks crossing it is a
   world. 16 embers + 6 motes, each a 4–16px radial gradient painted ONCE and
   then only translated — no canvas, no rAF, no main-thread work at all.
   Every value that varies per spark is an inline custom property, so all of
   them share two keyframe tracks.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-atm #g5-atm{
  inset:0; z-index:var(--g5-z-amb);
  overflow:hidden;
  contain:layout paint style;
}
html.g5-atm .g5-em,
html.g5-atm .g5-mote{
  position:absolute; top:100%; left:var(--x);
  width:var(--sz); height:var(--sz);
  border-radius:50%;
  opacity:0;
}
html.g5-atm .g5-em{
  background:radial-gradient(circle at 50% 50%,
    rgba(var(--g5-atm-spark),.95) 0%, rgba(var(--g5-atm-sun),.72) 26%,
    rgba(var(--g5-atm-coal),.42) 52%, rgba(var(--g5-atm-coal),0) 74%);
  animation:g5atmRise var(--dur) var(--del) linear infinite;
}
/* motes are dust in the shaft, not fire: paler, slower, and they fall as
   often as they rise, which is what dust actually does */
html.g5-atm .g5-mote{
  top:auto; bottom:var(--y);
  background:radial-gradient(circle at 50% 50%,
    rgba(var(--g5-atm-spark),.55) 0%, rgba(var(--g5-atm-haze),.30) 42%, rgba(var(--g5-atm-haze),0) 72%);
  animation:g5atmDrift var(--dur) var(--del) var(--g5-ease-in-out) infinite alternate;
}
@keyframes g5atmRise{
  0%  { transform:translate3d(0,0,0) scale(.55);                       opacity:0 }
  7%  {                                                                opacity:var(--op) }
  26% { transform:translate3d(var(--sw),-27vh,0) scale(1) }
  50% { transform:translate3d(calc(var(--sw) * -.65),-53vh,0) scale(.9) }
  74% { transform:translate3d(calc(var(--sw) * .85),-79vh,0) scale(1.06);
                                                                       opacity:var(--op) }
  100%{ transform:translate3d(calc(var(--sw) * -.25),-112vh,0) scale(.7); opacity:0 }
}
@keyframes g5atmDrift{
  0%  { transform:translate3d(0,0,0) scale(.85);                              opacity:0 }
  18% {                                                                       opacity:var(--op) }
  82% {                                                                       opacity:var(--op) }
  100%{ transform:translate3d(var(--sw),calc(var(--sw) * -.7),0) scale(1.15);  opacity:0 }
}

/* ── 7 · GRAIN — the last thing in the pipeline, and the DITHER ──────────
   Plain alpha at 5%: mid-grey over near-black lifts the shadows a hair (the
   lifted-black film look) and, more usefully, breaks up the banding that six
   overlapping full-screen gradients would otherwise show on an 8-bit display.
   Static — the previous skin jittered its grain three times a second, which
   is three full-screen `overlay` recomposites a second for a texture nobody
   can see move. */
html.g5-atm .g5-grain{
  position:absolute; inset:0;
  background:url("/assets/login5/art/atm-grain.png") repeat 0 0 / 128px 128px;
  opacity:.05;
}

/* ── the canvas particle system this pass replaces ────────────────────────
   02-atmosphere.js calls AON_GATE_FX.stop() first; this only stops the empty
   canvas from being composited afterwards. Decorative + aria-hidden, so
   display:none here is safe — no login2.js code path touches it. */
html.g5-atm #g6-fx{ display:none !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE — phones show the poster and have no frame budget. Grade, haze-free,
   one static shaft pass, no embers, no drift. Everything below is paint-once.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:870px){
  /* the container stays — it carries the grain, which is the one layer a
     phone WANTS (the poster bands badly under a gradient). Only the moving
     parts go, and 02-atmosphere.js never creates them here in the first
     place; this is the belt to that braces. */
  html.g5-atm .g5-em, html.g5-atm .g5-mote{ display:none; }
  html.g5-atm #g7-fog{ display:none !important; }
  html.g5-atm #g6-rays{ opacity:.5 !important; }
  html.g5-atm #g6-rays::before{ animation:none; }
  html.g5-atm #g6-rays::after { display:none; }
  html.g5-atm #g6-vignette::after{ display:none; }
  html.g5-atm #g5-grade{
    background:
      radial-gradient(ellipse 74% 34% at 14% -4%,
        rgba(var(--g5-atm-fire),.24), transparent 70%),
      linear-gradient(180deg,
        rgba(var(--g5-atm-deep),.42) 0%,
        rgba(var(--g5-atm-deep),.16) 20%,
        rgba(var(--g5-atm-soot),.34) 52%,
        rgba(var(--g5-atm-deep),.80) 78%,
        rgba(var(--g5-atm-deep),.94) 100%) !important;
  }
}
html.g5-atm.mob .g5-em,
html.g5-atm.mob .g5-mote{ display:none; }
html.g5-atm.mob #g7-fog{ display:none !important; }
html.g5-atm.mob #g6-rays::after{ display:none; }

/* ── pause everything the moment the tab goes away. Set by 02-atmosphere.js
      on visibilitychange — no rAF loop is used anywhere in this pass. ───── */
html.g5-atm-still #g7-fog,
html.g5-atm-still #g6-rays::before,
html.g5-atm-still #g6-rays::after,
html.g5-atm-still .g5-em,
html.g5-atm-still .g5-mote{ animation-play-state:paused !important; }

/* ── reduced motion: the plate stays, the movement goes ─────────────────── */
@media (prefers-reduced-motion: reduce){
  html.g5-atm #g7-fog,
  html.g5-atm #g6-rays::before,
  html.g5-atm #g6-rays::after{ animation:none !important; }
  html.g5-atm .g5-em,
  html.g5-atm .g5-mote{ display:none; }
}

/* ══ gate5 · parts/03-hero.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 03 — THE HERO: wordmark, crest, tagline
   ───────────────────────────────────────────────────────────────────────────
   The hero was type with a gradient on it. A published game has a LOCKUP:
   a crest, letterforms with real depth, and an engraved rule under them.

     · #g5-crest .g5-shield   the game's own painted roundel (tower + crossed
                              spears) instead of a CSS star in a box.
     · .g5-title::before      the crowned shield, cut out of the game's own
                              aon-topbar-center art and charged with that same
                              roundel — one identity at two scales.
     · .g5-title              struck metal: a hammered-grain fill, a dark
                              bronze lip, a solid extrusion and a cast shadow,
                              built from three copies of ONE text node.
     · .g5-tag                engraved caps between two tapered rules that
                              terminate in a cut diamond.

   ── how the wordmark is built ────────────────────────────────────────────
   background-clip:text cannot take a text-shadow (the shadow shows straight
   through the transparent glyphs), and stacked drop-shadow() filters are a
   full-element repaint — imperial ran five of them in a 5.5s infinite loop
   ON TOP OF A LIVE WEBGL SCENE. So 03-hero.js wraps the h1's text in ONE
   <span class="g5-wm" data-t="…"> and the two pseudo-elements re-print that
   same string from attr():

       ::before   z-index -1   the dark bronze lip + the extrusion + the shadow
       the text node           the metal face  (grain × gold ramp, clip:text)
       ::after                 the lit top bevel               (clip:text)

   There is exactly ONE text node, so SEO and the accessibility tree still see
   "AGE OF NATIONS" once, not four times; the decorative copies are generated
   content and never enter the DOM. If the script never runs, .g5-title keeps
   a complete standalone treatment — the layers are scoped to html.g5-wm.

   ── specificity ──────────────────────────────────────────────────────────
   parts/*.css load BEFORE login5-imperial.css and login5-aoe.css, and those
   two set the hero with !important at (1,1,0). Every override here is
   prefixed `html` (or html.g5-wm) so it outranks them; nothing relies on
   source order. #g5-hero::before belongs to the aoe pass (the scrim behind
   the title) and is left alone.

   NOTHING HERE ANIMATES. The gate runs a live 3D kingdom; a logo does not
   need to shimmer, and the one loop that was here is switched off below.
   ═══════════════════════════════════════════════════════════════════════════ */

#g5-hero{
  /* composed from tokens, so the lockup has one vocabulary.
     min(vw,vh) is deliberate: the lockup has to give way on a SHORT screen
     (1440x900, 2292x958) as readily as on a narrow one, or it pushes the two
     panels off the fold. */
  --h-lip:    var(--g5-gold-5);                        /* dark side of the emboss */
  --h-emb:    clamp(62px, min(6.4vw, 11vh), 140px);    /* crowned shield width    */
  --h-word:   clamp(34px, min(4.6vw, 7.6vh), 104px);   /* wordmark cap size       */
  --h-rule:   clamp(52px, 7.4vw, 148px);               /* tagline flanking rule   */
  --h-track:  clamp(4px, .42vw, 8px);

  /* THE METAL. Two lit steps down the top bevel, a hard specular band at the
     letter's waist, then the shaded face into the deep engrave — the ramp a
     struck-gold letter actually has. Declared once, worn by both the layered
     wordmark and its script-less fallback. */
  --h-grain: url("/assets/login5/art/hero-grain.png");
  --h-metal: linear-gradient(180deg,
      var(--g5-gold-1)  0%,
      var(--g5-gold-2) 13%,
      var(--g5-gold-3) 36%,
      var(--g5-gold-1) 47%,
      var(--g5-gold-2) 53%,
      var(--g5-gold-3) 64%,
      var(--g5-gold-4) 86%,
      var(--g5-gold-5) 100%);
}

/* ══ 1 · THE CREST — the game's painted roundel, not a CSS star ══════════ */
html #g5-crest{ gap:clamp(10px,.85vw,15px) !important; align-items:center; }

html #g5-crest .g5-shield{
  width:clamp(46px,3.1vw,58px) !important;
  height:clamp(46px,3.1vw,58px) !important;
  flex:0 0 auto;
  border:0 !important;
  border-radius:50% !important;
  background:url("/assets/login5/art/hero-crest.png") 50% 50%/contain no-repeat !important;
  box-shadow:none !important;
  /* drop-shadow follows the roundel's alpha; a box-shadow would draw a disc */
  filter:drop-shadow(0 4px 10px rgba(0,0,0,.7)) saturate(1.12) contrast(1.05);
  overflow:visible;
  font-size:0 !important;
  transition:transform var(--g5-t-base) var(--g5-spring),
             filter var(--g5-t-base) var(--g5-ease);
}
/* imperial drew the mark with gradients; the painted art replaces it */
html #g5-crest .g5-shield::before{ content:none; }
/* a soft glass highlight across the top-left of the boss */
html #g5-crest .g5-shield::after{
  content:'';
  position:absolute; inset:6%;
  border-radius:50%;
  background:linear-gradient(148deg, rgba(255,244,214,.16) 0%, rgba(255,244,214,.03) 30%, transparent 52%);
  pointer-events:none;
}
html #g5-crest .g5-shield svg{ display:none; }

html #g5-crest:hover .g5-shield{
  transform:translateY(-1px) scale(1.04);
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.75)) drop-shadow(0 0 14px var(--g5-line-2))
         saturate(1.2) contrast(1.06);
}
html #g5-crest:focus-visible{ outline:2px solid var(--g5-gold-3); outline-offset:5px; border-radius:var(--g5-r-sm); }

/* the top-left wordmark is the QUIET mark — the hero carries the name */
html #g5-crest .g5-wordmark{
  font-size:clamp(13px,.86vw,16px) !important;
  letter-spacing:.24em !important;
  line-height:1;
  background:linear-gradient(180deg, var(--g5-gold-2) 0%, var(--g5-gold-3) 52%, var(--g5-gold-4) 100%) !important;
  -webkit-background-clip:text !important; background-clip:text !important;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.85)) !important;
  opacity:.92;
  transition:opacity var(--g5-t-base) var(--g5-ease);
}
html #g5-crest:hover .g5-wordmark{ opacity:1; }

/* ══ 2 · THE HERO BLOCK ═════════════════════════════════════════════════ */
html #g5-hero{
  margin:clamp(6px,3vh,34px) 0 clamp(6px,2vh,22px) !important;
  padding:0 20px;
}

/* ── 2a · the crowned shield above the wordmark ─────────────────────────── */
html #g5-hero .g5-title::before{
  content:'';
  display:block;
  width:var(--h-emb);
  aspect-ratio:300/382;
  /* negative: Cinzel leaves a deep ascender gap above the caps, so the shield
     is pulled into it. That closing of the gap is what makes it one lockup
     instead of a picture with a heading under it. */
  margin:0 auto clamp(-22px,-1.5vh,-6px);
  background:url("/assets/login5/art/hero-emblem.webp") 50% 100%/contain no-repeat;
  filter:drop-shadow(0 12px 22px rgba(0,0,0,.62));
}

/* ── 2b · the wordmark ─────────────────────────────────────────────────── */
html #g5-hero .g5-title{
  font-family:var(--g5-f-display);
  font-weight:700;
  font-size:var(--h-word) !important;
  line-height:1.02;
  letter-spacing:.085em !important;
  text-indent:.085em;                 /* letter-spacing pads the LAST glyph  */
  margin:0;
  /* imperial ran five stacked drop-shadows on a 5.5s infinite filter loop.
     Over a live WebGL scene that is a full-element repaint every frame. */
  animation:none !important;
  will-change:auto;
}

/* CSS-only fallback: if 03-hero.js never runs there is no .g5-wm to layer,
   so the h1 itself keeps the metal fill and a static carved shadow. */
html #g5-hero .g5-title{
  background:var(--h-grain) 50% 50%/86px auto repeat, var(--h-metal) !important;
  background-blend-mode:overlay, normal;
  -webkit-background-clip:text !important;
  background-clip:text !important;
  color:transparent;
  filter:
    drop-shadow(0 2px 0 rgba(0,0,0,.9))
    drop-shadow(0 12px 26px rgba(0,0,0,.72)) !important;
}

/* the layered build takes over the moment the script has wrapped the text */
html.g5-wm #g5-hero .g5-title{
  background:none !important;
  -webkit-background-clip:border-box !important;
  background-clip:border-box !important;
  filter:none !important;
}
html.g5-wm #g5-hero .g5-title::before{
  /* the emblem lost the h1's filter, so it carries its own shadow */
  filter:drop-shadow(0 12px 22px rgba(0,0,0,.62));
}

html #g5-hero .g5-wm{
  position:relative;
  display:inline-block;
  text-indent:0;                      /* the h1 carries the optical shift    */
  /* a stacking context, so the extrusion's z-index:-1 is LOCAL paint order
     inside the wordmark and never touches the --g5-z-* page layer scale */
  isolation:isolate;
  white-space:nowrap;
  /* hammered grain blended into the gold ramp — a gradient on its own reads
     as a gradient, the grain is what makes it read as struck metal */
  background:var(--h-grain) 50% 50%/86px auto repeat, var(--h-metal);
  background-blend-mode:overlay, normal;
  -webkit-background-clip:text; background-clip:text;
  color:transparent;
}
html #g5-hero .g5-wm::before,
html #g5-hero .g5-wm::after{
  content:attr(data-t);
  position:absolute; left:0; top:0; width:100%;
  white-space:nowrap;
  pointer-events:none;
}
/* the lip + the extrusion + the shadow the wordmark sits in */
html #g5-hero .g5-wm::before{
  z-index:-1;
  color:var(--h-lip);
  transform:translateY(2px);
  text-shadow:
    0 1px 0 rgba(0,0,0,.92),
    0 2px 0 rgba(0,0,0,.88),
    0 3px 0 rgba(0,0,0,.84),
    0 4px 0 rgba(0,0,0,.74),
    0 5px 0 rgba(0,0,0,.56),
    0 10px 20px rgba(0,0,0,.72),
    0 26px 48px rgba(0,0,0,.6);
}
/* the lit top bevel + a hint of bounce off the bottom edge */
html #g5-hero .g5-wm::after{
  color:transparent;
  background:
    linear-gradient(180deg, rgba(255,255,255,.82) 0%, rgba(255,244,214,.34) 11%, rgba(255,244,214,0) 27%),
    linear-gradient(0deg,   rgba(255,233,168,.26) 0%, rgba(255,233,168,0) 13%);
  -webkit-background-clip:text; background-clip:text;
}

/* ── 2c · the tagline: engraved caps between two rules ──────────────────── */
html #g5-hero .g5-tag{
  margin:clamp(9px,1.5vh,19px) 0 0 !important;
  display:inline-flex; align-items:center;
  gap:clamp(9px,1.2vw,18px);
  font-family:var(--g5-f-display);
  font-weight:600;
  font-size:clamp(10px,.8vw,13.5px);
  line-height:1;
  letter-spacing:var(--h-track) !important;
  color:var(--g5-ink-2) !important;
  text-shadow:0 1px 0 rgba(0,0,0,.92), 0 2px 9px rgba(0,0,0,.8) !important;
}
html #g5-hero .g5-tag i{
  position:relative;
  width:var(--h-rule) !important;
  height:8px !important;
  flex:0 0 auto;
  box-shadow:none;
  /* a tapered gold hairline with its engraved shadow line beneath it */
  background:
    linear-gradient(90deg, transparent 0%, var(--g5-line) 34%, var(--g5-line-2) 100%)
      0 3px/100% 1px no-repeat,
    linear-gradient(90deg, transparent 0%, rgba(0,0,0,.55) 40%, rgba(0,0,0,.8) 100%)
      0 4px/100% 1px no-repeat !important;
}
/* letter-spacing pads the RIGHT of the last glyph, so the words sit a whole
   space closer to the left rule than the right one. Pull the right rule back
   by exactly that, and the three parts read as centred. */
html #g5-hero .g5-tag i:last-child{ margin-left:calc(var(--h-track) * -1); }
/* the cut diamond where the rule meets the words */
html #g5-hero .g5-tag i::after{
  content:'';
  position:absolute; right:-1px; top:50%;
  width:7px; height:7px; margin:-4px 0 0;
  transform:rotate(45deg);
  background:linear-gradient(135deg, var(--g5-gold-1), var(--g5-gold-3) 46%, var(--g5-gold-5));
  box-shadow:0 0 0 1px rgba(0,0,0,.5), 0 0 9px var(--g5-line);
}

/* imperial's filigree under the tag would be a THIRD horizontal rule under a
   lockup that already has two. The composition is tighter without it. */
html #g5-hero::after{ content:none !important; }

/* ══ 3 · SHORT VIEWPORTS ════════════════════════════════════════════════
   login5.css already compacts the hero under 780px tall; the emblem has to
   give way first, then go, so the two panels always clear the fold.        */
@media (max-height:780px){
  html #g5-hero{ margin:6px 0 8px !important; }
  #g5-hero{
    --h-emb:clamp(56px, min(4.6vw, 9.6vh), 88px);
    --h-word:clamp(28px, min(3.4vw, 6.2vh), 62px);
    --h-rule:clamp(40px, 5.4vw, 96px);
  }
  html #g5-hero .g5-tag{ margin-top:9px !important; }
}
@media (max-height:640px){
  html #g5-hero .g5-title::before{ display:none; }
}

/* ══ 4 · THE PHONE COLUMN (#mob) ════════════════════════════════════════
   Different DOM: .m-hero prints the wordmark and the tagline from ::before /
   ::after, both already owned by imperial. The crest goes on the element
   itself so nothing is fought over.                                        */
html.mob #mob .m-hero{
  margin:clamp(20px,5vh,44px) 0 18px !important;
  padding-top:clamp(84px,21vw,124px);
  background:url("/assets/login5/art/hero-emblem.webp") 50% 0/auto clamp(78px,19.5vw,116px) no-repeat;
}
html #mob .m-hero::before{
  letter-spacing:.1em !important;
  filter:
    drop-shadow(0 2px 0 rgba(0,0,0,.9))
    drop-shadow(0 8px 20px rgba(0,0,0,.8)) !important;
}
html #mob .m-hero::after{
  margin-top:10px;
  letter-spacing:.34em !important;
  color:var(--g5-ink-2) !important;
}

/* ══ 5 · MOTION ═════════════════════════════════════════════════════════
   Nothing in this pass animates by itself; these are the hover transitions,
   and they are switched off with everything else.                          */
@media (prefers-reduced-motion:reduce){
  html #g5-crest .g5-shield,
  html #g5-crest .g5-wordmark{ transition:none !important; }
  html #g5-crest:hover .g5-shield{ transform:none; }
}

/* ══ gate5 · parts/04-panels.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PASS 04 — THE TWO PANELS                  parts/04-panels.css
   ───────────────────────────────────────────────────────────────────────────
   LOGIN and REGISTER are the only two objects on this page a player actually
   touches. They were a 26px border-image over a flat two-stop gradient. This
   pass makes them forged, lit and SEATED in the 3D kingdom behind them.

   WHAT CHANGED
   1 · the frame   hud-grand-modal-v10-alpha.png — the celtic-knot steel frame
                   with turquoise corner gems and the crowned top crest —
                   replaces the hud-card-frame cut. It is a *modal* frame:
                   painted for exactly this job, and by far the richest piece
                   in client/assets/ui. Cut by tools/gate5_art/04-panels.py:
                   2.03 MB -> 30 KB (crop to bbox · punch the interior ·
                   collapse the side rails · 256-colour palette).
   2 · the surface real painted slate (aon-forged-panel-v34's interior, made
                   seamless) over the token plate gradient, with a rake from
                   the top-left — the same corner the scene's sun comes from —
                   and an ambient-occlusion edge where the field meets the rail.
   3 · the head    a real plaque under the title (the game's own ornate
                   cap-left / center / cap-right bar set, composed and
                   9-sliced), letterspaced caps beneath, an engraved rule.
   4 · hierarchy   LOGIN is the sunk, cool, quiet one — "come back".
                   REGISTER is raised, lit and warm — "begin". Same system,
                   not identical twins.
   5 · depth       contact + ambient shadow and a faint warm bleed onto the
                   scene, so the panels sit ON the world instead of over it.

   GEOMETRY IS LOAD-BEARING and it does not move. `.g5-panel` is content-box,
   so `width` is the content column and stays exactly what it was. The frame
   art overhangs — a crown crest and four corner spikes rise above the rails —
   and paying for that with border-width would have eaten 25px of panel. So
   `border-width` stays at the rail thickness (27px sides, as before) while
   `border-image-width` + `border-image-outset` hang the overhang OUTSIDE the
   box. Layout uses border-width only: nothing shifts.

     source (hud-grand-modal cropped to bbox, 1461x910), display scale s=.34
       top    silhouette y=65   rail inner face y=129  -> 22px border
       left   silhouette x=14   rail inner face x=94   -> 27px border
       right  silhouette x=1445 rail inner face x=1366 -> 27px border
       bottom silhouette y=893  rail inner face y=848  -> 15px border
     so   outset = silhouette*s        (22 5 6 5)
     and  border-image-width = 200*s / 140*s   (68 68 48 68)
     and  border-width = rail*s        (22 27 15 27)

   The top/bottom middle slices are NOT collapsed: `stretch` draws a middle
   slice exactly once, so keeping them full width leaves the crown crest and
   the bottom diamond CENTRED for free, with the braid stretched ~12%.

   CASCADE — index.php loads login5-imperial.css and login5-aoe.css AFTER
   gate5.css.php, and both restyle `.g5-panel` with `!important`. Everything
   here is therefore scoped `#g5-panels …`: one id outranks any number of
   classes, so this pass wins whether or not those two legacy sheets are
   still linked. Nothing here touches `display` on anything login2.js toggles.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --g5p-frame:  url("/assets/login5/art/pnl-frame.png");
  --g5p-plaque: url("/assets/login5/art/pnl-plaque.png");
  --g5p-grain:  url("/assets/login5/art/pnl-grain.png");
  --g5p-rule:   url("/assets/login5/art/pnl-rule.png");
}

/* ══ 1 · THE PLATE ══════════════════════════════════════════════════════════
   background-clip is BORDER-box on purpose: the rail art is fully opaque
   across the whole border band, so filling under it costs nothing and removes
   the 1px sliver of live 3D scene that padding-box clipping leaves between the
   rail's inner face and the field whenever the border rounds to a half pixel. */
#g5-panels .g5-panel{
  position:relative;
  box-sizing:content-box;
  border-style:solid !important;
  border-color:transparent !important;
  border-width:22px 27px 15px !important;
  border-image:var(--g5p-frame) 100 100 70 100 / 68px 68px 48px 68px / 22px 5px 6px 5px stretch !important;
  padding:12px 15px 16px !important;
  background:var(--g5-plate) !important;
  background-origin:padding-box !important;
  background-clip:border-box !important;
  overflow:visible;
  /* seated: a tight contact, a wide ambient, and a warm bleed onto the scene */
  box-shadow:
    0 18px 30px -16px rgba(0,0,0,.78),
    0 44px 90px -34px rgba(0,0,0,.85),
    0 0 74px -26px rgba(232,192,94,.22) !important;
}

/* REGISTER is the RAISED one — the token plate has a lit step for exactly this */
#g5-panels .g5-panel.g6-register{
  background:var(--g5-plate-hi) !important;
  box-shadow:
    0 20px 34px -16px rgba(0,0,0,.8),
    0 52px 104px -34px rgba(0,0,0,.88),
    0 0 96px -22px rgba(232,192,94,.30) !important;
}

/* imperial's 2px inner hairline and its four 2px corner studs were standing in
   for an ornament the frame did not have. It has one now — four celtic knots
   and four gems — so they only add noise. */
#g5-panels .g5-panel::before{ content:none; }

/* ══ 2 · THE SURFACE ═══════════════════════════════════════════════════════
   Two decorative layers, both inside the panel's own stacking order and both
   below the z-index:1 children the earlier sheets already set:
     .g6-panel-ornament (first child)  = the material
     ::after            (last child)   = the light and the occlusion
   ------------------------------------------------------------------------- */
/* the ornament div is the carrier; its two pseudos are the material and the
   tint. Tints are `token colour + opacity` rather than a mixed rgba, so the
   only colour named anywhere in this pass is a token — and so that an old
   engine that cannot parse a colour function drops a wash, never the plate. */
#g5-panels .g5-panel > .g6-panel-ornament{
  position:absolute; inset:0; z-index:0; pointer-events:none;
  border-radius:var(--g5-r-xs);
  background:none;
  opacity:1;
  box-shadow:none;
}
/* REAL painted slate, not a noise filter: cut from the interior of
   aon-forged-panel-v34.png and made seamless. Baked to white-over-dark with a
   per-pixel alpha, so it modulates the plate underneath with no blend mode —
   background-blend-mode over a live WebGL scene is a composite worth avoiding.
   13 KB. */
#g5-panels .g5-panel > .g6-panel-ornament::before{
  content:''; position:absolute; inset:0;
  background:var(--g5p-grain) 0 0 / 168px repeat;
  opacity:.42;
}
/* the rake comes from the top-left — the corner the kingdom's sun is in */
#g5-panels .g5-panel > .g6-panel-ornament::after{
  content:''; position:absolute; inset:0;
  background:radial-gradient(120% 88% at 0% -12%, var(--g5-gold-2) 0 6%, transparent 68%);
  opacity:.14;
}
/* REGISTER — a warm wash off the top rail over the same rake. `--g5-blood` is
   the token that exists for this side of the gate. Both gradients hold their
   colour to an explicit first stop and then fall away: a plain centre-to-
   transparent ramp is only ever at full strength at its own centre, which is
   above the box, so it lands under 6% effective alpha on a plate this dark and
   simply is not there — and widening it far enough to be seen washes the whole
   panel mauve instead of warming its head. */
#g5-panels .g5-panel.g6-register > .g6-panel-ornament::before{ opacity:.34; }
#g5-panels .g5-panel.g6-register > .g6-panel-ornament::after{
  background:
    radial-gradient(150% 72% at 50% -6%, var(--g5-blood) 0 30%, transparent 76%),
    radial-gradient(120% 88% at 0% -12%, var(--g5-gold-2) 0 6%, transparent 68%);
  opacity:.26;
}

/* the field is SUNK behind the rail: an occluded edge all the way round.
   `opacity` is restated because imperial's `.g5-panel::after` (its four corner
   studs, replaced above) also sets .55 — and opacity is the one thing it
   declares that a background override would otherwise inherit. */
#g5-panels .g5-panel::after{
  content:''; position:absolute; inset:0; z-index:0; pointer-events:none;
  opacity:1;
  border-radius:var(--g5-r-xs);
  background:linear-gradient(178deg, rgba(255,246,220,.05), rgba(255,246,220,0) 26%);
  box-shadow:
    inset 0 0 0 1px rgba(232,192,94,.09),
    inset 0 13px 20px -13px rgba(0,0,0,.92),
    inset 0 -15px 26px -15px rgba(0,0,0,.8),
    inset 14px 0 24px -17px rgba(0,0,0,.85),
    inset -14px 0 24px -17px rgba(0,0,0,.85);
}

/* ══ 3 · THE HEAD ══════════════════════════════════════════════════════════
   A real plaque, not a text style: hud-ornate-cap-left-v8 + hud-ornate-center-v8
   + hud-ornate-cap-right-v8 composed into one 9-slice sheet (7 KB).

   It is the h2's OWN border-image, not a pseudo behind it, for two reasons.
   Painting order: a `border-image` draws after the element's background and
   before its inline content, so the plaque lands *under the title and over
   everything else* with no z-index at all — a `::before` at z-index:-1 paints
   over the background, which is where `background-clip:text` keeps its gold
   leaf, and would have blanked the title. And it auto-sizes: login2.js
   rewrites #ng-cap (`FOUNDING YOUR EMPIRE…`, `REGISTRATION UNAVAILABLE`), so
   the plaque has to grow with the caption instead of being a fixed box.

   That trades the clipped-gradient leaf for solid gold — which is the better
   read anyway: the gradient's bottom stop is #6d4f1c, invisible against a dark
   plaque. Struck metal instead: a lit face with an engraved lip under it.
   ------------------------------------------------------------------------- */
#g5-panels .g5-panel h2{
  position:relative; z-index:1;
  box-sizing:border-box;
  margin:0 0 9px !important;
  padding:3px 6px 4px !important;
  border-style:solid !important; border-color:transparent !important;
  border-width:8px 46px 9px !important;
  border-image:var(--g5p-plaque) 10 63 12 63 fill / 8px 46px 9px stretch !important;
  font:var(--g5-t-title) !important;
  font-size:24px !important;
  letter-spacing:var(--g5-track-2) !important;
  /* letter-spacing pads the LAST glyph too, which walks centred caps left by
     half a step — put it back */
  text-indent:var(--g5-track-2);
  background-image:none !important;
  -webkit-background-clip:border-box !important;
  background-clip:border-box !important;
  color:var(--g5-gold-2) !important;
  -webkit-text-fill-color:var(--g5-gold-2) !important;
  text-shadow:
    0 1px 0 var(--g5-gold-5),
    0 2px 1px rgba(0,0,0,.65),
    0 5px 16px rgba(0,0,0,.7) !important;
  filter:drop-shadow(0 3px 5px rgba(0,0,0,.5));
}
/* the register plaque is lit from within — it is the invitation. The TITLE
   colour stays gold-2 on both: pushing this one to gold-1 read as white, and
   the difference between the two panels belongs in the plate, not the type. */
#g5-panels .g5-panel.g6-register h2{
  filter:drop-shadow(0 3px 5px rgba(0,0,0,.5)) brightness(1.07);
}

#g5-panels .g5-panel .g5-sub{
  margin:0 0 6px !important;
  font:var(--g5-t-sub) !important;
  letter-spacing:var(--g5-track-2) !important;
  text-indent:var(--g5-track-2);
  color:var(--g5-ink-3) !important;
  text-shadow:0 1px 0 rgba(0,0,0,.7) !important;
}
#g5-panels .g5-panel.g6-register .g5-sub{ color:var(--g5-ink-2) !important; }

/* the engraved rule — client/assets/royal/bar_sep.png, trimmed (4 KB) */
#g5-panels .g5-panel .g5-rule{
  border:0 !important;
  height:16px !important;
  width:76% !important;
  margin:0 auto 12px !important;
  background:var(--g5p-rule) center / contain no-repeat !important;
  opacity:.85;
}
#g5-panels .g5-panel.g6-register .g5-rule{ opacity:.95; }

/* The login panel's FOOT. `.g5-socrow{margin:auto 0 4px}` in the base is what
   makes the two stretched panels read as one composition instead of a form
   with a hole under it — login5-imperial.css:556 replaced it with a flat
   `margin-top:16px !important`, which dropped the socials into the middle of
   the panel and left ~110px of dead plate below them (measured on the render
   before this pass). The auto margin is panel composition, so it comes back
   here; imperial's rule above it — a hairline and its centred pip — stays. */
#g5-panels .g5-panel .g5-socrow{ margin:auto 0 var(--g5-s1) !important; }

/* ══ 4 · RESPONSIVE ════════════════════════════════════════════════════════
   Verified at 1280 / 1600 / 1920 / 2560 wide and at max-height:780px. The
   panel is content-box, so none of this changes the content column: the
   nation grid keeps its width, its max-height scroll and its fade mask.
   ------------------------------------------------------------------------- */
@media (max-height:780px){
  #g5-panels .g5-panel{ padding:8px 15px 10px !important; }
  #g5-panels .g5-panel h2{
    margin:0 0 6px !important;
    padding:2px 6px 3px !important;
    font-size:21px !important;
    border-width:7px 41px 8px !important;
    border-image:var(--g5p-plaque) 10 63 12 63 fill / 7px 41px 8px stretch !important;
  }
  #g5-panels .g5-panel .g5-rule{ height:14px !important; margin-bottom:9px !important; }
}
/* the tablet band where the row stacks — the frame is a 9-slice, it just works,
   but the crest's 22px outset needs the stacked gap not to swallow it */
@media (max-width:940px) and (min-width:869px){
  #g5-panels{ gap:34px !important; }
}

/* ══ gate5 · parts/05-controls.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 05 — THE CONTROLS                assets/login5/parts/05-controls.css
   ───────────────────────────────────────────────────────────────────────────
   Everything the player actually TOUCHES: the two fields, the reveal, the
   remember-me stud, the forgot link, the CTA, the social coins, the Google
   slot and the message strip.

   The brief for all of it is one word: FORGED. A field is a slot stamped into
   the panel's iron — dark at the top where the lip shadows it, lit along the
   far edge where the bounce catches, with real grain in the floor. An icon is
   struck into that floor, not printed on it. The CTA is the one raised object
   on the page and it must move like a lever. Nothing here is a rectangle with
   a border.

   ── WHY EVERY RULE CARRIES `#g5-panels` ──────────────────────────────────
   index.php loads `login5-imperial.css` and `login5-aoe.css` AFTER the whole
   gate5 aggregator, and both fire `!important` at `.g5-field`, `.g5-cta`,
   `.g5-check i` and `.sochot`. A part file cannot win those on document order,
   so the structural declarations here are scoped to `#g5-panels` — an id beats
   any number of classes, and `!important` is added only where the later sheets
   already used it. Nothing is over-specified for its own sake: `.omsg`/`.mmsg`
   are plain selectors, because nothing after this file touches them.

   ── WIRING (login2.js, untouched) ────────────────────────────────────────
   setBusy()     -> button.disabled + `.is-busy` + [aria-busy] + label swap
   markInvalid() -> input[aria-invalid="true"] (+ .focus()), NOT the label
   setMsg()      -> msg `.show` when non-empty, `.ok` when good, role=alert
   reveal        -> `.eyehot` gains `.shown` + [aria-pressed]; text is NOT
                    swapped for this button, so the glyph has to be CSS
   `#soc-google` and `#gsi-desktop` have their `display` written INLINE by
   login2.js — nothing here declares `display` on either of them.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ══ 0 · derived vocabulary ════════════════════════════════════════════════
   No new colours: every one of these is a token mixed with transparency, or
   plain light/shadow — which is exactly how tokens.css writes --g5-bevel and
   --g5-engrave. Declared once so the same lip, the same cut and the same gold
   wash are literally the same value on every control below. */
:root{
  --c5-lip:      rgba(255,244,210,.13);          /* --g5-gold-1 as a lit edge */
  --c5-lip-2:    rgba(255,244,210,.26);
  --c5-cut:      rgba(0,0,0,.72);                /* the engraved line          */
  --c5-sink:     rgba(0,0,0,.9);
  --c5-iron:     url("/assets/login5/art/ctl-iron.png");   /* peened grain     */

  --c5-gold-a08: color-mix(in srgb, var(--g5-gold-3)  8%, transparent);
  --c5-gold-a20: color-mix(in srgb, var(--g5-gold-3) 20%, transparent);
  --c5-gold-a34: color-mix(in srgb, var(--g5-gold-3) 34%, transparent);
  --c5-gold-a55: color-mix(in srgb, var(--g5-gold-3) 55%, transparent);
  --c5-gold5-a55:color-mix(in srgb, var(--g5-gold-5) 55%, transparent);

  /* every iron token is a cool grey. A trace of --g5-gold-5 in the FLOOR of a
     well is the bounce light off a gold-rimmed slot, and without it the fields
     read as blue-black holes that belong to a different page than the rim. */
  --c5-warm-floor: color-mix(in srgb, var(--g5-iron-2) 84%, var(--g5-gold-5));

  --c5-err-wash: color-mix(in srgb, var(--g5-blood) 34%, transparent);
  --c5-err-line: color-mix(in srgb, var(--g5-err)   50%, transparent);
  --c5-err-glow: color-mix(in srgb, var(--g5-err)   26%, transparent);
  --c5-ok-wash:  color-mix(in srgb, var(--g5-ok)    14%, transparent);
  --c5-ok-line:  color-mix(in srgb, var(--g5-ok)    42%, transparent);
}


/* ══ 1 · FIELDS — a slot stamped into the panel ════════════════════════════
   Four things make it read as a real cut rather than a dark box:
     · the floor is DARKEST AT THE TOP (the lip shadows it) and warms toward
       the bottom, which is the opposite of a raised surface;
     · peened iron grain in the floor (tools/gate5_art/05-controls.py, a 48px
       seamless tile, 2.6 KB) — nothing you would ever call a texture, and the
       whole difference between a material and a gradient;
     · a light hairline along the INSIDE of the bottom edge (the far wall
       catching the bounce) and a dark hairline OUTSIDE the top (the cut);
     · an engraved groove between the icon seat and the text.                */
#g5-panels .g5-field{
  gap:13px;
  background:
    var(--c5-iron) 0 0 / 24px 24px repeat,
    linear-gradient(180deg,
      var(--g5-well)   0%,
      var(--g5-iron-3) 58%,
      var(--c5-warm-floor) 100%) !important;
  border:1px solid var(--c5-gold-a20) !important;
  box-shadow:
    inset 0 3px 6px -1px var(--c5-sink),
    inset 0 14px 16px -14px rgba(0,0,0,.8),
    inset 0 -1px 0 var(--c5-lip),
    0 1px 0 rgba(255,244,210,.055),
    0 -1px 0 rgba(0,0,0,.55) !important;
  /* colour + transform only. No box-shadow in the transition list: this sits
     over a live WebGL scene and a shadow tween is the one thing that costs
     real money there. The focus "ignite" below is transform/opacity. */
  transition:
    border-color var(--g5-t-fast) var(--g5-ease),
    background-color var(--g5-t-fast) var(--g5-ease) !important;
}
/* the groove between the icon seat and the text.
   left = the field's own padding (14px, set by login5-imperial) + the icon box
   (18px) + half the 13px gap above. Written out so it stays legible if any of
   the three ever moves. */
#g5-panels .g5-field::before{
  content:''; position:absolute; left:calc(14px + 18px + 6px);
  top:12px; bottom:12px; width:1px;
  background:linear-gradient(180deg,
    transparent, var(--c5-cut) 24%, var(--c5-cut) 76%, transparent);
  box-shadow:1px 0 0 rgba(255,244,210,.05);
  pointer-events:none;
}

/* the IGNITE — heat rising off the floor of the slot, anchored on a bright
   filament along the base. It grows from the bottom edge (scaleY, origin at
   the floor) so focus reads as the slot lighting UP rather than as a border
   changing colour. transform + opacity only; one shot; nothing looping.
   A first cut put a thin gold filament here and it was invisible — the focused
   border is already bright gold, so a gold hairline 1px inside it had nothing
   to contrast against. The heat has to spill onto the dark floor to be seen. */
#g5-panels .g5-field::after{
  content:''; position:absolute; left:1px; right:1px; bottom:1px; height:22px;
  border-radius:0 0 5px 5px;
  background:linear-gradient(180deg,
    transparent 0%,
    var(--c5-gold-a08) 46%,
    var(--c5-gold-a34) 84%,
    var(--g5-gold-2) 100%);
  opacity:0; transform:scaleY(.25); transform-origin:50% 100%;
  transition:
    opacity   var(--g5-t-fast) var(--g5-ease),
    transform var(--g5-t-base) var(--g5-ease);
  pointer-events:none;
}

#g5-panels .g5-field:hover{ border-color:var(--c5-gold-a34) !important; }

#g5-panels .g5-field:focus-within{
  border-color:var(--g5-gold-3) !important;
  box-shadow:
    inset 0 3px 6px -1px var(--c5-sink),
    inset 0 14px 16px -14px rgba(0,0,0,.72),
    inset 0 -1px 0 var(--c5-lip-2),
    inset 0 0 22px -6px var(--c5-gold-a34),
    0 0 0 1px var(--c5-gold-a34),
    0 0 20px -4px var(--c5-gold-a34) !important;
}
#g5-panels .g5-field:focus-within::after{ opacity:1; transform:none; }

/* keyboard arrival gets a ring on top of the ignite — a login form is the
   last place to hide focus. */
#g5-panels .g5-field:has(input:focus-visible){
  outline:2px solid var(--g5-gold-2);
  outline-offset:3px;
}

/* ── the struck icon ──────────────────────────────────────────────────────
   Two opposed 1px drop-shadows — dark above, warm below — is what turns a
   printed glyph into a stamped one: the light says there is a lip above the
   shape and a bevel below it, which is exactly what a die leaves behind.

   The silhouettes are keyed off the input's NAME, not its id. login5-imperial
   keys the same masks off `#li-identity` / `#li-password`, and an id is a
   thing another pass could reasonably rename; `name=` is what the browser
   autofills on and what login2.js reads (`f.email`, `f.password`), so it is
   the stable hook. */
#g5-panels .g5-field .gi{
  flex:0 0 18px; width:18px; height:18px;
  font-size:0;
  background:currentColor;
  color:var(--g5-gold-4);
  opacity:1;
  filter:
    drop-shadow(0 -1px 0 rgba(0,0,0,.9))
    drop-shadow(0  1px 0 rgba(255,244,210,.16));
  transition:color var(--g5-t-fast) var(--g5-ease);
  -webkit-mask:var(--c5-i-user) center / contain no-repeat;
          mask:var(--c5-i-user) center / contain no-repeat;
}
#g5-panels .g5-field:has(input[name="password"]) .gi{
  -webkit-mask-image:var(--c5-i-lock);
          mask-image:var(--c5-i-lock);
}
:root{
  --c5-i-user:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M12 12a5 5 0 1 0-5-5 5 5 0 0 0 5 5zm0 2c-4.4 0-8 2.2-8 5v1h16v-1c0-2.8-3.6-5-8-5z'/></svg>");
  --c5-i-lock:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M17 9h-1V7a4 4 0 0 0-8 0v2H7a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2zm-7-2a2 2 0 0 1 4 0v2h-4V7zm3 8.7V18h-2v-2.3a1.5 1.5 0 1 1 2 0z'/></svg>");
}
#g5-panels .g5-field:hover .gi{ color:var(--g5-gold-3); }
#g5-panels .g5-field:focus-within .gi{ color:var(--g5-gold-2); }

/* ── the text ──
   16px is not a taste call: below it iOS zooms the whole page on focus and
   the player lands on a login form they have to pinch back out of. */
#g5-panels .g5-field input{
  font-size:16px !important;
  letter-spacing:.2px;
  color:var(--g5-ink) !important;
  box-shadow:none !important;   /* login5-aoe puts a second well on the input */
  caret-color:var(--g5-gold-2);
}
/* --g5-ink-3 rather than --g5-ink-4: a placeholder is the label on a login
   field, and at 45% alpha over a black well it was under 3:1. It is still
   plainly dimmer than typed text (--g5-ink), which is the only job it has. */
#g5-panels .g5-field input::placeholder{
  color:var(--g5-ink-3) !important;
  letter-spacing:.3px;
}
#g5-panels .g5-field input::selection{
  background:var(--c5-gold-a55); color:var(--g5-ink-on);
}

/* Chrome paints its own pale-yellow slab over an autofilled login and there is
   no property that turns it off — clipping the background to the glyphs is the
   one reliable way to keep the forged well, and the long transition covers the
   frame or two before that lands. */
#g5-panels .g5-field input:-webkit-autofill,
#g5-panels .g5-field input:-webkit-autofill:hover,
#g5-panels .g5-field input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--g5-ink);
  -webkit-background-clip:text;
          background-clip:text;
  transition:background-color 600000s 0s linear;
}


/* ══ 2 · THE REVEAL ════════════════════════════════════════════════════════
   The emoji goes. `.eyehot` keeps its wiring (login2.js only toggles `.shown`
   and aria-pressed on it, never its text) and becomes a small iron stud whose
   glyph actually changes with the state it reports. */
#g5-panels .g5-field .eyehot{
  display:flex; align-items:center; justify-content:center;
  width:28px; height:28px; padding:0;
  border-radius:var(--g5-r-sm);
  font-size:0;                      /* retires the emoji; aria-label carries it */
  opacity:1 !important;
  /* the bevel is the IMAGE and the tint is the COLOUR underneath it, because a
     gradient cannot be transitioned and a colour can */
  background-color:transparent;
  background-image:linear-gradient(180deg, rgba(255,244,210,.05), rgba(0,0,0,.28));
  box-shadow:inset 0 1px 0 var(--c5-lip), inset 0 -1px 0 rgba(0,0,0,.5);
  transition:background-color var(--g5-t-fast) var(--g5-ease),
             transform        var(--g5-t-fast) var(--g5-ease) !important;
}
#g5-panels .g5-field .eyehot::before{
  content:''; display:block; width:17px; height:17px;
  background:var(--g5-ink-3);
  filter:drop-shadow(0 -1px 0 rgba(0,0,0,.85)) drop-shadow(0 1px 0 rgba(255,244,210,.14));
  transition:background-color var(--g5-t-fast) var(--g5-ease);
  -webkit-mask:var(--c5-eye) center / contain no-repeat;
          mask:var(--c5-eye) center / contain no-repeat;
}
:root{
  --c5-eye:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z'/></svg>");
  --c5-eye-off:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M12 6c3.79 0 7.17 2.13 8.82 5.5-.59 1.22-1.42 2.27-2.41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l1.65 1.65C10.66 6.09 11.32 6 12 6zm-1.07 1.14L13 9.21c.57.25 1.03.71 1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07C16.5 9.01 14.48 7 12 7c-.37 0-.72.05-1.07.14zM2.01 3.87l2.68 2.68C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.98-.29 4.32-.82l3.42 3.42 1.41-1.41L3.42 2.45 2.01 3.87zm7.5 7.5l2.61 2.61c-.04.01-.08.02-.12.02-1.38 0-2.5-1.12-2.5-2.5 0-.05.01-.08.01-.13zm-3.4-3.4l1.75 1.75c-.23.55-.36 1.15-.36 1.78 0 2.48 2.02 4.5 4.5 4.5.63 0 1.23-.13 1.77-.36l.98.98c-.88.24-1.8.38-2.75.38-3.79 0-7.17-2.13-8.82-5.5.7-1.43 1.72-2.61 2.93-3.53z'/></svg>");
}
#g5-panels .g5-field .eyehot.shown::before{
  -webkit-mask-image:var(--c5-eye-off);
          mask-image:var(--c5-eye-off);
  background:var(--g5-gold-3);
}
#g5-panels .g5-field .eyehot:hover{ background-color:var(--c5-gold-a20); }
#g5-panels .g5-field .eyehot:hover::before{ background:var(--g5-gold-2); }
#g5-panels .g5-field .eyehot:active{ transform:translateY(1px) scale(.94); }
#g5-panels .g5-field .eyehot:focus-visible{
  outline:2px solid var(--g5-gold-2); outline-offset:2px;
  border-radius:var(--g5-r-sm);
}


/* ══ 3 · THE ROW — remember-me stud, forgot link ═══════════════════════════ */
#g5-panels .g5-row{
  color:var(--g5-ink-3) !important;
  letter-spacing:.2px;
}

/* the stud: iron at rest, struck gold when set, with the tick ENGRAVED into
   the plate (dark glyph, warm 1px underneath) rather than sitting on it. */
#g5-panels .g5-check i{
  background:
    var(--c5-iron) center / 24px 24px repeat,
    linear-gradient(180deg, var(--g5-well), var(--c5-warm-floor)) !important;
  border:1px solid var(--c5-gold-a34) !important;
  border-radius:var(--g5-r-xs) !important;
  box-shadow:inset 0 2px 4px rgba(0,0,0,.75), inset 0 -1px 0 var(--c5-lip) !important;
  /* the plate swap is a STAMP — instant, on purpose. Only the rim and the
     press travel. */
  transition:border-color var(--g5-t-fast) var(--g5-ease),
             transform    var(--g5-t-fast) var(--g5-spring);
}
#g5-panels .g5-check:hover i{ border-color:var(--c5-gold-a55) !important; }
#g5-panels .g5-check:active i{ transform:scale(.9); }

#g5-panels .g5-check i::before{
  content:''; display:block; width:13px; height:13px;
  background:var(--g5-ink-on);
  filter:drop-shadow(0 1px 0 rgba(255,244,210,.5));
  opacity:0; transform:scale(.4) rotate(-16deg);
  transition:opacity var(--g5-t-fast) var(--g5-ease),
             transform var(--g5-t-base) var(--g5-spring);
  -webkit-mask:var(--c5-tick) center / contain no-repeat;
          mask:var(--c5-tick) center / contain no-repeat;
}
:root{
  --c5-tick:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M9.2 18.1 3.3 12.2l2.1-2.1 3.8 3.8L18.6 4.5l2.1 2.1z'/></svg>");
}
#g5-panels .g5-check input:checked + i{
  background:linear-gradient(180deg, var(--g5-gold-2), var(--g5-gold-3) 46%, var(--g5-gold-4)) !important;
  border-color:var(--g5-gold-2) !important;
  box-shadow:
    inset 0 1px 0 rgba(255,244,210,.7),
    inset 0 -2px 5px var(--c5-gold5-a55),
    0 0 12px -2px var(--c5-gold-a55) !important;
}
#g5-panels .g5-check input:checked + i::before{ opacity:1; transform:none; }
#g5-panels .g5-check input:focus-visible + i{
  outline:2px solid var(--g5-gold-2); outline-offset:3px;
}

/* the link: gold, with a hairline that wipes in under it instead of a border
   that pops on. */
#g5-panels .g5-link{
  position:relative; display:inline-block;
  border-bottom:0;
  letter-spacing:.2px;
  transition:color var(--g5-t-fast) var(--g5-ease);
}
#g5-panels .g5-link::after{
  content:''; position:absolute; left:0; right:0; bottom:-3px; height:1px;
  background:linear-gradient(90deg, transparent, var(--g5-gold-2), transparent);
  transform:scaleX(0); transform-origin:0 50%;
  transition:transform var(--g5-t-base) var(--g5-ease);
}
#g5-panels .g5-link:hover::after,
#g5-panels .g5-link:focus-visible::after{ transform:none; }
#g5-panels .g5-link:active{ transform:translateY(1px); }
#g5-panels .g5-link:focus-visible{
  outline:2px solid var(--g5-gold-2); outline-offset:3px;
  border-radius:var(--g5-r-xs);
}


/* ══ 4 · THE CTA — the most important pixel on the page ════════════════════
   The plate art and its pewter fleur-de-lis frame are already right, so this
   pass is entirely about MOVEMENT: catching the key light on approach, sinking
   under the lip on press, and reporting work honestly while it waits on the
   server. `::before` belongs to login5-imperial (the sweep) — `::after` here
   is the light, the press wash and the progress scan, one at a time. */
#g5-panels .g5-cta{
  position:relative;
  /* the wash and the busy scan live inside the plate, never over the pewter
     frame. login5-imperial already sets this; declared here so the pseudo
     below cannot spill if that sheet is ever pulled. */
  overflow:hidden;
  transition:
    transform var(--g5-t-fast) var(--g5-ease),
    filter    var(--g5-t-fast) linear !important;
}
#g5-panels .g5-cta::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  /* the same upper-left key the rest of the gate is lit by */
  background:radial-gradient(ellipse 72% 130% at 26% -12%,
    rgba(255,248,225,.55), rgba(255,248,225,.14) 46%, transparent 66%);
  opacity:0;
  transition:opacity var(--g5-t-fast) linear;
}
#g5-panels .g5-cta:hover{ transform:translateY(-1px); }
#g5-panels .g5-cta:hover::after{ opacity:1; }

/* press: it goes DOWN, the top of the plate falls into the frame's shadow,
   the bottom picks up bounce, and the cast shadow tightens because the object
   is now touching the surface. */
#g5-panels .g5-cta:active{
  transform:translateY(2px) !important;
  filter:drop-shadow(0 2px 5px rgba(0,0,0,.72)) brightness(.93) !important;
}
#g5-panels .g5-cta:active::after{
  opacity:1;
  background:linear-gradient(180deg,
    rgba(0,0,0,.34) 0%, rgba(0,0,0,.1) 44%, rgba(255,244,210,.12) 100%);
  transition:none;
}
#g5-panels .g5-cta:focus-visible{
  outline:2px solid var(--g5-gold-1);
  outline-offset:3px;
}

/* disabled — the plate is still there, the light is not */
#g5-panels .g5-cta:disabled{
  cursor:not-allowed;
  filter:saturate(.35) brightness(.62) !important;
  transform:none !important;
}
#g5-panels .g5-cta:disabled::after{ opacity:0; }

/* BUSY — setBusy() swaps the label to "SIGNING IN…" and sets .is-busy. The
   button stops pretending to be pressable, the idle sweep stops, and one
   indeterminate scan runs across the plate: the page is talking to a server
   and this is the only element that can say so. */
#g5-panels .g5-cta.is-busy{
  cursor:progress;
  filter:saturate(.8) brightness(.9) !important;
  transform:none !important;
}
#g5-panels .g5-cta.is-busy::before{ animation:none; opacity:0; }
#g5-panels .g5-cta.is-busy::after{
  opacity:1;
  left:0; right:auto; width:42%;
  background:linear-gradient(90deg,
    transparent, rgba(255,248,225,.10) 24%, rgba(255,248,225,.6) 50%,
    rgba(255,248,225,.10) 76%, transparent);
  transition:none;
  animation:g5c-scan 1.1s var(--g5-ease-in-out) infinite;
}
@keyframes g5c-scan{
  from{ transform:translateX(-105%); }
  to  { transform:translateX(340%);  }
}


/* ══ 5 · VALIDATION + THE MESSAGE STRIP ════════════════════════════════════
   markInvalid() writes aria-invalid on the INPUT and focuses it, so the
   invalid state has to out-rank the focus state — `:has()` on the label gives
   it one more attribute of specificity than `:focus-within`, which is exactly
   the ordering we want. */
#g5-panels .g5-field:has(input[aria-invalid="true"]){
  border-color:var(--g5-err) !important;
  box-shadow:
    inset 0 3px 6px -1px var(--c5-sink),
    inset 0 14px 16px -14px rgba(0,0,0,.72),
    inset 0 0 22px -6px var(--c5-err-glow),
    0 0 0 1px var(--c5-err-line),
    0 0 20px -4px var(--c5-err-glow) !important;
  animation:g5c-shake .4s var(--g5-ease-in-out) 1;
}
#g5-panels .g5-field:has(input[aria-invalid="true"]) .gi{ color:var(--g5-err); }
#g5-panels .g5-field:has(input[aria-invalid="true"])::after{
  opacity:1; transform:none;
  background:linear-gradient(180deg,
    transparent 0%, var(--c5-err-glow) 52%, var(--c5-err-line) 86%, var(--g5-err) 100%);
}
@keyframes g5c-shake{
  10%,90%{ transform:translateX(-1.5px); }
  20%,80%{ transform:translateX(2.5px);  }
  30%,50%,70%{ transform:translateX(-3px); }
  40%,60%{ transform:translateX(3px);    }
}

/* The strip itself. Two separate questions, deliberately keyed off two
   separate hooks:
     · IS IT VISIBLE — `:empty`, not `.show`. setMsg() clears textContent, so
       empty is the truthful test, and it also covers the strips login2.js
       injects itself (`.mmsg.password-strength`, in the reset and claim
       dialogs) which carry text but are never given `.show`.
     · DOES IT WEAR THE PLATE — `.show`, which only a real RESULT gets. A live
       hint stays as plain type.
   The 18px floor is held either way so a panel does not jump when an answer
   lands under the button. */
.omsg, .mmsg{
  display:flex; align-items:center; justify-content:center;
  gap:var(--g5-s2);
  margin:var(--g5-s4) var(--g5-s3) 0;
  padding:0 var(--g5-s4);
  min-height:18px;
  border:1px solid transparent;
  border-radius:var(--g5-r-sm);
  font:var(--g5-t-label);
  letter-spacing:.2px;
  color:var(--g5-err);
  text-align:center;
  transition:opacity var(--g5-t-base) var(--g5-ease),
             transform var(--g5-t-base) var(--g5-ease);
}
.omsg:empty, .mmsg:empty{ opacity:0; transform:translateY(-3px); }
.omsg::before, .mmsg::before{
  content:''; display:none; flex:0 0 auto; width:15px; height:15px;
  background:currentColor;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.7));
  -webkit-mask:var(--c5-warn) center / contain no-repeat;
          mask:var(--c5-warn) center / contain no-repeat;
}
:root{
  --c5-warn:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z'/></svg>");
  --c5-good:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='white' d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z'/></svg>");
}
.omsg.show, .mmsg.show{
  padding:var(--g5-s3) var(--g5-s4);
  background:linear-gradient(180deg, var(--c5-err-wash), transparent);
  border-color:var(--c5-err-line);
  box-shadow:inset 0 1px 0 rgba(255,244,210,.07), 0 6px 16px -8px rgba(0,0,0,.8);
}
.omsg.show::before, .mmsg.show::before{ display:block; }
.omsg.ok, .mmsg.ok{ color:var(--g5-ok); }
.omsg.ok.show, .mmsg.ok.show{
  background:linear-gradient(180deg, var(--c5-ok-wash), transparent);
  border-color:var(--c5-ok-line);
}
.omsg.ok::before, .mmsg.ok::before{
  -webkit-mask-image:var(--c5-good);
          mask-image:var(--c5-good);
}


/* ══ 6 · THE SOCIAL COINS ══════════════════════════════════════════════════
   These were three emoji in circles. They are now struck coins made of the
   game's OWN button art — `btn_rnd.png` under `btn_rnd_fr.png`, the round
   members of the same pewter family the CTA's frame comes from — so the row
   at the foot of the panel belongs to the button above it.

   The mark itself is a mask filled with gold and engraved, which keeps the
   row monochrome and calm at rest. On hover / keyboard focus the real brand
   colour blooms in underneath (opacity only). Those hex values are the one
   place in this file that is not a token, and they cannot be: a brand mark's
   colour is defined by its owner, not by AON's palette. */
#g5-panels .g5-socrow .sochot{
  position:relative;
  background:
    url("/client/assets/royal/btn_rnd_fr.png") center / 100% 100% no-repeat,
    /* the painted disc is warm bronze and the panels are cold navy — a wash of
       night over it, under the pewter ring, brings the coin into the room
       without giving up the ring's real bevel */
    radial-gradient(circle at 34% 28%,
      color-mix(in srgb, var(--g5-iron-1) 60%, transparent),
      color-mix(in srgb, var(--g5-night)  82%, transparent) 76%),
    url("/client/assets/royal/btn_rnd.png")    center / 100% 100% no-repeat !important;
  border:0 !important;
  box-shadow:0 6px 16px -6px rgba(0,0,0,.75) !important;
  /* transform only: the brand bloom below is what carries hover, so there is
     no filter to repaint over the live scene */
  transition:transform var(--g5-t-base) var(--g5-spring) !important;
}
#g5-panels .g5-socrow .sochot::before,
#g5-panels .g5-socrow .sochot::after{
  content:''; position:absolute; left:50%; top:50%; right:auto; bottom:auto;
  width:44%; height:44%; margin:-22% 0 0 -22%;
  background:var(--g5-gold-3);
  -webkit-mask:center / contain no-repeat;
          mask:center / contain no-repeat;
}
#g5-panels .g5-socrow .sochot::before{
  filter:drop-shadow(0 -1px 0 rgba(0,0,0,.85)) drop-shadow(0 1px 0 rgba(255,244,210,.18));
  transition:opacity var(--g5-t-base) var(--g5-ease);
}
#g5-panels .g5-socrow .sochot::after{
  background:none;
  background-position:center; background-repeat:no-repeat; background-size:contain;
  -webkit-mask:none; mask:none;
  opacity:0;
  transition:opacity var(--g5-t-base) var(--g5-ease);
}
#g5-panels .g5-socrow .sochot:hover::after,
#g5-panels .g5-socrow .sochot:focus-visible::after{ opacity:1; }
#g5-panels .g5-socrow .sochot:hover::before,
#g5-panels .g5-socrow .sochot:focus-visible::before{ opacity:0; }

#g5-panels .g5-socrow .sochot:hover{ transform:translateY(-3px); }
#g5-panels .g5-socrow .sochot:active{ transform:translateY(1px) scale(.96); }
#g5-panels .g5-socrow .sochot:focus-visible{
  outline:2px solid var(--g5-gold-2); outline-offset:3px;
}

/* Google — the four-arc G, union-masked for the gold rest state, true
   four-colour for the bloom. */
#g5-panels .g5-socrow .sochot[data-p="google"]::before{
  -webkit-mask-image:var(--c5-m-google); mask-image:var(--c5-m-google);
}
#g5-panels .g5-socrow .sochot[data-p="google"]::after{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='%234285F4' d='M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z'/><path fill='%2334A853' d='M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z'/><path fill='%23FBBC05' d='M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z'/><path fill='%23EA4335' d='M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z'/></svg>");
}
#g5-panels .g5-socrow .sochot[data-p="facebook"]::before{
  -webkit-mask-image:var(--c5-m-fb); mask-image:var(--c5-m-fb);
}
#g5-panels .g5-socrow .sochot[data-p="facebook"]::after{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='%231877F2' d='M14 13.5h2.5l1-4H14v-2c0-1.03 0-2 2-2h1.5V2.14C17.17 2.09 16.02 2 14.79 2 12.06 2 10 3.72 10 7.05V9.5H7.5v4H10V22h4v-8.5z'/></svg>");
}
#g5-panels .g5-socrow .sochot[data-p="steam"]::before{
  -webkit-mask-image:var(--c5-m-steam); mask-image:var(--c5-m-steam);
}
#g5-panels .g5-socrow .sochot[data-p="steam"]::after{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='%23c7d5e0' d='M12 2a10 10 0 0 0-10 9.3l5.4 2.2a2.7 2.7 0 0 1 1.5-.4l2.4-3.5v-.2a3.4 3.4 0 1 1 3.4 3.4h-.1l-3.4 2.5a2.7 2.7 0 0 1-5.3.7L2.3 14A10 10 0 1 0 12 2zm-3.7 13.5-2.3-.9a2.7 2.7 0 0 0 5.1.7l.1-.3-2.9.5zm8.1-5.2a2.1 2.1 0 1 0-2.1 2.1 2.1 2.1 0 0 0 2.1-2.1zm-3.6 0a1.5 1.5 0 1 1 1.5 1.5 1.5 1.5 0 0 1-1.5-1.5z'/></svg>");
}
:root{
  --c5-m-google:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z'/><path d='M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z'/><path d='M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z'/><path d='M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z'/></svg>");
  --c5-m-fb:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M14 13.5h2.5l1-4H14v-2c0-1.03 0-2 2-2h1.5V2.14C17.17 2.09 16.02 2 14.79 2 12.06 2 10 3.72 10 7.05V9.5H7.5v4H10V22h4v-8.5z'/></svg>");
  --c5-m-steam:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M12 2a10 10 0 0 0-10 9.3l5.4 2.2a2.7 2.7 0 0 1 1.5-.4l2.4-3.5v-.2a3.4 3.4 0 1 1 3.4 3.4h-.1l-3.4 2.5a2.7 2.7 0 0 1-5.3.7L2.3 14A10 10 0 1 0 12 2zm-3.7 13.5-2.3-.9a2.7 2.7 0 0 0 5.1.7l.1-.3-2.9.5zm8.1-5.2a2.1 2.1 0 1 0-2.1 2.1 2.1 2.1 0 0 0 2.1-2.1zm-3.6 0a1.5 1.5 0 1 1 1.5 1.5 1.5 1.5 0 0 1-1.5-1.5z'/></svg>");
}

/* the OR between the two rules reads as engraved caps, not as a label */
#g5-panels .g5-socrow .g5-or{
  color:var(--g5-ink-3) !important;
  letter-spacing:var(--g5-track-2) !important;
  text-shadow:0 1px 0 rgba(0,0,0,.8);
}

/* ── #gsi-desktop — Google's OWN widget renders in here when a client id is
   configured, and only their widget can mint a credential. So: no transform,
   no filter, no overflow, no display, nothing that reaches inside. A seat of
   warm light under it and a centring rule for the block Google switches it to,
   and that is the whole intervention. */
#gsi-desktop{
  position:relative;
  padding:var(--g5-s2) 0 var(--g5-s1);
  text-align:center;
  background:radial-gradient(ellipse 70px 34px at 50% 48%, var(--c5-gold-a08), transparent 72%);
}
/* login2.js writes `display:block` INLINE on this element the moment Google is
   configured, which quietly retires login5.css's `justify-content:center` and
   leaves the widget hard against the left edge of the panel. Centring is
   restored the only way that does not touch what Google renders: text-align
   for an inline widget, auto inline-margins for a block one, two levels deep
   because their wrapper is full-width and the sized node is its child. */
#gsi-desktop > div,
#gsi-desktop > div > div{ margin-left:auto; margin-right:auto; }
/* login2.js flags the container while it is exchanging the credential (and
   already kills its pointer-events) — say so instead of looking dead. */
#gsi-desktop[aria-busy="true"]{ opacity:.6; cursor:progress; }


/* ══ 7 · MOTION BUDGET ═════════════════════════════════════════════════════
   The transitions above are all keyed off --g5-t-*, which tokens.css already
   collapses under prefers-reduced-motion. The two raw @keyframes need their
   own guard — and the busy scan must not simply vanish, or a player who has
   asked for less motion loses the only signal that the form is working. It
   becomes a steady lit plate instead. */
@media (prefers-reduced-motion:reduce){
  #g5-panels .g5-field:has(input[aria-invalid="true"]){ animation:none; }
  #g5-panels .g5-cta.is-busy::after{
    animation:none;
    left:0; right:0; width:auto;
    background:linear-gradient(180deg, rgba(255,248,225,.16), transparent);
  }
  #g5-panels .g5-cta:hover,
  #g5-panels .g5-socrow .sochot:hover{ transform:none; }
}


/* ══ 8 · NARROW ════════════════════════════════════════════════════════════
   Between the desktop stage and the #mob column there is a band where these
   very controls are what a tablet gets. Keep the touch targets honest there.  */
@media (max-width:1024px){
  #g5-panels .g5-field input{ font-size:16px !important; }
  #g5-panels .g5-field .eyehot{ width:32px; height:32px; }
  #g5-panels .g5-socrow .sochot{ width:48px !important; height:48px !important; }
}

/* ══ gate5 · parts/06-nations.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 06 — THE NATION GALLERY  (the actual registration flow)
   ───────────────────────────────────────────────────────────────────────────
   There is no signup form on this page. The player clicks a nation and
   `quick_signup` founds an empire. So these 49 rectangles ARE the front door,
   and they should read as a WAR ROOM'S WALL OF BANNERS, not a list of flags.

   THE TILE IS A BANNER
     · a brass rod across the top, the cloth hanging 3px inside it
     · the flag IS the cloth — full-bleed, `object-fit:cover`, with a scrim
       poured over the lower half so the name and the perk sit on darkness
     · the hem is forked (clip-path swallowtail) and carries the nation's own
       colour, handed in by 06-nations.js as `--ng-c`
     · the whole silhouette casts one drop-shadow, so the tail throws a shadow
       too and the thing reads as cloth on a wall

   THE PERK IS THE PRODUCT
     `+15% cavalry charge damage` is the reason to pick France over England.
     It was 9px grey and ellipsised. It is now an engraved inscription plaque
     at the banner's foot, two lines allowed, the NUMBER split out in hot gold
     by 06-nations.js (and still fine if that script never runs).

   NOTES FOR WHOEVER TOUCHES THIS NEXT
     · index.php loads login5-imperial.css and login5-aoe.css AFTER the gate5
       aggregator, and both hit .ng-tile/.ng-flag/.nname/.nperk with
       `!important`. Everything here is therefore scoped under the grid id —
       (1,1,0) beats their (0,2,1) among important declarations — and marked
       important where it must win. That is the only reason for the noise.
     · NEVER `display:…!important` on .ng-tile or the grids: login2.js toggles
       state on them and an author important would beat its inline style.
     · 49 tiles. Nothing here is continuous: every animation is hover-only,
       :focus-visible, or the one-shot founding moment. Ambient costs 49×.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the wall ─────────────────────────────────────────────────────────────
   `html #…` and not `#…`: login5-imperial.css hits #nation-grid with its own
   important gap/padding/mask at the SAME specificity and loads later, so a
   bare id here silently loses. One extra type selector settles it.        ── */
html #nation-grid, html #m-nation-grid{
  /* per-nation colour; 06-nations.js overwrites this on every tile */
  --ng-c: var(--g5-gold-4);
  --ng-tail: 13px;     /* depth of the forked hem                            */
  --ng-hem: 18px;      /* the coloured hem the fork is cut out of            */
  --ng-rod: 5px;       /* the brass rod                                      */
  --ng-hang: 7px;      /* where the cloth starts under it                    */
  --ng-band: 44px;     /* clear flag above the scrim = where the name starts */

  gap: 10px var(--g5-s3) !important;
  /* NO padding-top: the region lintels stick to the scrollport's top edge and
     anything in a top padding would slide out from under them */
  padding: 0 var(--g5-s4) var(--g5-s5) !important;
  align-content: start;
  overscroll-behavior: contain;
  /* the sticky region lintels must not cover a tile the arrow keys focus */
  scroll-padding: 34px 0 20px;
}

html #nation-grid{
  /* the base leaves ~40px of dead panel under the terms line; spend it on a
     fourth row of banners and on a deliberately half-cut row at the fold —
     a clipped row is the strongest "there is more below" there is */
  max-height: min(404px, 43vh) !important;
  -webkit-mask-image: linear-gradient(180deg, black 0, black calc(100% - 34px), transparent 100%) !important;
          mask-image: linear-gradient(180deg, black 0, black calc(100% - 34px), transparent 100%) !important;
}
@media (max-height: 820px){
  html #nation-grid{ max-height: min(310px, 35vh) !important; }
}

/* the scroll rail — a sunk groove with a brass thumb, not a browser scrollbar */
#nation-grid, #m-nation-grid{
  scrollbar-width: thin;
  scrollbar-color: var(--g5-gold-4) rgba(0,0,0,.5);
}
#nation-grid::-webkit-scrollbar, #m-nation-grid::-webkit-scrollbar{ width: 10px; }
#nation-grid::-webkit-scrollbar-track, #m-nation-grid::-webkit-scrollbar-track{
  background: var(--g5-sunk);
  border-radius: var(--g5-r-pill);
  box-shadow: inset 0 0 0 1px rgba(232,192,94,.14), inset 0 2px 5px rgba(0,0,0,.7);
  margin: 2px 0 6px;
}
#nation-grid::-webkit-scrollbar-thumb, #m-nation-grid::-webkit-scrollbar-thumb{
  background:
    linear-gradient(90deg, rgba(0,0,0,.35), transparent 40%, rgba(255,244,210,.35) 52%, transparent 66%),
    linear-gradient(180deg, var(--g5-gold-2), var(--g5-gold-3) 46%, var(--g5-gold-5));
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: var(--g5-r-pill);
}
#nation-grid::-webkit-scrollbar-thumb:hover, #m-nation-grid::-webkit-scrollbar-thumb:hover{
  background:
    linear-gradient(90deg, rgba(0,0,0,.3), transparent 40%, rgba(255,244,210,.55) 52%, transparent 66%),
    linear-gradient(180deg, var(--g5-gold-1), var(--g5-gold-2) 46%, var(--g5-gold-4));
}

/* ── region lintel — an engraved stone course spanning the wall. It sticks,
      so you always know which quarter of the world you are looking at. ───── */
#nation-grid > .ng-region, #m-nation-grid > .ng-region{
  grid-column: 1 / -1;
  position: sticky; top: 0; z-index: 4;
  margin: 0 0 var(--g5-s1) !important;
  padding: 7px 10px 7px 2px;
  display: flex; align-items: center; gap: var(--g5-s3);
  font: 700 9.5px/1 var(--g5-f-display) !important;
  letter-spacing: var(--g5-track-2) !important;
  color: var(--g5-gold-3) !important;
  text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(0,0,0,.95), 0 0 14px rgba(232,192,94,.22);
  /* opaque all the way down — banners scroll UNDER this course, and a fade
     at its foot lets their colour bleed through the stone */
  background: var(--g5-iron-3);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--g5-gold-5) 18%, var(--g5-night)) 0%,
      color-mix(in srgb, var(--g5-gold-5) 9%,  var(--g5-night)) 100%);
  box-shadow:
    inset 0 1px 0 rgba(232,192,94,.18),
    0 1px 0 rgba(232,192,94,.22),
    0 4px 10px rgba(0,0,0,.6);
}
/* the engraved rule that runs off to the edge of the wall */
#nation-grid > .ng-region::after, #m-nation-grid > .ng-region::after{
  content: ''; flex: 1; height: 2px !important;
  background:
    linear-gradient(90deg, var(--g5-gold-4), rgba(232,192,94,.14) 62%, transparent) !important;
  box-shadow: 0 1px 0 rgba(0,0,0,.8);
}
/* a lozenge stud, the way a real course is pegged */
#nation-grid > .ng-region::before, #m-nation-grid > .ng-region::before{
  content: ''; width: 6px; height: 6px; flex: none;
  background: linear-gradient(135deg, var(--g5-gold-2), var(--g5-gold-5));
  transform: rotate(45deg);
  box-shadow: 0 0 0 1px rgba(0,0,0,.6), 0 0 8px rgba(232,192,94,.4);
}

/* ══ THE BANNER ═══════════════════════════════════════════════════════════ */
#nation-grid .ng-tile, #m-nation-grid .ng-tile{
  position: relative;
  box-sizing: border-box;
  padding: calc(var(--ng-hang) + var(--ng-band)) 7px calc(var(--ng-hem) + 3px) !important;
  gap: 3px;
  text-align: center;
  background: none !important;
  border: 0 !important;
  border-image: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  /* one shadow for the whole silhouette — the forked hem throws it too */
  filter: drop-shadow(0 5px 6px rgba(0,0,0,.6));
  transition:
    transform var(--g5-t-base) var(--g5-ease),
    filter    var(--g5-t-base) var(--g5-ease),
    opacity   var(--g5-t-slow) var(--g5-ease) !important;
}

/* the ring that fires once when the empire is founded (see FOUNDING below) */
#nation-grid .ng-tile::before, #m-nation-grid .ng-tile::before{
  content: ''; position: absolute; inset: var(--ng-hang) 3px 0;
  border: 1px solid var(--g5-gold-1);
  opacity: 0; pointer-events: none;
}

/* the rod. Wider than the cloth, so the banner visibly HANGS from it. */
#nation-grid .ng-tile::after, #m-nation-grid .ng-tile::after{
  content: ''; position: absolute; left: 0; right: 0; top: 1px;
  height: var(--ng-rod); border-radius: var(--g5-r-pill);
  background:
    linear-gradient(90deg, var(--g5-gold-5) 0 3px, transparent 3px calc(100% - 3px), var(--g5-gold-5) calc(100% - 3px)),
    linear-gradient(180deg, var(--g5-gold-1) 0, var(--g5-gold-3) 40%, var(--g5-gold-5) 100%);
  box-shadow: 0 1px 2px rgba(0,0,0,.85);
  pointer-events: none;
  transition: filter var(--g5-t-base) var(--g5-ease);
}

/* ── the cloth. .ng-flag stops being a 58×38 stamp and becomes the banner. ── */
#nation-grid .ng-flag, #m-nation-grid .ng-flag{
  position: absolute;
  inset: var(--ng-hang) 3px 0 3px;
  width: auto !important; height: auto !important;
  border: 0 !important;
  border-radius: 0 !important;
  overflow: hidden;
  /* the nation's own colour is the cloth under the flag — it is ALL you see
     on the fallback path, and it tints the hem on both paths. Plain gradient
     first, color-mix second: no browser is left with a black rag. */
  background: linear-gradient(178deg, var(--ng-c) 0%, var(--g5-iron-3) 88%);
  background:
    linear-gradient(178deg,
      color-mix(in srgb, var(--ng-c) 78%, var(--g5-night)) 0%,
      color-mix(in srgb, var(--ng-c) 42%, var(--g5-night)) 46%,
      var(--g5-iron-3) 100%);
  box-shadow: inset 0 0 0 1px rgba(232,192,94,.30) !important;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% calc(100% - var(--ng-tail)), 0 100%);
}
#nation-grid .ng-flag img, #m-nation-grid .ng-flag img{
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 45%;
  box-shadow: none !important;
  border-radius: 0 !important;
}

/* Scrim + cloth folds + hem colour — one element, one paint, always on.
   Deliberately NO color-mix() in this stack: if it were unsupported the whole
   `background` would be dropped and every nation name would land on a bare
   flag. The hem is shaded with a plain black band instead.               ── */
#nation-grid .ng-flag::before, #m-nation-grid .ng-flag::before{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    /* the stitched hem line, sitting on top of the coloured band */
    linear-gradient(0deg,
      transparent 0 calc(var(--ng-hem) - 1px),
      rgba(232,192,94,.5) calc(var(--ng-hem) - 1px) var(--ng-hem),
      transparent var(--ng-hem)),
    /* the cloth thickens where it is doubled over at the hem */
    linear-gradient(0deg,
      rgba(0,0,0,.34) 0 calc(var(--ng-hem) - 7px),
      rgba(0,0,0,.06) calc(var(--ng-hem) - 7px) var(--ng-hem),
      transparent var(--ng-hem)),
    /* the hem takes the nation's own colour. The fork is cut OUT of this, so
       the notch reads as cloth instead of as a scratch in the dark. */
    linear-gradient(0deg,
      var(--ng-c) 0 calc(var(--ng-hem) - 1px),
      transparent var(--ng-hem)),
    /* Text scrim. The stops are PIXELS off the top of the cloth, not
       percentages: tiles are not all the same height (a two-line nation name
       makes its row taller) and a % ramp drops the name onto bare flag —
       "REPUBLIC OF VENICE" landed on the Italian white. --ng-band is where
       the name starts, so the cloth must already be night by then. */
    linear-gradient(180deg,
      rgba(7,10,13,0)   0,
      rgba(7,10,13,0)   calc(var(--ng-band) - 15px),
      rgba(7,10,13,.55) calc(var(--ng-band) - 5px),
      rgba(7,10,13,.90) calc(var(--ng-band) + 4px),
      rgba(7,10,13,.96) calc(var(--ng-band) + 20px),
      rgba(7,10,13,.97) 100%),
    /* folds */
    repeating-linear-gradient(90deg,
      rgba(0,0,0,.10) 0 1px, transparent 1px 18px),
    /* the cloth curls away at both edges */
    linear-gradient(90deg,
      rgba(0,0,0,.26) 0%, transparent 12%, transparent 88%, rgba(0,0,0,.3) 100%),
    /* warm unifying wash — 49 different flags, one wall */
    linear-gradient(180deg, rgba(109,79,28,.10), rgba(109,79,28,.05));
  box-shadow: inset 0 3px 7px rgba(0,0,0,.8);
}

/* the light a banner catches when you pick it up — hover only, transform only */
#nation-grid .ng-flag::after, #m-nation-grid .ng-flag::after{
  content: ''; position: absolute; top: -12%; bottom: -12%; left: 0; width: 38%;
  pointer-events: none;
  background: linear-gradient(100deg,
    transparent, rgba(255,244,210,.30) 42%, rgba(255,244,210,.46) 55%, transparent);
  transform: translateX(-170%) skewX(-13deg);
  transition: transform .62s var(--g5-ease);
}

/* the emoji / country-code fallback (flagcdn is blocked by many privacy
   filters, and Windows never renders regional-indicator flags at all — so
   this path shows "FR" and it has to look like a device on a banner) */
#nation-grid .ng-flag-fallback, #m-nation-grid .ng-flag-fallback{
  inset: 0 0 auto 0; height: var(--ng-band);
  align-items: center; justify-content: center;
  font-family: var(--g5-f-display);
  font-weight: 700; font-size: 22px; line-height: 1;
  letter-spacing: .04em;
  color: var(--g5-gold-1);
  text-shadow: 0 1px 0 rgba(0,0,0,.85), 0 0 16px rgba(0,0,0,.6);
}

/* ── the inscription ─────────────────────────────────────────────────────── */
#nation-grid .ng-tile .nname, #m-nation-grid .ng-tile .nname{
  position: relative; z-index: 1;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  max-width: 100%; white-space: normal !important; text-overflow: clip;
  font-family: var(--g5-f-display) !important;
  font-weight: 700 !important;
  font-size: 10.5px !important;
  line-height: 1.1;
  letter-spacing: .01em !important;
  color: var(--g5-ink) !important;
  text-shadow: 0 1px 0 rgba(0,0,0,.9), 0 2px 8px rgba(0,0,0,.8) !important;
  transition: color var(--g5-t-fast) var(--g5-ease);
}

/* THE PERK — the reason to pick this banner over the next one. */
#nation-grid .ng-tile .nperk, #m-nation-grid .ng-tile .nperk{
  position: relative; z-index: 1;
  align-self: stretch;
  margin-top: auto;                     /* pinned to the hem, rows stay level */
  padding: 3px 5px;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  max-width: 100%; white-space: normal !important; text-overflow: clip;
  font: 600 9.5px/1.3 var(--g5-f-ui) !important;
  letter-spacing: .01em;
  color: var(--g5-ink-2) !important;
  background: linear-gradient(180deg, rgba(5,7,10,.62), rgba(5,7,10,.86));
  border-radius: var(--g5-r-xs);
  box-shadow:
    inset 0 1px 0 rgba(232,192,94,.26),
    inset 0 0 0 1px rgba(232,192,94,.10),
    0 1px 2px rgba(0,0,0,.6);
  transition: color var(--g5-t-fast) var(--g5-ease),
              box-shadow var(--g5-t-fast) var(--g5-ease);
}
/* 06-nations.js splits the leading number out; without it the line still reads */
#nation-grid .ng-tile .nperk b, #m-nation-grid .ng-tile .nperk b{
  font-weight: 700;
  color: var(--g5-gold-2);
  letter-spacing: .02em;
  text-shadow: 0 0 10px rgba(232,192,94,.35);
}

/* ══ PICKING ONE UP ═══════════════════════════════════════════════════════ */
#nation-grid .ng-tile:hover, #m-nation-grid .ng-tile:hover,
#nation-grid .ng-tile:focus-visible, #m-nation-grid .ng-tile:focus-visible{
  transform: translateY(-5px) !important;
  filter:
    drop-shadow(0 12px 12px rgba(0,0,0,.68))
    drop-shadow(0 0 13px rgba(232,192,94,.45)) !important;
}
#nation-grid .ng-tile:hover .ng-flag::after,
#m-nation-grid .ng-tile:hover .ng-flag::after,
#nation-grid .ng-tile:focus-visible .ng-flag::after,
#m-nation-grid .ng-tile:focus-visible .ng-flag::after{
  transform: translateX(420%) skewX(-13deg);
}
#nation-grid .ng-tile:hover .ng-flag,
#m-nation-grid .ng-tile:hover .ng-flag,
#nation-grid .ng-tile:focus-visible .ng-flag,
#m-nation-grid .ng-tile:focus-visible .ng-flag{
  box-shadow: inset 0 0 0 1px var(--g5-line-2) !important;
}
#nation-grid .ng-tile:hover .nname, #m-nation-grid .ng-tile:hover .nname,
#nation-grid .ng-tile:focus-visible .nname, #m-nation-grid .ng-tile:focus-visible .nname{
  color: var(--g5-gold-1) !important;
}
#nation-grid .ng-tile:hover .nperk, #m-nation-grid .ng-tile:hover .nperk,
#nation-grid .ng-tile:focus-visible .nperk, #m-nation-grid .ng-tile:focus-visible .nperk{
  color: var(--g5-ink) !important;
  box-shadow:
    inset 0 1px 0 rgba(255,233,168,.5),
    inset 0 0 0 1px rgba(232,192,94,.3),
    0 1px 2px rgba(0,0,0,.6);
}
#nation-grid .ng-tile:active, #m-nation-grid .ng-tile:active{
  transform: translateY(-1px) !important;
}

/* keyboard. The grid has arrow-key roving focus — this has to be unmissable.
   The tile box is NOT clipped (only the cloth is), so a real outline works. */
#nation-grid .ng-tile:focus-visible, #m-nation-grid .ng-tile:focus-visible{
  outline: 2px solid var(--g5-gold-2) !important;
  outline-offset: 3px !important;
}
@media (forced-colors: active){
  #nation-grid .ng-tile:focus-visible, #m-nation-grid .ng-tile:focus-visible{
    outline: 3px solid Highlight !important;
  }
}

/* ── CHOSEN ──────────────────────────────────────────────────────────────── */
#nation-grid .ng-tile.sel, #m-nation-grid .ng-tile.sel{
  transform: translateY(-5px) scale(1.03) !important;
  opacity: 1 !important;
  z-index: 3;
  filter:
    drop-shadow(0 14px 14px rgba(0,0,0,.7))
    drop-shadow(0 0 20px rgba(255,214,120,.6)) !important;
}
#nation-grid .ng-tile.sel .ng-flag, #m-nation-grid .ng-tile.sel .ng-flag{
  box-shadow: inset 0 0 0 2px var(--g5-gold-2) !important;
}
#nation-grid .ng-tile.sel .nname, #m-nation-grid .ng-tile.sel .nname{
  color: var(--g5-gold-1) !important;
}
#nation-grid .ng-tile.sel .nperk, #m-nation-grid .ng-tile.sel .nperk{
  color: var(--g5-ink) !important;
}
#nation-grid .ng-tile.sel::after, #m-nation-grid .ng-tile.sel::after{
  filter: brightness(1.35);
}

/* ── not available ───────────────────────────────────────────────────────── */
#nation-grid .ng-tile[disabled], #m-nation-grid .ng-tile[disabled]{
  cursor: default;
}

/* ══ THE FOUNDING MOMENT ══════════════════════════════════════════════════
   login2.js: .sel on the chosen tile, `.locked` + aria-busy on the grid,
   #ng-cap swaps to "FOUNDING YOUR EMPIRE…". Until now that was invisible.
   The wall goes dark, ONE banner stays lit, a ring breaks out of it and the
   caption catches fire. One-shot, on one element — 49× nothing.           ── */
#nation-grid.locked, #m-nation-grid.locked,
#nation-grid[aria-busy="true"], #m-nation-grid[aria-busy="true"]{
  opacity: 1 !important;
  pointer-events: none;
}
#nation-grid.locked .ng-tile:not(.sel), #m-nation-grid.locked .ng-tile:not(.sel),
#nation-grid[aria-busy="true"] .ng-tile:not(.sel),
#m-nation-grid[aria-busy="true"] .ng-tile:not(.sel){
  opacity: .14 !important;
  transform: translateY(4px) scale(.97) !important;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.5)) !important;
}
#nation-grid.locked > .ng-region, #m-nation-grid.locked > .ng-region,
#nation-grid[aria-busy="true"] > .ng-region, #m-nation-grid[aria-busy="true"] > .ng-region{
  opacity: .22;
  transition: opacity var(--g5-t-slow) var(--g5-ease);
}
#nation-grid.locked .ng-tile.sel::before, #m-nation-grid.locked .ng-tile.sel::before,
#nation-grid[aria-busy="true"] .ng-tile.sel::before,
#m-nation-grid[aria-busy="true"] .ng-tile.sel::before{
  animation: g6ngFound .95s var(--g5-ease) 1 both;
}
@keyframes g6ngFound{
  0%   { opacity: 0;   transform: scale(.86); }
  22%  { opacity: .95; }
  100% { opacity: 0;   transform: scale(1.5); }
}

/* The caption ignites. Scoped to the busy state ONLY, so the panel's own
   typography pass owns #ng-cap everywhere else. It is gold-leafed with
   `background-clip:text`, and on some skins that same background also paints
   its plaque — so this lights the glyphs through -webkit-text-fill-color and
   never touches background-image. */
body:has(#nation-grid.locked) #ng-cap,
body:has(#m-nation-grid.locked) #m-ng-cap{
  color: var(--g5-gold-1) !important;
  -webkit-text-fill-color: var(--g5-gold-1) !important;
  text-shadow: 0 2px 0 rgba(0,0,0,.6), 0 0 34px rgba(255,214,120,.7) !important;
}
body:has(#nation-grid.locked) #ng-sub,
body:has(#m-nation-grid.locked) #m-ng-sub{
  position: relative;
  color: var(--g5-gold-2) !important;
}
/* an indeterminate rule under the sub-line — "something is happening".
   ::before is the sunk track, ::after the runner, and the runner's travel is
   bounded to the track so it never wanders off into the panel. */
body:has(#nation-grid.locked) #ng-sub::before,
body:has(#m-nation-grid.locked) #m-ng-sub::before{
  content: ''; position: absolute; left: 34%; right: 34%; bottom: -6px;
  height: 2px; border-radius: var(--g5-r-pill);
  background: rgba(232,192,94,.30);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.5);
}
body:has(#nation-grid.locked) #ng-sub::after,
body:has(#m-nation-grid.locked) #m-ng-sub::after{
  content: ''; position: absolute; left: 34%; width: 9%; bottom: -6px;
  height: 2px; border-radius: var(--g5-r-pill);
  background: linear-gradient(90deg, transparent, var(--g5-gold-1), transparent);
  box-shadow: 0 0 8px rgba(255,214,120,.7);
  animation: g6ngPulse 1.15s var(--g5-ease-in-out) infinite alternate;
}
@keyframes g6ngPulse{
  from { transform: translateX(0); }
  to   { transform: translateX(255%); }
}

/* ── the terms line — a quiet engraved footnote, not a grey afterthought ─── */
.g5-panel .ng-tos, .mcard .m-ngtos{
  margin: var(--g5-s4) var(--g5-s5) 0 !important;
  font: 500 9.5px/1.55 var(--g5-f-ui) !important;
  letter-spacing: .04em !important;
  color: var(--g5-ink-4) !important;
  text-shadow: 0 1px 0 rgba(0,0,0,.7);
}

/* ══ MOBILE — the same wall, two banners across ═══════════════════════════ */
html #m-nation-grid{
  --ng-band: 46px;
  max-height: 380px;
  padding: 0 var(--g5-s3) var(--g5-s4) !important;
  -webkit-mask-image: linear-gradient(180deg, black 0, black calc(100% - 30px), transparent 100%);
          mask-image: linear-gradient(180deg, black 0, black calc(100% - 30px), transparent 100%);
}
#m-nation-grid .ng-tile{
  padding-bottom: 15px !important;
}
#m-nation-grid .ng-tile .nname{ font-size: 12px !important; }
#m-nation-grid .ng-tile .nperk{ font-size: 10px !important; }
#m-nation-grid .ng-flag-fallback{ font-size: 25px; }
/* phones have no hover and no WebGL scene to protect — but they do have 49
   tiles in one scroller, so the sweep never runs and the shadow stays cheap */
html.mob #m-nation-grid .ng-flag::after{ display: none; }
html.mob #m-nation-grid .ng-tile{
  filter: drop-shadow(0 3px 4px rgba(0,0,0,.6));
}

/* ══ REDUCED MOTION — the wall keeps its light, nothing travels ═══════════ */
@media (prefers-reduced-motion: reduce){
  #nation-grid .ng-flag::after, #m-nation-grid .ng-flag::after{ display: none; }
  #nation-grid .ng-tile.sel::before, #m-nation-grid .ng-tile.sel::before,
  #nation-grid.locked .ng-tile.sel::before, #m-nation-grid.locked .ng-tile.sel::before,
  #nation-grid[aria-busy="true"] .ng-tile.sel::before,
  #m-nation-grid[aria-busy="true"] .ng-tile.sel::before{
    animation: none !important;
    opacity: .9; transform: none;
  }
  body:has(#nation-grid.locked) #ng-sub::after,
  body:has(#m-nation-grid.locked) #m-ng-sub::after{
    animation: none !important;
    transform: none; left: 34%; width: 32%;
  }
  #nation-grid .ng-tile, #m-nation-grid .ng-tile{ transition: none !important; }
}

/* ══ gate5 · parts/07-motion.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PASS 07 — MOTION                 assets/login5/parts/07-motion.css
   ───────────────────────────────────────────────────────────────────────────
   This pass owns TIMING, not surface: only `animation`, `transition`,
   `transform` and `will-change`. No colour, no layout, no spacing, no type.

   It sets the motion that belongs to the PAGE rather than to any one control:

     · the arrival — the whole first second, choreographed
     · pointer parallax over the live 3D kingdom
     · the ambient loops that had to stop
     · the reduced-motion / mobile floor under everything

   It deliberately does NOT restate hover, press or state motion for the
   controls: passes 05 (fields + CTA + socials), 06 (nation wall), 08 (phone
   column), 09 (dialogs) and 10 (chrome) each own theirs, all of them keyed to
   the same `--g5-t-*` / `--g5-ease` tokens, which IS the shared language. An
   earlier draft of this file restated them and every rule was dead on arrival —
   measured, not assumed (tools/_gate5 probe).

   ── CASCADE MAP (read before editing) ─────────────────────────────────────
   index.php loads THREE stylesheets:

       1  gate5.css.php  → tokens.css + login5.css + parts/02,05,06,07,08,09,10
       2  login5-imperial.css        ← lands AFTER every part file
       3  login5-aoe.css             ← lands after that

   So parts/ is not last, and both late sheets use `!important` freely. Hence
   the `html ` prefix on nearly every selector here: a free +1 element
   specificity, which is enough to beat their un-`!important`ed id rules
   without an `!important` war. Where an `!important` does appear below it is
   beating a named declaration, never decoration.

   ── THE ARRIVAL ───────────────────────────────────────────────────────────
   Every duration AND every delay is a multiple of `--g5-ar` (= --g5-t-slow).
   One number retunes the whole title sequence, and the reduced-motion collapse
   in tokens.css flattens it to nothing for free.

       t+0.00  the poster settles      scale 1.055 → 1, 1.29s, behind everything
       t+0.06  the top rail drops in                              ends 0.59
       t+0.14  the hero establishes                               ends 0.75
       t+0.26  the login panel seats                              ends 0.87
       t+0.34  the register panel seats                           ends 0.95
       t+0.30  the hall banners drop                              ends 0.98
       t+0.44  the nation wall fills, 26ms/tile, index capped 10  ends 1.04
       t+0.52  the feature strip                                  ends 1.05
       ──────  07-motion.js then flips html.g5-done, which releases the fills
               and arms the parallax. First pointerdown/keydown/wheel/touch
               flips it early: the arrival is skippable by interaction.

   The `html:not(.g5-done)` gate is not a stylistic choice. Killing the arrival
   with `animation:none !important` also kills the `both` fill, and any element
   whose resting state came FROM that fill snaps back — that is exactly how the
   hall banners vanished at 1250ms in the first cut of this file. Gating on
   :not() lets the rule simply stop matching, and leaves the state animations
   pass 06 and 09 declare on the same elements completely alone.

   ── WHAT WAS CUT ──────────────────────────────────────────────────────────
   · g6titlePulse (#g5-hero .g5-title, 5.5s infinite) — an animated `filter`
     carrying five drop-shadows, on the largest text on the page, forever.
     The static filter is untouched; only the pulse is gone.
   · g6grain (#g6-grain, .35s steps(2) infinite) — a full-viewport
     mix-blend-mode:overlay layer re-composited ~6×/s over a live WebGL scene,
     carrying no information. The grain TEXTURE stays. (02-atmosphere reached
     the same verdict independently; both rules are kept, they agree.)
   · g6sweep (.g5-cta::before, .mbox .mbtn::before, .mbtn::before, 3.8s
     infinite ×5 nodes) — a login button that flashes forever pulls the eye off
     the form. Pass 05 replaced the CTA's with a hover wash and pass 09 replaced
     the dialog buttons' with a one-shot sheen; this file is what turns the old
     loop off underneath them.
   · imperial's `.g5-panel{transition:box-shadow .35s}` — a 450×600 plate
     repainting its 100px shadow every frame on hover, over the 3D.

   ── LEFT ALONE, ON PURPOSE ────────────────────────────────────────────────
   · #g5-poster's `transition:opacity 1.2s` — the 3D handoff cross-fade. NOT
     token-keyed: a dissolve is not vestibular motion and must survive
     prefers-reduced-motion. It is also why there is no `*{animation:none}`
     anywhere in this file.
   · g6crown (#g5-hero::before, 3.2s) — transform + opacity on a 14px glyph,
     one composited layer. Kept on desktop, cut ≤870px.
   · 02-atmosphere's rays / embers / motes / haze — all transform+opacity, all
     display:none ≤870px and on .mob, all paused while the tab is hidden.

   ── REPORTED, NOT FOUGHT ──────────────────────────────────────────────────
   Five transitions in other passes still list a property that repaints:
     05-controls.css:306  #g5-panels .g5-cta            filter
     05-controls.css:466  #g5-panels .sochot            filter
     06-nations.css:143   .ng-tile                      filter
     06-nations.css:163   .ng-flag                      filter
     06-nations.css:283   (link)                        box-shadow
     09-dialogs.css:145   modal input                   box-shadow
     09-dialogs.css:184   .mbox .mbtn                   box-shadow
     10-chrome.css:130    #g5-nav .nhot                 background
     10-chrome.css:331    .fcard                        box-shadow
     10-chrome.css:347    .fcard b                      filter
     10-chrome.css:438    #aon-dc-gate                  box-shadow
   All are hover/focus-only and short, so none of them loops — but each is a
   full-element repaint per frame while the WebGL scene renders behind it.
   They belong to their owners; this file does not overwrite them.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* the arrival's one knob — everything below is a multiple of it, so it
     inherits the tokens.css reduced-motion collapse */
  --g5-ar: var(--g5-t-slow);          /* 380ms */
  /* pointer parallax, [-1..1], written on <html> by 07-motion.js */
  --g5-mx: 0;
  --g5-my: 0;
}


/* ═══════════════════════════════════════════════════════════════════════════
   1 · THE ARRIVAL
   ═══════════════════════════════════════════════════════════════════════════ */

@keyframes g5-in{
  from{ opacity:0; transform:translate3d(0, var(--g5-in-y, 18px), 0) scale(var(--g5-in-s, 1)); }
  to  { opacity:1; transform:none; }
}
@keyframes g5-banner-in{
  from{ opacity:0; transform:translate3d(0,-26px,0) rotate(-1.4deg); }
  to  { opacity:.92; transform:none; }
}
@keyframes g5-poster-settle{
  from{ transform:scale(1.055); }
  to  { transform:none; }
}

/* ── retire the two arrivals that shipped before this pass ────────────────
      login5-imperial.css:897-901 (g6riseIn ×5). The :nth-child is not
      decoration: imperial owns the panels at (1,2,0), so a plain
      `html #g5-panels .g5-panel` at (1,1,1) would lose to it. ── */
html #g5-top,
html #g5-hero,
html #g5-feats{ animation:none; }
html #g5-panels .g5-panel:nth-child(1),
html #g5-panels .g5-panel:nth-child(2){ animation:none; }

/* ── the scene settles first. One composited layer, transform only: the camera
      arriving, reading THROUGH the poster→3D cross-fade rather than fighting
      it. No .g5-done gate — it blocks nothing and cutting it mid-flight would
      pop the entire backdrop. ── */
html #g5-poster{
  animation:g5-poster-settle calc(var(--g5-ar) * 3.4) var(--g5-ease) both;   /* 1292ms */
}

/* ── the rail comes DOWN from the top edge ── */
html:not(.g5-done) #g5-top{
  --g5-in-y:-14px;
  animation:g5-in calc(var(--g5-ar) * 1.4) calc(var(--g5-ar) * .16) var(--g5-ease) both;
}
/* ── the establishing beat: furthest travel, a touch of scale, longest curve ── */
html:not(.g5-done) #g5-hero{
  --g5-in-y:22px; --g5-in-s:.965;
  animation:g5-in calc(var(--g5-ar) * 1.6) calc(var(--g5-ar) * .37) var(--g5-ease) both;
}
/* ── the two panels SEAT — together, but not in unison ── */
html:not(.g5-done) #g5-panels .g5-panel:nth-child(1),
html:not(.g5-done) #g5-panels .g5-panel:nth-child(2){
  --g5-in-y:26px; --g5-in-s:.985;
  animation:g5-in calc(var(--g5-ar) * 1.6) calc(var(--g5-ar) * .68) var(--g5-ease) both;
}
html:not(.g5-done) #g5-panels .g5-panel:nth-child(2){
  animation-delay:calc(var(--g5-ar) * .90);
}
/* ── the hall banners drop from the lintel. NO .g5-done gate: their base rule
      in login5-aoe.css is opacity:0 and the fill IS their resting state, so
      dropping the animation would delete them off the page. ── */
html #g7-bnl, html #g7-bnr{
  animation:g5-banner-in calc(var(--g5-ar) * 1.8) calc(var(--g5-ar) * .79) var(--g5-ease) both;
}
/* ── the nation wall FILLS IN. 07-motion.js writes --g5-i (capped at 10) on
      each grid child, so the visible rows cascade and the ~40 below the scroll
      fold land together instead of dribbling in for three seconds. ── */
html:not(.g5-done) #nation-grid > *{
  --g5-in-y:10px; --g5-in-s:.96;
  animation:g5-in calc(var(--g5-ar) * .9) var(--g5-ease) both;
  animation-delay:calc(var(--g5-ar) * 1.16 + var(--g5-ar) * .068 * var(--g5-i, 0));
}
html:not(.g5-done) #g5-feats{
  --g5-in-y:16px;
  animation:g5-in calc(var(--g5-ar) * 1.4) calc(var(--g5-ar) * 1.37) var(--g5-ease) both;
}

/* ── the phone column is a different DOM (#mob) and never sees any of the
      above. One-shot only: nothing here repeats, so it does not breach the
      no-continuous-motion-on-mobile rule §4 enforces. ── */
html.mob:not(.g5-done) #mob .m-hero{
  --g5-in-y:16px;
  animation:g5-in calc(var(--g5-ar) * 1.4) calc(var(--g5-ar) * .16) var(--g5-ease) both;
}
html.mob:not(.g5-done) #mob .mcard.navy{
  --g5-in-y:20px; --g5-in-s:.985;
  animation:g5-in calc(var(--g5-ar) * 1.5) calc(var(--g5-ar) * .45) var(--g5-ease) both;
}
html.mob:not(.g5-done) #mob .mcard.red{
  --g5-in-y:20px; --g5-in-s:.985;
  animation:g5-in calc(var(--g5-ar) * 1.5) calc(var(--g5-ar) * .68) var(--g5-ease) both;
}
html.mob:not(.g5-done) #mob .m-feats{
  --g5-in-y:14px;
  animation:g5-in calc(var(--g5-ar) * 1.4) calc(var(--g5-ar) * .95) var(--g5-ease) both;
}


/* ═══════════════════════════════════════════════════════════════════════════
   2 · THE LOOPS THAT HAD TO STOP
   ═══════════════════════════════════════════════════════════════════════════ */

/* an animated `filter` with five drop-shadows, on the biggest text on the
   page, forever. (retires login5-imperial.css:220) */
html #g5-hero .g5-title{ animation:none; }

/* full-viewport mix-blend-mode:overlay layer, re-composited ~6×/s, over WebGL,
   carrying nothing. Texture kept, jitter gone. (retires login5-imperial.css:54) */
html #g6-grain{ animation:none; }

/* the button sweep stops being wallpaper. Pass 05 gives the CTA a hover wash
   and pass 09 gives the dialog buttons a one-shot sheen; these three lines are
   what switches the old 3.8s loop off underneath them, on all five nodes.
   (retires login5-imperial.css:531, :796, :878) */
html .g5-cta::before,
html .mbox .mbtn::before,
html .mbtn::before{ animation:none; }

/* a 450×600 plate re-rasterising a 100px shadow every frame for 350ms, on
   hover, over the live scene. The shadow still changes — it just lands.
   (retires login5-imperial.css:322) */
html .g5-panel{ transition:transform var(--g5-t-base) var(--g5-ease); }


/* ═══════════════════════════════════════════════════════════════════════════
   3 · PARALLAX — a few pixels of depth over the 3D kingdom
   ───────────────────────────────────────────────────────────────────────────
   transform only, one rAF, and `html.g5-par` only exists once 07-motion.js has
   confirmed a fine pointer, a desktop width, no `.mob` and no reduced-motion
   preference. Off ⇒ no transform declaration at all ⇒ no promoted layer and no
   containing block. The hero travels furthest because it sits deepest.
   ═══════════════════════════════════════════════════════════════════════════ */
html.g5-par #g5-hero{
  transform:translate3d(calc(var(--g5-mx) * -9px), calc(var(--g5-my) * -6px), 0);
}
html.g5-par #g5-panels{
  transform:translate3d(calc(var(--g5-mx) * -4px), calc(var(--g5-my) * -2.5px), 0);
}


/* ═══════════════════════════════════════════════════════════════════════════
   4 · REDUCED MOTION
   ───────────────────────────────────────────────────────────────────────────
   Every duration and delay in §1 is a `calc()` on --g5-t-slow, which tokens.css
   already collapses, so the arrival flattens on its own. This block is the belt
   to that pair of braces: under `reduce` the sequence must not merely be fast,
   it must not be SCHEDULED. Verified with a getAnimations() probe — under
   --force-prefers-reduced-motion the page runs exactly one animation, the
   poster cross-fade, which is the one that has to survive.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  html #g5-poster, html #g5-top, html #g5-hero, html #g5-panels .g5-panel,
  html #g5-feats, html #g7-bnl, html #g7-bnr, html #nation-grid > *,
  html #mob .m-hero, html #mob .mcard, html #mob .m-feats{
    animation-delay:0s !important;
    animation-duration:.001s !important;
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
   5 · MOBILE — nothing continuous, at all
   ───────────────────────────────────────────────────────────────────────────
   `.mob` is set by ASPECT RATIO (login2.js:21) and the breakpoint by VIEWPORT
   WIDTH, so the two are not the same set: an 869×900 window is ≤870px and not
   `.mob`. Both are covered.

   02-atmosphere and 08-mobile already display:none their own layers here, and
   10-chrome stops its beacon ≤868px and its ping ≤760px. What is left is the
   handful with no owner: imperial's crown ornament, and the 761–870px band
   where 10's ping is still ticking.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:870px){
  html #g5-hero::before,
  html #g6-rays,
  html #g6-grain,
  html #g7-fog,
  html body.g6-imperial #aon-online .dot::after,
  html body.g6-imperial #aon-dc-gate .dc-gift::after{ animation:none !important; }
}
html.mob #g5-hero::before,
html.mob #g6-rays,
html.mob #g6-grain,
html.mob #g7-fog,
html.mob body.g6-imperial #aon-online .dot::after,
html.mob body.g6-imperial #aon-dc-gate .dc-gift::after{ animation:none !important; }

/* ══ gate5 · parts/08-mobile.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PASS 08 — THE PHONE                    parts/08-mobile.css
   ───────────────────────────────────────────────────────────────────────────
   A large share of real signups arrive on a phone. This pass makes #mob a
   first-class surface rather than a fallback column.

   WHEN THIS APPLIES
     login2.js fit() sets html.mob when min(w/1930, h/815) < 0.45 — i.e.
     w < 869px OR h < 367px. A phone in LANDSCAPE (844×390) is therefore .mob
     too, and it misses every max-width query — see §9.

   WHAT IT FIGHTS
     index.php loads login5-imperial.css and login5-aoe.css AFTER the parts
     aggregator, and both are dense with !important. Every rule below that has
     to beat one of them is scoped `html.mob #mob …` so it wins on SPECIFICITY,
     not on order. That is also why some declarations carry !important: the
     rule they override already has it.

   HARD RULES HONOURED
     · no `display:…!important` on anything login2.js toggles inline
       (.modal, #gsi-*, .ng-tile, #mob itself is only class-toggled — safe)
     · no 3D, no backdrop-filter, no continuous animation on a phone (§7)
     · tokens only; every raw `animation:` is reduced-motion guarded (§11)
   ═══════════════════════════════════════════════════════════════════════════ */

/* ══ 1 · THE COLUMN ══════════════════════════════════════════════════════
   Safe areas on every edge, dvh instead of vh, and no iOS text inflation. */
html.mob{
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}
html.mob #mob{
  box-sizing:border-box;
  min-height:100vh;                    /* fallback for pre-dvh engines      */
  min-height:100dvh;                   /* the URL bar makes vh wrong here   */
  padding-top:calc(env(safe-area-inset-top, 0px) + var(--g5-s3));
  padding-right:calc(env(safe-area-inset-right, 0px) + var(--g5-s4));
  padding-bottom:calc(env(safe-area-inset-bottom, 0px) + 92px);
  padding-left:calc(env(safe-area-inset-left, 0px) + var(--g5-s4));
}
/* ══ 2 · THE HERO ════════════════════════════════════════════════════════
   PASS 03 OWNS THIS. It claims #mob .m-hero with an emblem background and
   its own ::before / ::after typography, so everything below is DORMANT and
   this pass does not touch the lockup's proportions — two passes styling one
   wordmark is how a gate ends up with two wordmarks.

   What survives is the fallback path: if 03 is ever skipped (?nogate5=03) the
   base leaves a hidden <img> and CSS type in its place, and 08-mobile.js then
   adds .m8-art to put the real painted lockup on screen. The script checks
   for exactly the claim 03 makes (a background-image on .m-hero, or a ::before
   it rewrote) and stands down when it finds one — verified live: the moment
   03 landed, this block went dark on its own.

   The painted lockup is assets/login2/hero_m2.png, already in the markup and
   already downloaded by every phone whether it is shown or not (a
   display:none <img> is still fetched), so putting it on screen costs zero
   additional bytes. Cutting a transparent copy of the same artwork and
   shipping it alongside would not — which is why there is no 08 art script.

   It was painted as a PLATE though: gold on an opaque dark ground with
   straight edges, which over the poster's sky reads as a pasted box —
   worst in landscape, where the sky behind it is brightest. Two moves fix
   that without a byte: the outer edges dissolve, and what is left of the
   ground lands on a deliberate halo instead of on the sky. */
html.mob #mob .m-hero.m8-art{
  position:relative;
  line-height:0;                        /* kills the inline-image gap */
  background:radial-gradient(ellipse 64% 104% at 50% 48%,
    color-mix(in srgb, var(--g5-night) 82%, transparent) 0 38%,
    color-mix(in srgb, var(--g5-night) 40%, transparent) 68%,
    transparent 100%);
}
html.mob #mob .m-hero.m8-art::before,
html.mob #mob .m-hero.m8-art::after{ content:none; }
html.mob #mob .m-hero.m8-art img{
  display:block;
  position:relative;
  width:min(430px, 94%);
  height:auto;
  margin:0 auto;
  /* the fades are cut outside the crown, the wordmark and the strapline, so
     no glyph is touched — only the ground they sit on */
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent),
                     linear-gradient(180deg, transparent, #000 6%, #000 88%, transparent);
          mask-image:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent),
                     linear-gradient(180deg, transparent, #000 6%, #000 88%, transparent);
  -webkit-mask-composite:source-in;
          mask-composite:intersect;
}

/* ══ 3 · THE CARDS ═══════════════════════════════════════════════════════
   The forged frame is a 26/28px border cut for a 1900px stage. On a 390px
   screen that is 15% of the width per side and the ornate corners downsample
   to mush. Re-cut: same art, same 65px slice, thinner rail. */
html.mob #mob .mcard{
  width:min(520px, 100%);
  margin:0 auto var(--g5-s5);
  border-width:17px !important;
  border-image:var(--g5-frame) 65 / 17px / 0 stretch !important;
  padding:var(--g5-s3) var(--g5-s4) var(--g5-s5) !important;
}
html.mob #mob .mcard h2{
  margin-top:0;
  font-size:19px !important;
  letter-spacing:3px !important;
}
html.mob #mob .mcard .msub{
  margin-bottom:var(--g5-s5);
  font-size:9.5px;
  letter-spacing:1.9px;
}

/* ══ 4 · FIELDS + THUMB REACH ════════════════════════════════════════════
   Audit target: every interactive box ≥ 44×44 CSS px, and every text input
   ≥16px so focusing one never zooms the page on iOS. */
html.mob #mob .mf{
  margin-bottom:var(--g5-s4);
  /* native scroll-into-view on focus must clear the fixed online chip */
  scroll-margin-top:calc(env(safe-area-inset-top, 0px) + 76px);
  scroll-margin-bottom:var(--g5-s6);
}
html.mob #mob .mf input{
  font-size:16px;                       /* iOS zoom threshold — do not lower */
  line-height:1.2;
  min-width:0;
  /* `all:unset` left the input 19px tall inside a 52px field. The <label>
     forwards the tap either way, but a finger that lands 2px off the glyph
     row should be ON the control, not next to it. */
  align-self:stretch;
}
/* 👁 — was 27×27 of padding around a glyph */
html.mob #mob .mf .meye{
  display:flex; align-items:center; justify-content:center;
  width:44px; height:44px; padding:0;
  margin-right:calc(var(--g5-s4) * -1 + 2px);   /* keep the optical inset    */
  border-radius:var(--g5-r-sm);
  -webkit-tap-highlight-color:transparent;
}
html.mob #mob .mf .meye:active{ opacity:1; background:var(--g5-sunk); }

html.mob #mob .mrow{
  min-height:44px;
  margin-bottom:var(--g5-s4);
  gap:var(--g5-s4);
}
/* the whole label is the target, not the 18px box */
html.mob #mob .mrow .mchk{
  min-height:44px;
  padding-right:var(--g5-s2);
  -webkit-tap-highlight-color:transparent;
}
html.mob #mob .mrow .mchk i{ width:22px; height:22px; flex:0 0 22px; }
/* "Forgot Password?" — inline text; pad it out to 44 and pull the padding
   back out of the flow so the row does not grow */
html.mob #mob .mrow .mlink{
  display:flex; align-items:center;
  min-height:44px; padding:0 var(--g5-s1);
  margin:0 calc(var(--g5-s1) * -1);
  text-align:right;
  -webkit-tap-highlight-color:transparent;
}
/* the CTA is 58px from imperial — well past 44, so only the touch behaviour
   is this pass's business (no double-tap zoom, no blue flash) */
html.mob #mob .mbtn{
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
}
html.mob #mob #gsi-mobile-wrap{ margin-top:var(--g5-s1); }

/* ══ 5 · THE NATION WALL — the signup ════════════════════════════════════
   It was a 2-column scroller (max-height:340px) inside a card inside a
   scrolling page: a nested-scroll trap where a thumb that starts on a flag
   scrolls the wrong box and a whole region can never be discovered.

   Fix, in three parts:
     · the inner scroller is GONE — one page, one scroll axis
     · the region headings pin as you pass them (iOS-contacts pattern), so you
       always know where you are in 49 nations
     · 08-mobile.js adds a region filter row above the grid; ALL is the
       default, so nothing is ever hidden from someone who ignores it
   Tiles are auto-fill, not a hard 2-up: html.mob runs all the way to 868px
   wide (and every landscape phone), where 2 columns would be absurd. */
html.mob #m-nation-grid{
  max-height:none;
  overflow:visible;
  grid-template-columns:repeat(auto-fill, minmax(142px, 1fr));
  /* an interrupted vertical swipe must never become a horizontal pan */
  touch-action:pan-y;
}
/* pass 06 already pins the region lintel with top:0 — correct while the wall
   is its own scroller, wrong once the PAGE is the scroller, because it then
   parks under the fixed "commanders online" pill. Offset only; the lintel
   itself stays exactly as 06 drew it. */
html.mob #m-nation-grid > .ng-region{
  top:calc(env(safe-area-inset-top, 0px) + 46px);
}
/* pass 06 owns the tile itself (the hanging-banner build). This pass only
   adds what a finger needs and stays off its geometry. */
html.mob #m-nation-grid .ng-tile{
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
}
/* a tap must not leave a stuck :hover state behind on a touch screen */
@media (hover:none){
  html.mob #m-nation-grid .ng-tile:hover{ transform:none; }
}
html.mob #m-nation-grid .ng-tile:active{ transform:scale(.965); }
html.mob #m-nation-grid .ng-tile .nname{ white-space:normal; }
html.mob #mob .m-ngtos{ margin-top:var(--g5-s5); font-size:10px; }

/* ── the region filter (built by 08-mobile.js) ──────────────────────────
   A horizontal chip rail: a different scroll AXIS from the page, so it is
   not a nested trap. Deliberately NOT sticky — the fixed "commanders online"
   pill already owns the top 38px, and two stacked bars would eat a tenth of
   a landscape phone. Hidden entirely when the script has not run. */
.m8-regions{ display:none; }
html.mob #mob .m8-regions{
  display:flex; gap:var(--g5-s2);
  margin:0 0 var(--g5-s4);
  padding:var(--g5-s1) 0;
  scroll-margin-top:calc(env(safe-area-inset-top, 0px) + 52px);
  overflow-x:auto; overflow-y:hidden;
  scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;
  /* the rail runs off the right edge — say so */
  -webkit-mask-image:linear-gradient(90deg, #000 calc(100% - 22px), transparent);
          mask-image:linear-gradient(90deg, #000 calc(100% - 22px), transparent);
}
html.mob #mob .m8-regions::-webkit-scrollbar{ display:none; }
html.mob #mob .m8-chip{
  all:unset;
  box-sizing:border-box; flex:0 0 auto; cursor:pointer;
  display:flex; align-items:center;
  min-height:44px; padding:0 var(--g5-s5);
  border-radius:var(--g5-r-pill);
  scroll-snap-align:start;
  background:var(--g5-sunk);
  border:1px solid var(--g5-line);
  font:600 12px/1 var(--g5-f-ui);
  letter-spacing:.4px;
  color:var(--g5-ink-2);
  white-space:nowrap;
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
  transition:color var(--g5-t-fast) var(--g5-ease),
             border-color var(--g5-t-fast) var(--g5-ease);
}
html.mob #mob .m8-chip[aria-pressed="true"]{
  background:linear-gradient(180deg, var(--g5-gold-2), var(--g5-gold-4));
  border-color:var(--g5-gold-2);
  color:var(--g5-ink-on);
  font-weight:700;
}
html.mob #mob .m8-chip:focus-visible{ outline:2px solid var(--g5-gold-2); outline-offset:2px; }
/* the filter is CSS-applied only on the phone: at ≥869px the class stays on
   the node but every tile is visible again */
html.mob #m-nation-grid .m8-off{ display:none; }

/* ══ 6 · FEATURE CARDS + FOOTNOTE ════════════════════════════════════════ */
html.mob #mob .m-feats{
  width:min(520px, 100%);
  margin-top:var(--g5-s2);
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(232px, 1fr));
  gap:var(--g5-s3);
}
html.mob #mob .mft{ padding:var(--g5-s4) var(--g5-s5); }
html.mob #mob .m-copy{ margin-top:var(--g5-s6); line-height:1.5; }
/* the SEO block sits below the column — keep it off the home indicator and
   out of the notch's ears. index.php sets its padding INLINE, so this is one
   of the few places an author !important is the only lever. */
html.mob #seo-footer{
  padding-bottom:calc(env(safe-area-inset-bottom, 0px) + 40px) !important;
  padding-left:calc(env(safe-area-inset-left, 0px) + var(--g5-s6)) !important;
  padding-right:calc(env(safe-area-inset-right, 0px) + var(--g5-s6)) !important;
}

/* ══ 7 · FLOATING CHROME ═════════════════════════════════════════════════
   Three things float over the column from outside #mob: the online plaque and
   the Discord disc (index.php, restyled by pass 10) and the studio badge
   (vision_badge.js, inline styles).

   Their LOOPS are not this pass's problem — pass 07 already kills every
   ambient keyframe under html.mob, the two pings included, and pass 02 has
   repurposed #g6-grain as its colour grade, so nothing here touches either.
   What is left is what only a phone has:

     · SAFE AREAS. Nothing out there knows a notch exists. Applied as MARGIN
       rather than by rewriting top/right/bottom — margin is additive, no
       other pass sets it, and it therefore composes with whatever offsets
       pass 10 (or a later one) picks instead of fighting them for the
       property.
     · BLUR. A backdrop-filter over a column a thumb is scrolling means a
       backdrop snapshot per pill per frame, for a 32px and a 46px disc.  */
html.mob #aon-online{ margin-top:env(safe-area-inset-top, 0px); }
html.mob #aon-dc-gate{
  margin-right:env(safe-area-inset-right, 0px);
  margin-bottom:env(safe-area-inset-bottom, 0px);
  touch-action:manipulation;
}
html.mob .vision-badge{
  margin-left:env(safe-area-inset-left, 0px);
  margin-bottom:env(safe-area-inset-bottom, 0px);
  /* inline style attribute — !important is the only lever that reaches it */
  -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
}
/* the one place in this file that deliberately out-specifies a LATER pass
   (10's `html body.g6-imperial #…`, one step up via the attribute), and only
   to take a blur off a phone. */
html.mob body #aon-online[role],
html.mob body #aon-dc-gate[href]{
  -webkit-backdrop-filter:none; backdrop-filter:none;
}

/* ══ 8 · MODALS + TOAST ON A PHONE ═══════════════════════════════════════
   Pass 09 designs the dialogs; this pass only fixes what is specifically
   wrong on a phone and leaves its plate — frame, studs, seal, padding —
   completely alone.
     · `.modal{position:fixed;inset:0}` resolves against the LARGE viewport,
       so a "centred" dialog sits below the visual centre while the URL bar
       is up. Anchor it to the bottom instead: exact, and it puts the primary
       button (SECURE MY EMPIRE, SEND RESET LINK) in the thumb zone.
     · the scrim's backdrop-filter is a full-screen blur — no phone should
       pay for one.
     · 15px inputs zoom the whole page on focus in iOS Safari.
   `[role="dialog"]` rides along purely for specificity: 09 scopes its scrim
   that way and login2.js guarantees the attribute on every .modal.
   NOTE: display is never touched here — login2.js owns .modal.open. */
html.mob .modal,
html.mob .modal[role="dialog"]{
  align-items:flex-end;
  padding:var(--g5-s4) var(--g5-s3)
          calc(env(safe-area-inset-bottom, 0px) + var(--g5-s4));
  -webkit-backdrop-filter:none !important; backdrop-filter:none !important;
}
html.mob .modal .mbox{
  width:100%;
  margin:auto auto 0;                  /* flex-end + auto top margin = bottom */
  max-height:calc(100dvh - env(safe-area-inset-top, 0px)
                         - env(safe-area-inset-bottom, 0px) - var(--g5-s8));
  -webkit-overflow-scrolling:touch;
}
/* 15px !important from pass 09 — under the 16px iOS zoom threshold */
html.mob .modal .mbox input{
  font-size:16px !important;
  scroll-margin-top:var(--g5-s6);
}
html.mob .modal .mbox .mbtn{ touch-action:manipulation; }
/* the ✕ is a 32px disc by design — grow the TARGET, not the disc */
html.mob .modal .mbox .mx{
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
}
html.mob .modal .mbox .mx::after{
  content:''; position:absolute; inset:-7px; border-radius:inherit;
}
html.mob .modal .mbox .claim-skip{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:44px; padding:0 var(--g5-s4);
}
/* the toast landed on top of the Discord pill and the studio badge */
html.mob #toast{
  left:var(--g5-s4); right:var(--g5-s4);
  bottom:calc(env(safe-area-inset-bottom, 0px) + 76px);
  max-width:none;
  transform:translateY(14px) scale(.97);
}
html.mob #toast.show{ transform:translateY(0) scale(1); }

/* ══ 9 · LANDSCAPE ═══════════════════════════════════════════════════════
   A phone on its side is ~844×390: still html.mob (844/1930 = 0.437), and it
   misses every max-width query in this file and in login5.css. Vertical room
   is the scarce axis, so the column becomes two — hero across the top, LOGIN
   and REGISTER side by side, exactly like the desktop gate reads. */
@media (orientation:landscape) and (max-height:560px){
  html.mob #mob{
    display:grid;
    grid-template-columns:repeat(2, minmax(0, 1fr));
    align-items:start;
    column-gap:var(--g5-s5);
    padding-bottom:calc(env(safe-area-inset-bottom, 0px) + 64px);
  }
  html.mob #mob > .m-hero,
  html.mob #mob > .m-feats,
  html.mob #mob > .m-copy{ grid-column:1 / -1; }
  /* pass 03's crest and margin are clamped on vw — correct in portrait, but
     a landscape phone is 844 WIDE and 390 TALL, so the width clamps hand it
     ~104px of emblem plus 42px of margin out of 390px of screen. Re-clamp the
     same design on the axis that is actually scarce. */
  html.mob #mob .m-hero{
    margin:calc(env(safe-area-inset-top, 0px) + 16px) 0 var(--g5-s3) !important;
    padding-top:clamp(40px, 11vh, 58px);
    background-size:auto clamp(36px, 10vh, 52px);
  }
  html.mob #mob .m-hero::before{ font-size:clamp(24px, 5.6vh, 38px); }
  html.mob #mob .m-hero::after{ font-size:9px; margin-top:var(--g5-s2); }
  html.mob #mob .m-hero.m8-art img{ width:min(360px, 62%); }
  html.mob #mob .mcard{ width:auto; margin-left:0; margin-right:0; }
  /* the two cards are half-width now — smaller tiles keep 2 up */
  html.mob #m-nation-grid{ grid-template-columns:repeat(auto-fill, minmax(124px, 1fr)); }
  /* 390px of height is too little to spend on a pinned bar */
  html.mob #m-nation-grid > .ng-region{ position:static; }
  /* pass 10 collapses the Discord pill to a disc at ≤760px WIDE — but a
     landscape phone is 844 wide and 390 tall, so it keeps the full bar and
     parks it across the register card. Same collapse, height-driven. */
  html.mob #aon-dc-gate .dc-t{ display:none; }
  /* a sheet that tall would cover the whole screen sideways */
  html.mob .modal,
  html.mob .modal[role="dialog"]{ align-items:center; padding:var(--g5-s3); }
  html.mob .modal .mbox{ width:min(460px, 100%); max-height:94dvh; margin:0 auto; }
  html.mob #toast{ bottom:calc(env(safe-area-inset-bottom, 0px) + var(--g5-s4)); }
}

/* ══ 10 · SMALL PHONES (≤380px: iPhone SE/mini, older Androids) ══════════
   Chrome on this workstation floors the layout viewport near 510px, so this
   band was reasoned about statically rather than photographed — every value
   here is a proportional step down from a rendered 510px, not a guess at a
   new layout. */
@media (max-width:380px){
  html.mob #mob{
    padding-right:calc(env(safe-area-inset-right, 0px) + var(--g5-s3));
    padding-left:calc(env(safe-area-inset-left, 0px) + var(--g5-s3));
  }
  html.mob #mob .mcard{
    border-width:13px !important;
    border-image:var(--g5-frame) 65 / 13px / 0 stretch !important;
    padding:var(--g5-s2) var(--g5-s3) var(--g5-s4) !important;
  }
  html.mob #mob .mcard h2{ font-size:17px !important; letter-spacing:2.4px !important; }
  html.mob #mob .mcard .msub{ font-size:9px; letter-spacing:1.5px; }
  html.mob #m-nation-grid{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  html.mob #mob .m-feats{ grid-template-columns:1fr; }
}

/* ══ 11 · MOTION ═════════════════════════════════════════════════════════
   This pass ships NO raw `animation:` of its own — pass 06 owns the founding
   moment and pass 07 owns the entrances, and duplicating either would mean
   two keyframes fighting over one element. What is left is press feedback,
   which still has to go quiet when the system asks. */
@media (prefers-reduced-motion:reduce){
  html.mob #m-nation-grid .ng-tile:active{ transform:none; }
  html.mob #mob .m8-chip{ transition:none; }
}

/* ══ gate5 · parts/09-dialogs.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 09 — DIALOGS, FEEDBACK & TOAST          parts/09-dialogs.css
   ───────────────────────────────────────────────────────────────────────────
   Three dialogs (#modal-forgot, #modal-reset, #modal-claim), one system:

     SCRIM   one darkened, softly blurred field. Never touched by display.
     PLATE   one forged-iron writ — gold hairline rim, engraved inner rule,
             four rivets, radius from --g5-r-lg. Same metal as the panels,
             built from the same tokens rather than from their art, so this
             pass lands with pass 04 without depending on it.
     HEAD    eyebrow (injected by 09-dialogs.js) · Cinzel title · engraved
             rule (art/dlg-rule.png). Identical in all three dialogs.
     CLOSE   one seal-shaped ✕ inside the plate's top-right.
     ENTER   scrim fades, plate rises. Claim gets the seal press instead.

   #modal-claim is the commercial moment: the empire has just been founded as
   a guest and this is what turns it into an account. It gets the wax seal
   (art/dlg-seal.png), the stakes in warn-amber, a gold CTA that reads as a
   reward rather than an alarm, and a quiet, honest skip.

   ⚠ THE ONE RULE THAT BREAKS THE PAGE
   login2.js opens a dialog with `.open` and closes it by removing the class;
   the base sets `.modal{display:none}` / `.modal.open{display:flex}`. NOTHING
   in this file declares `display` on `.modal` — not with !important, not
   without. An author !important there beats the class state and would pin a
   full-viewport scrim over the login page for good. Every rule below styles
   paint, box and motion only.

   SPECIFICITY — login5-imperial.css loads AFTER the aggregator and !importants
   .modal / .mbox / .mbox input / .mbox .mbtn / .mbox .mx / #toast. Important
   declarations are settled by specificity first, so every override here is
   deliberately one step heavier (.modal .mbox … , html #toast). That is why
   the selectors look longer than they need to.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ══ 1 · THE SCRIM ══════════════════════════════════════════════════════ */
.modal[role="dialog"]{
  z-index: var(--g5-z-modal);
  padding: var(--g5-s5);
  box-sizing: border-box;
  /* the scrim itself scrolls only if a plate somehow outgrows it; the plate
     caps its own height and scrolls internally first (§2). */
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--g5-scrim) !important;
  -webkit-backdrop-filter: blur(6px) saturate(.82) !important;
          backdrop-filter: blur(6px) saturate(.82) !important;
}
.modal.open{ animation: g509scrim var(--g5-t-base) var(--g5-ease); }
/* A scrim that something still floats above is not a scrim. The studio badge
   is injected by /vision_badge.js with an INLINE z-index of 2147483647, so no
   layer can outrank it — it has to be faded instead, and only while a dialog
   is open (login2.js owns html.modal-open). At 320px it lands exactly on the
   claim dialog's "skip for now". The Discord pill is pass 10's — it already
   re-based that one onto --g5-z-float. Opacity only; never display. */
html.modal-open .vision-badge{ opacity: 0 !important; pointer-events: none !important; }

/* ══ 2 · THE PLATE ══════════════════════════════════════════════════════ */
.modal .mbox{
  position: relative;
  box-sizing: border-box;
  width: min(452px, 100%);
  margin: auto;                       /* safe centring inside a scrollable scrim */
  max-height: calc(100vh - var(--g5-s8));
  max-height: calc(100dvh - var(--g5-s8));
  overflow-y: auto;
  overscroll-behavior: contain;
  text-align: center;

  /* the 26/28px painted border-image of the base + imperial is retired here:
     the dialog is a plate, not a picture frame. */
  border: 1px solid var(--g5-line-2) !important;
  border-image: none !important;
  border-radius: var(--g5-r-lg);
  /* top gutter = the ✕ (32px at top:s3) plus its own breathing room */
  padding: calc(var(--g5-s8) + var(--g5-s3)) var(--g5-s7) var(--g5-s7) !important;
  /* four rivets. One 4-way-symmetric PNG serves all four corners; the 10px
     inset keeps each disc clear of the --g5-r-lg corner curve. */
  background:
    url("/assets/login5/art/dlg-stud.png") no-repeat left  10px  top    10px / 18px 18px,
    url("/assets/login5/art/dlg-stud.png") no-repeat right 10px  top    10px / 18px 18px,
    url("/assets/login5/art/dlg-stud.png") no-repeat left  10px  bottom 10px / 18px 18px,
    url("/assets/login5/art/dlg-stud.png") no-repeat right 10px  bottom 10px / 18px 18px,
    var(--g5-plate) !important;
  background-clip: padding-box !important;
  /* --g5-plate is near-opaque by design; a dialog is not a panel and must not
     let the kingdom bleed through its own paper. The colour goes UNDER it. */
  background-color: var(--g5-iron-3) !important;
  box-shadow: var(--g5-e4), var(--g5-glow-gold) !important;
  /* the engraved inner rule. An outline (not a ::before) so it tracks the
     border box and never slides when a tall plate scrolls internally. */
  outline: 1px solid var(--g5-line);
  outline-offset: -6px;
  animation: g509plate var(--g5-t-slow) var(--g5-ease);

  scrollbar-width: thin;
  scrollbar-color: var(--g5-line-2) transparent;
}
.modal .mbox::-webkit-scrollbar{ width: 8px; }
.modal .mbox::-webkit-scrollbar-track{ background: transparent; }
.modal .mbox::-webkit-scrollbar-thumb{
  background: var(--g5-line); border-radius: var(--g5-r-pill);
}
/* ══ 3 · THE HEADER ═════════════════════════════════════════════════════ */
/* eyebrow — injected by 09-dialogs.js, aria-hidden, purely a frame for the
   title. Absent if the script never runs; nothing below depends on it. */
.modal .g5d-brow{
  font: var(--g5-t-sub);
  font-size: 9.5px;
  letter-spacing: var(--g5-track-2);
  text-transform: uppercase;
  color: var(--g5-gold-4);
  margin: 0 0 var(--g5-s3);
}
.modal .mbox h3{
  margin: 0 0 var(--g5-s4) !important;
  font: var(--g5-t-title) !important;
  font-size: clamp(16px, 4.3vw, 21px) !important;
  letter-spacing: .16em !important;
  text-wrap: balance;
  color: var(--g5-gold-2);
  background-image: linear-gradient(178deg,
      var(--g5-gold-1) 0%, var(--g5-gold-2) 34%, var(--g5-gold-3) 66%, var(--g5-gold-4) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 3px var(--g5-night));
}
.modal .mbox h3::after{           /* the engraved rule, art/dlg-rule.png */
  content: '';
  display: block;
  width: 82%; height: 12px;
  margin: var(--g5-s4) auto 0;
  background: url("/assets/login5/art/dlg-rule.png") center / 100% auto no-repeat;
}
.modal .mbox p{
  margin: 0 0 var(--g5-s5) !important;
  font: var(--g5-t-body);
  color: var(--g5-ink-2);
  text-wrap: pretty;
}
/* the stakes sentence inside the claim copy — wrapped by 09-dialogs.js */
.modal .g5d-stake{ color: var(--g5-warn); font-weight: 600; }

/* ══ 4 · FIELDS ═════════════════════════════════════════════════════════ */
.modal .mbox input{
  height: 48px !important;
  margin: 0 0 var(--g5-s4) !important;
  padding: 0 var(--g5-s5) !important;
  border-radius: var(--g5-r-sm) !important;
  background: var(--g5-sunk) !important;
  border: 1px solid var(--g5-ink-4) !important;
  box-shadow: var(--g5-engrave) !important;
  font: var(--g5-t-body) !important;
  font-size: 15px !important;
  color: var(--g5-ink) !important;
  caret-color: var(--g5-gold-3);
  /* border-color only: pass 07 counts every repainting transition that runs
     over the live WebGL scene, and a shadow fade is the expensive one */
  transition: border-color var(--g5-t-fast) var(--g5-ease);
}
.modal .mbox input::placeholder{ color: var(--g5-ink-3); opacity: .78; }
.modal .mbox input:hover{ border-color: var(--g5-line) !important; }
.modal .mbox input:focus{
  border-color: var(--g5-gold-3) !important;
  box-shadow: var(--g5-engrave), var(--g5-glow-gold) !important;
}
.modal .mbox input[aria-invalid="true"]{
  border-color: var(--g5-err) !important;
  animation: g509nudge var(--g5-t-slow) var(--g5-ease-in-out);
}

/* ══ 5 · BUTTONS ════════════════════════════════════════════════════════ */
/* One button, one look: struck gold with dark ink. The painted btn_cta art of
   the base is dropped INSIDE dialogs only — the page's own CTAs are untouched
   because every selector here is scoped under .modal. */
.modal .mbox .mbtn{
  display: flex; align-items: center; justify-content: center;
  gap: var(--g5-s3);
  width: 100%;
  min-height: 52px !important;
  height: auto !important;
  margin: var(--g5-s2) 0 0;
  padding: var(--g5-s4) var(--g5-s5);
  box-sizing: border-box;
  border: 1px solid var(--g5-gold-4) !important;
  border-image: none !important;
  border-radius: var(--g5-r-sm) !important;
  background: linear-gradient(180deg,
      var(--g5-gold-2) 0%, var(--g5-gold-3) 48%, var(--g5-gold-4) 100%) !important;
  font: var(--g5-t-cta) !important;
  font-size: 14px !important;
  letter-spacing: .14em !important;
  color: var(--g5-ink-on) !important;
  text-shadow: 0 1px 0 var(--g5-gold-1);
  box-shadow: var(--g5-e2);
  cursor: pointer;
  transition: transform var(--g5-t-fast) var(--g5-ease),
              opacity   var(--g5-t-fast) linear;
}
.modal .mbox .mbtn::before{ content: none; }     /* retires the imperial sweep */
.modal .mbox .mbtn:hover{
  box-shadow: var(--g5-e2), var(--g5-glow-hot);
  transform: translateY(-1px);
}
.modal .mbox .mbtn:active{ transform: translateY(1px); box-shadow: var(--g5-e1); }
.modal .mbox .mbtn:focus-visible{ outline: 2px solid var(--g5-gold-1); outline-offset: 3px; }

/* busy — setBusy() adds .is-busy + [aria-busy] and swaps the label */
.modal .mbox .mbtn.is-busy,
.modal .mbox .mbtn[aria-busy="true"]{
  cursor: progress;
  opacity: .72;
  transform: none !important;
  box-shadow: var(--g5-e1);
}
.modal .mbox .mbtn.is-busy::before,
.modal .mbox .mbtn[aria-busy="true"]::before{
  content: '';
  /* reviving this pseudo also revives login5-imperial's sweep, which is
     absolutely positioned, gradient-filled and translated off-button — every
     one of its properties has to be taken back or the spinner never lands */
  position: static; inset: auto;
  transform: none;
  background: none;
  mix-blend-mode: normal;
  width: 14px; height: 14px;
  box-sizing: border-box;
  flex: 0 0 auto;
  border: 2px solid var(--g5-ink-on);
  border-right-color: transparent;
  border-radius: var(--g5-r-pill);
  opacity: .8;
  animation: g509spin .72s linear infinite;
}
.modal .mbox .mbtn[disabled]:not(.is-busy){ opacity: .55; cursor: not-allowed; }

/* close — a small seal set inside the plate, not hanging off its corner */
.modal .mbox .mx{
  position: absolute; top: var(--g5-s3); right: var(--g5-s3); z-index: 2;
  display: flex; align-items: center; justify-content: center;
  width: 32px !important; height: 32px !important;
  border-radius: var(--g5-r-pill) !important;
  background: var(--g5-sunk) !important;
  border: 1px solid var(--g5-line) !important;
  color: var(--g5-ink-3) !important;
  font-size: 13px;
  cursor: pointer;
  box-shadow: var(--g5-bevel);
  transition: color var(--g5-t-fast) var(--g5-ease),
              border-color var(--g5-t-fast) var(--g5-ease),
              transform var(--g5-t-base) var(--g5-ease);
}
.modal .mbox .mx:hover{
  color: var(--g5-gold-2) !important;
  border-color: var(--g5-gold-3) !important;
  transform: rotate(90deg);
}
.modal .mbox .mx:focus-visible{ outline: 2px solid var(--g5-gold-2); outline-offset: 2px; }

/* quiet text buttons — #cg-skip and the "Show password" toggle login2.js
   injects with the same .claim-skip class */
.modal .claim-skip{
  display: inline-block;
  padding: var(--g5-s2) var(--g5-s3);
  border-radius: var(--g5-r-xs);
  font: var(--g5-t-label);
  color: var(--g5-ink-3);
  cursor: pointer;
  transition: color var(--g5-t-fast) var(--g5-ease);
}
.modal .claim-skip:hover{ color: var(--g5-ink); }
.modal .claim-skip:focus-visible{ outline: 2px solid var(--g5-gold-2); outline-offset: 2px; }
.modal .auth-pass-toggle{
  display: block;
  margin: calc(-1 * var(--g5-s2)) 0 var(--g5-s4) auto;
  width: max-content;
  font-size: 11.5px;
  letter-spacing: .02em;
}
.modal #cg-skip{
  display: block;
  margin: var(--g5-s5) auto 0 !important;
  border-top: 1px solid var(--g5-ink-4);
  border-radius: 0;
  padding-top: var(--g5-s4);
  width: 100%;
}

/* ══ 6 · FEEDBACK — #msg-fp · #msg-rp · #msg-cg ═════════════════════════
   The result strip itself belongs to pass 05: it styles .omsg/.mmsg for the
   whole gate (wash plate, masked warn/check icon, .show reveal) and a dialog
   should not speak a second dialect of the same thing. Two things 05 cannot
   know about are settled here:

     · its strip is opacity:0 until login2.js adds .show — but the password
       hints login2.js injects (.mmsg.password-strength) NEVER get .show, so
       under 05 alone they are invisible. They are a live hint, not a result.
     · inside a plate the strip wants the plate's own gutter, not the panel's.
*/
.modal .mmsg{ margin-left: 0; margin-right: 0; }
/* 05 reserves 18px so a panel does not jump when a result lands. A dialog is
   short and its result strip sits between the CTA and the way out, where the
   reserved gap reads as a hole — collapse it until setMsg() writes text. */
.modal .mmsg:empty{ min-height: 0; margin-top: 0; padding: 0; border: 0; }
.modal .mmsg.password-strength{
  opacity: 1;
  transform: none;
  justify-content: flex-start;
  text-align: left;
  gap: var(--g5-s2);
  min-height: 0;
  padding: 0;
  margin: calc(-1 * var(--g5-s2)) 0 var(--g5-s4);
  font-size: 11.5px;
  color: var(--g5-warn);          /* "not strong yet" is progress, not error */
}
.modal .mmsg.password-strength.ok{ color: var(--g5-ok); }
.modal .mmsg.password-strength::before{
  display: block;                 /* 05 reveals its icon on .show only */
  width: 12px; height: 12px;
}

/* focus is handled in login2.js — this only guarantees it stays visible */
.modal .mbox :focus-visible{ outline: 2px solid var(--g5-gold-2); outline-offset: 2px; }

/* ══ 7 · THE CLAIM MOMENT ═══════════════════════════════════════════════
   The empire exists; this dialog is the seal that makes it the player's. */
#modal-claim .mbox{
  width: min(468px, 100%);
  padding-top: var(--g5-s6) !important;      /* no ✕ here — claim is a decision */
  animation: g509press var(--g5-t-slow) var(--g5-spring);
}
#modal-claim .claim-badge{
  position: relative;
  display: grid; place-items: center;
  width: 86px; height: 86px;
  margin: 0 auto var(--g5-s4) !important;
  font-size: 34px !important;
  background: url("/assets/login5/art/dlg-seal.png") center / contain no-repeat;
  filter: drop-shadow(0 10px 18px var(--g5-night));
  animation: g509seal var(--g5-t-cine) var(--g5-spring);
}
#modal-claim .claim-badge::after{           /* the struck-seal shockwave, once */
  content: '';
  position: absolute; inset: -6px;
  border: 2px solid var(--g5-gold-3);
  border-radius: var(--g5-r-pill);
  opacity: 0;                                /* the keyframes own it */
  animation: g509ring 1.05s var(--g5-ease) 1 both;
  pointer-events: none;
}
/* the bouncing arrow becomes an engraved assurance strip (09-dialogs.js
   rewrites the copy; the styling reads correctly either way) */
#modal-claim .claim-arrow{
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap;
  gap: var(--g5-s2) var(--g5-s3);
  margin: 0 0 var(--g5-s5) !important;
  padding: var(--g5-s3) var(--g5-s4);
  border-radius: var(--g5-r-sm);
  border: 1px solid var(--g5-line);
  background: var(--g5-sunk);
  box-shadow: var(--g5-bevel);
  font: var(--g5-t-sub) !important;
  font-size: 9.5px !important;
  letter-spacing: .18em !important;
  text-transform: uppercase;
  color: var(--g5-gold-3) !important;
  text-shadow: none !important;
  animation: none !important;               /* retires the bob */
}
#modal-claim .claim-arrow > span{ white-space: nowrap; }
#modal-claim .claim-arrow .g5d-sep{
  font-size: 5px;
  color: var(--g5-gold-5);
  transform: translateY(-1px);
}
/* the crest inside the seal — the emoji ships in its own colours, which are
   not the empire's. Pulled back to struck metal, never recoloured wholesale
   (platforms draw it differently). */
#modal-claim .claim-badge .g5d-glyph{
  filter: saturate(.32) brightness(1.12) drop-shadow(0 2px 3px var(--g5-night));
}
#modal-claim #cg-go{
  position: relative;
  overflow: hidden;
  min-height: 58px !important;
  font-size: 15px !important;
  box-shadow: var(--g5-e2), var(--g5-glow-gold);
}
#modal-claim #cg-go::after{                 /* one pass of light as it lands */
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%,
      var(--g5-gold-1) 50%, transparent 62%);
  opacity: .55;
  transform: translateX(-130%);
  pointer-events: none;
  animation: g509sheen 1.15s var(--g5-ease) .35s 1 both;
}
#modal-claim #cg-go:hover{ box-shadow: var(--g5-e2), var(--g5-glow-hot); }

/* ══ 8 · TOAST ══════════════════════════════════════════════════════════
   One surface, three semantics. login2.js only toggles .show; 09-dialogs.js
   sets data-g5t from the message text. No variant = info, which is what every
   [data-toast] hotspot on the page is. */
html #toast{
  display: flex; align-items: center; gap: var(--g5-s4);
  left: 50%; bottom: var(--g5-s7);
  max-width: min(560px, calc(100vw - 2 * var(--g5-s5)));
  padding: var(--g5-s4) var(--g5-s6) !important;
  border-radius: var(--g5-r-md) !important;
  border: 1px solid var(--g5-line) !important;
  background: var(--g5-plate-hi) !important;
  box-shadow: var(--g5-e3) !important;
  font: var(--g5-t-body) !important;
  color: var(--g5-ink) !important;
  text-align: left;
  z-index: var(--g5-z-toast);
  transform: translateX(-50%) translateY(14px) scale(.97);
  transition: opacity var(--g5-t-base) var(--g5-ease),
              transform var(--g5-t-slow) var(--g5-spring);
}
html #toast::before{
  content: '';
  flex: 0 0 auto;
  width: 8px; height: 8px;
  border-radius: var(--g5-r-pill);
  background: var(--g5-gold-3);
  box-shadow: 0 0 10px var(--g5-gold-3);
}
html #toast.show{ opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
html #toast[data-g5t="ok"]{ border-color: var(--g5-ok) !important; }
html #toast[data-g5t="ok"]::before{ background: var(--g5-ok); box-shadow: 0 0 10px var(--g5-ok); }
html #toast[data-g5t="err"]{ border-color: var(--g5-err) !important; }
html #toast[data-g5t="err"]::before{ background: var(--g5-err); box-shadow: 0 0 10px var(--g5-err); }

/* ══ 9 · SIZES ══════════════════════════════════════════════════════════ */
@media (max-width: 420px){
  .modal[role="dialog"]{ padding: var(--g5-s4); }
  .modal .mbox{ padding: 44px var(--g5-s5) var(--g5-s6) !important; }
  #modal-claim .mbox{ padding-top: var(--g5-s5) !important; }
  #modal-claim .claim-badge{ width: 68px; height: 68px; font-size: 27px !important; }
  /* the strip has to stay one line at 320 or the separators strand */
  #modal-claim .claim-arrow{
    letter-spacing: .06em !important;
    font-size: 8.5px !important;
    padding: var(--g5-s3) var(--g5-s2);
  }
  .modal .mbox .mbtn{ letter-spacing: .08em !important; }
}
/* a phone in portrait is short before it is narrow: buy back the height that
   decides whether "skip for now" needs a scroll */
@media (max-height: 760px){
  #modal-claim .claim-badge{ width: 58px; height: 58px; font-size: 23px !important;
                             margin-bottom: var(--g5-s3) !important; }
  .modal .mbox h3::after{ margin-top: var(--g5-s3); }
  .modal .mbox p{ margin-bottom: var(--g5-s4) !important; }
  #modal-claim .claim-arrow{ margin-bottom: var(--g5-s4) !important; }
  .modal #cg-skip{ margin-top: var(--g5-s4) !important; padding-top: var(--g5-s3); }
}
/* a very wide viewport must not stretch a form — the plate stays a plate */
@media (min-width: 1800px){
  .modal .mbox{ width: min(496px, 100%); }
  #modal-claim .mbox{ width: min(512px, 100%); }
}

/* ══ 10 · MOTION ════════════════════════════════════════════════════════ */
@keyframes g509scrim{ from{ opacity: 0; } }
@keyframes g509plate{
  from{ opacity: 0; transform: translateY(14px) scale(.985); }
}
@keyframes g509press{     /* the stamp coming down on the writ */
  0%  { opacity: 0; transform: translateY(-14px) scale(1.055); }
  58% { opacity: 1; transform: translateY(0) scale(.992); }
  100%{ opacity: 1; transform: none; }
}
@keyframes g509seal{
  0%  { opacity: 0; transform: scale(1.75) rotate(-16deg); }
  55% { opacity: 1; transform: scale(.94) rotate(2deg); }
  100%{ opacity: 1; transform: none; }
}
@keyframes g509ring{
  0%  { opacity: 0; transform: scale(.6); }
  22% { opacity: .9; }
  100%{ opacity: 0; transform: scale(1.85); }
}
@keyframes g509sheen{
  0%,18%{ transform: translateX(-130%); }
  100%  { transform: translateX(130%); }
}
@keyframes g509spin{ to{ transform: rotate(360deg); } }
@keyframes g509nudge{
  0%,100%{ transform: translateX(0); }
  20%    { transform: translateX(-5px); }
  45%    { transform: translateX(4px); }
  72%    { transform: translateX(-2px); }
}

@media (prefers-reduced-motion: reduce){
  .modal.open,
  .modal .mbox,
  #modal-claim .mbox,
  #modal-claim .claim-badge,
  #modal-claim .claim-badge::after,
  #modal-claim #cg-go::after,
  .modal .mbox input[aria-invalid="true"],
  .modal .mbox .mbtn.is-busy::before,
  .modal .mbox .mbtn[aria-busy="true"]::before{
    animation: none !important;
  }
  #modal-claim .claim-badge::after,
  #modal-claim #cg-go::after{ opacity: 0; }
  .modal .mbox .mx:hover{ transform: none; }
}

/* ══ gate5 · parts/10-chrome.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 10 — PAGE CHROME              assets/login5/parts/10-chrome.css
   ───────────────────────────────────────────────────────────────────────────
   Everything around the two auth panels: the top bar, the six feature cards,
   the live "commanders online" plaque, the Discord CTA and the SEO footer.
   Panels are part 04's, the toast + modals are part 09's — untouched here.

   ── WHY EVERY SELECTOR STARTS `html body.g6-imperial` ────────────────────
   The parts are NOT last in the cascade. index.php loads

       gate5.css.php (tokens + login5.css + parts/*)   ← we are in here
       login5-imperial.css                             ← ~40 `!important`s
       login5-aoe.css                                  ← more, at (0,2,1)
       the two inline <style> blocks in <body>          ← #aon-online, #aon-dc-gate

   so a later sheet beats this one on document order, and `!important` there
   beats plain declarations here whatever the order. Important declarations are
   resolved by SPECIFICITY first, so the prefix buys the margin that wins:

       #g5-feats                       imperial   (1,0,0)
       html:not(.mob) #g5-feats        aoe        (1,1,1)
       html body.g6-imperial #g5-feats HERE       (1,1,2)   ✔

   `<body class="g6-imperial">` is written in index.php, which no part may edit,
   so the hook is stable. Rules that only have to beat the inline <body> blocks
   (which carry no `!important`) win on `!important` alone.

   ── WHAT IS BEATEN, EXPLICITLY ───────────────────────────────────────────
   · index.php inline block #1 — #aon-online position/z-index/radius/border/
     background/font/colour, and `#aon-online .dot{animation:aonOnP … infinite}`
     which had NO prefers-reduced-motion guard at all.
   · index.php inline block #2 — #aon-dc-gate padding/radius/background/border/
     font/box-shadow, and `.dc-gift{animation:aonDcP … infinite}` — an INFINITE
     `box-shadow` animation, i.e. a full repaint every frame for the lifetime of
     the page, over a live WebGL scene, with no guard either. Both are replaced
     by transform/opacity pings that stop under reduced motion and on phones.
   · index.php inline z-indexes 99999 / 100000 — both dropped onto the token
     scale (`--g5-z-float`), which also fixes a real bug: at 100000 the Discord
     button floated ON TOP of the modals (.modal is z-index 1000).
   · login5-imperial.css — #g5-top, #g5-nav .nhot, #g5-feats, .fcard, .fcard b,
     .fcard:hover, #aon-online (+ .dot, b), #aon-dc-gate, #seo-footer (+ h1,h2).
   · login5-aoe.css — html:not(.mob) #g5-feats and html:not(.mob) .fcard.
     Its plaque.jpg card ground is KEPT (background-image is never overridden);
     only the frame, type, geometry and hover on top of it are rebuilt.
   · The <footer> and its children carry inline style="" attributes, so every
     footer rule needs `!important` to reach them at all.

   ── ART ──────────────────────────────────────────────────────────────────
   art/feat-medallions.png — the six painted `building-emblem-*-v16` medallions
   that already ship with the game, trimmed and packed into one 768×128 strip
   by tools/gate5_art/10-chrome.py (1.1 MB of separate PNGs → 40 KB, 1 request).
   Tile order == card order, so it is a plain background-position step.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════════════════
   1 · THE TOP BAR — title-screen chrome, not a website nav.
   A full-bleed forged rail that dissolves downward into the scene, with one
   gold edge line that fades to nothing at both ends, and a warm halo under the
   centre where the online plaque hangs.
   ═══════════════════════════════════════════════════════════════════════════ */

html body.g6-imperial #g5-top{
  padding: 0 clamp(16px, 2.2vw, 34px) !important;
  gap: clamp(10px, 1.5vw, 22px) !important;
  min-height: 66px;
  align-items: center;
  /* on the token scale so the language switcher's drop-down clears the panels —
     imperial had put the bar at z-index 4, the SAME layer as #g5-panels, so the
     menu opened UNDERNEATH the register panel. */
  z-index: var(--g5-z-float);
}

/* the rail itself — imperial drew an 18px-inset blurred rectangle whose blur
   ended in a visible hard edge. Full bleed + a mask so the blur dies with it. */
html body.g6-imperial #g5-top::before{
  content:'';
  position: absolute; inset: 0;
  border: 0; border-radius: 0;
  background:
    radial-gradient(ellipse 42% 190% at 50% -20%,
      color-mix(in srgb, var(--g5-gold-3) 13%, transparent), transparent 68%),
    linear-gradient(180deg,
      rgba(6,9,13,.88) 0%, rgba(7,10,14,.66) 58%, rgba(7,10,14,0) 100%);
  box-shadow: none;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,1) 0 56%, rgba(0,0,0,0) 100%);
  mask-image: linear-gradient(180deg, rgba(0,0,0,1) 0 56%, rgba(0,0,0,0) 100%);
  pointer-events: none;
  z-index: -1;
}

/* the edge — a struck line, brightest at the centre, gone at the corners */
html body.g6-imperial #g5-top::after{
  content:'';
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg,
    transparent 0%, var(--g5-line) 15%, var(--g5-line-hot) 50%,
    var(--g5-line) 85%, transparent 100%);
  opacity: .62;
  pointer-events: none;
  z-index: -1;
}

/* crest ↔ nav divider. The crest ART belongs to part 03; this is bar joinery. */
html body.g6-imperial #g5-top #g5-nav{
  display: flex; align-items: center;
  gap: clamp(0px, .4vw, 6px);
  margin-left: 0;
}
html body.g6-imperial #g5-top #g5-nav::before{
  content:'';
  flex: 0 0 1px; width: 1px; height: 26px;
  margin-right: clamp(6px, 1vw, 16px);
  background: linear-gradient(180deg, transparent, var(--g5-line-2), transparent);
}

/* ── nav buttons — engraved caps on iron ───────────────────────────────── */
html body.g6-imperial #g5-top #g5-nav .nhot{
  padding: 11px clamp(9px, 1vw, 15px) !important;
  border-radius: var(--g5-r-sm) !important;
  font: 700 11px/1 var(--g5-f-ui) !important;
  letter-spacing: var(--g5-track-2) !important;
  text-transform: uppercase;
  color: var(--g5-ink-3) !important;
  background: transparent !important;
  text-shadow: 0 1px 0 rgba(0,0,0,.7);
  transition: color var(--g5-t-base) var(--g5-ease),
              background var(--g5-t-base) var(--g5-ease),
              text-shadow var(--g5-t-base) var(--g5-ease) !important;
}
html body.g6-imperial #g5-top #g5-nav .nhot:hover{
  color: var(--g5-gold-2) !important;
  background: color-mix(in srgb, var(--g5-gold-3) 9%, transparent) !important;
  text-shadow: 0 0 16px color-mix(in srgb, var(--g5-gold-3) 55%, transparent);
}
/* imperial already animates a ::after underline in — retarget it to the token
   gold and to this padding so it sits under the label, not under the padding */
html body.g6-imperial #g5-top #g5-nav .nhot::after{
  left: clamp(9px, 1vw, 15px); right: clamp(9px, 1vw, 15px); bottom: 5px;
  background: linear-gradient(90deg, transparent, var(--g5-gold-3), transparent);
}
html body.g6-imperial #g5-top #g5-nav .nhot:focus-visible{
  outline: 2px solid var(--g5-gold-3) !important;
  outline-offset: 2px !important;
  color: var(--g5-gold-2) !important;
}

/* ── the language switcher's landing pad ───────────────────────────────────
   client/aon-lang.js appends #aon-lang here with position:absolute, top:0,
   right:0 and a 34px pill, then drops a 210px menu below it. So the slot must
   be exactly pill-high (top:0 == vertically centred), reserve the pill's width
   in the flex row, and NEVER clip or take a transform/filter — either would
   trap the drop-down. */
html body.g6-imperial #g5-top #g5-lang-slot{
  position: relative;
  flex: 0 0 auto; align-self: center;
  width: 152px; min-width: 0;
  height: 34px; min-height: 0;
  overflow: visible;
}

/* ── the trust mark — injected by 10-chrome.js before the language slot.
   A login page asks for a password; say the connection is safe. ─────────── */
html body.g6-imperial #g5-top #g5-secure{
  display: inline-flex; align-items: center; gap: 7px;
  flex: 0 0 auto;
  padding: 6px 12px;
  border-radius: var(--g5-r-pill);
  border: 1px solid var(--g5-ink-4);
  background: var(--g5-sunk);
  box-shadow: var(--g5-bevel);
  font: 700 9.5px/1 var(--g5-f-ui);
  letter-spacing: var(--g5-track-2);
  text-transform: uppercase;
  color: var(--g5-ink-3);
  white-space: nowrap;
}
html body.g6-imperial #g5-top #g5-secure svg{
  width: 11px; height: 13px; flex: 0 0 auto;
  fill: var(--g5-gold-4);
}
@media (max-width: 1340px){
  html body.g6-imperial #g5-top #g5-secure{ display: none; }
}

/* ── the nav yields to the centre plaque ───────────────────────────────────
   #aon-online is fixed at left:50%, so its left edge is `50vw − ~120px`, while
   the nav is left-anchored and its right edge does not move with the viewport:
   crest (≈305px incl. padding) + the four labels. They meet at about 1790px,
   and the plaque — being opaque and one layer higher — simply eats SUPPORT.
   Two steps of compression (1800, 1660) keep them apart down to ~1420px; below
   that the nav goes, exactly as login5.css already does at 1020px. The nav is
   four toast-only placeholders, so it is the cheap side of this trade. */
@media (max-width: 1800px){
  html body.g6-imperial #g5-top #g5-nav .nhot{
    padding: 10px 11px !important;
    font-size: 10px !important;
    letter-spacing: .14em !important;
  }
  html body.g6-imperial #g5-top #g5-nav .nhot::after{ left: 11px; right: 11px; }
}
@media (max-width: 1660px){
  html body.g6-imperial #g5-top #g5-nav .nhot{
    padding: 10px 8px !important;
    font-size: 9.5px !important;
    letter-spacing: .08em !important;
  }
  html body.g6-imperial #g5-top #g5-nav .nhot::after{ left: 8px; right: 8px; }
  html body.g6-imperial #aon-online{
    padding: 0 15px !important;
    font-size: 9.5px !important;
  }
  html body.g6-imperial #aon-online b{ font-size: 14px !important; }
}
@media (max-width: 1420px){
  html body.g6-imperial #g5-top #g5-nav{ display: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   2 · THE ONLINE COUNT — social proof, not a debug pill.
   It sits dead centre of the top bar, so it becomes the rail's centre plaque:
   flat top, hung from the bar, rounded at the foot. The number is real
   (aon_online_count()) and it ticks every 4.2s — tabular figures stop the whole
   plaque twitching sideways each time a digit changes.
   Stays pointer-events:none, as it must.
   ═══════════════════════════════════════════════════════════════════════════ */

html body.g6-imperial #aon-online{
  top: 0 !important;
  /* one step ABOVE the rail. #aon-online is written earlier in index.php than
     #g5-top, so at an equal z-index the bar — whose ::before is a 88%-opaque
     blurred plate — paints straight over the plaque's text. Measured: the
     glyphs vanished and only their glows survived. */
  z-index: calc(var(--g5-z-float) + 1) !important;
  height: 40px;
  padding: 0 var(--g5-s6) !important;
  gap: 9px !important;
  border-radius: 0 0 var(--g5-r-md) var(--g5-r-md) !important;
  border: 1px solid var(--g5-line) !important;
  border-top: 0 !important;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--g5-gold-3) 9%, transparent) 0%, transparent 52%),
    var(--g5-plate) !important;
  box-shadow:
    0 12px 26px -8px rgba(0,0,0,.65),
    0 0 30px -10px color-mix(in srgb, var(--g5-gold-3) 55%, transparent),
    var(--g5-bevel) !important;
  font: 600 10.5px/1 var(--g5-f-ui) !important;
  letter-spacing: var(--g5-track) !important;
  text-transform: uppercase;
  color: var(--g5-ink-3) !important;
  -webkit-backdrop-filter: blur(9px);
  backdrop-filter: blur(9px);
  pointer-events: none !important;
}

html body.g6-imperial #aon-online b{
  font: 800 16px/1 var(--g5-f-ui) !important;
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em !important;
  color: var(--g5-gold-2) !important;
  text-shadow: 0 0 14px color-mix(in srgb, var(--g5-gold-3) 60%, transparent) !important;
}

/* the beacon. index.php blinks the whole dot's opacity forever with no guard;
   that is replaced by a ring that expands once every 2.6s — transform+opacity
   only, so it stays on the compositor and never repaints the plaque. */
html body.g6-imperial #aon-online .dot{
  position: relative;
  width: 8px !important; height: 8px !important;
  background: var(--g5-ok) !important;
  box-shadow: 0 0 10px color-mix(in srgb, var(--g5-ok) 75%, transparent) !important;
  animation: none !important;
}
html body.g6-imperial #aon-online .dot::after{
  content:'';
  position: absolute; inset: -3px;
  border-radius: 50%;
  border: 1px solid var(--g5-ok);
  opacity: 0;
  animation: g5Beacon 2.6s var(--g5-ease-in-out) infinite;
}
@keyframes g5Beacon{
  0%        { transform: scale(.5);  opacity: .8 }
  60%, 100% { transform: scale(2);   opacity: 0  }
}

/* phones: no rail to hang from, and nothing may run continuously there */
@media (max-width: 868px){
  html body.g6-imperial #aon-online{
    top: 10px !important;
    height: 32px;
    padding: 0 15px !important;
    border-radius: var(--g5-r-pill) !important;
    border-top: 1px solid var(--g5-line) !important;
  }
  html body.g6-imperial #aon-online b{ font-size: 14px !important; }
  /* nothing continuous on a phone — both pings stop here, not only at 760px
     where the Discord CTA changes shape */
  html body.g6-imperial #aon-online .dot::after,
  html body.g6-imperial #aon-dc-gate .dc-gift::after{ animation: none; opacity: 0 }
}


/* ═══════════════════════════════════════════════════════════════════════════
   3 · THE FEATURE STRIP — the only place the page says what the game IS.
   Six web pills → six painted medallions on a centred ribbon. The medallions
   are the game's own building emblems (see the header), one per claim:

     storage  chest, grain, cut stone   → BUILD YOUR KINGDOM
     defense  castle, crossed spears    → RAISE MIGHTY ARMIES
     research the atlas + compass rose  → CONQUER & EXPAND
     trade    the golden scales         → RULE THE WORLD
     healing  the shared chalice        → FORGE ALLIANCES
     production hammer, anvil, sparks   → LIVE BATTLES

   aoe's plaque.jpg ground is deliberately left in place underneath.
   The data-toast contract is untouched: still <button data-toast>, still one
   text node, login2.js still binds them by attribute.
   ═══════════════════════════════════════════════════════════════════════════ */

html body.g6-imperial #g5-feats{
  position: relative;
  display: flex; flex-wrap: wrap;
  align-items: stretch; justify-content: center;
  gap: clamp(8px, .8vw, 13px) !important;
  padding: 16px clamp(16px, 2.4vw, 34px) clamp(16px, 2vh, 24px) !important;
}

/* the shelf the ribbon stands on */
html body.g6-imperial #g5-feats::before{
  content:'';
  position: absolute; left: 50%; top: 4px;
  width: min(1060px, 76vw); height: 1px;
  transform: translateX(-50%);
  background: linear-gradient(90deg,
    transparent, var(--g5-line) 24%, var(--g5-line-2) 50%, var(--g5-line) 76%, transparent);
  opacity: .5;
  pointer-events: none;
}

html body.g6-imperial #g5-feats .fcard{
  position: relative; z-index: 1;
  box-sizing: border-box;
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start;
  gap: 10px;
  flex: 0 0 auto;
  width: clamp(128px, 10.6vw, 168px);
  min-height: clamp(98px, 7.2vw, 116px);
  padding: 13px 10px 12px !important;
  border-radius: var(--g5-r-sm) !important;
  border: 1px solid var(--g5-ink-4) !important;
  border-top-color: var(--g5-line) !important;
  /* aoe's tooled-stone ground is kept, but tinted into the page's night+gold
     family — raw plaque.jpg reads mid-grey next to the near-black panels. */
  background-image:
    linear-gradient(180deg, color-mix(in srgb, var(--g5-gold-3) 8%, transparent), transparent 40%),
    linear-gradient(180deg, rgba(11,14,19,.74), rgba(5,7,10,.84)),
    url("/assets/login5/plaque.jpg") !important;
  background-size: auto, auto, cover !important;
  background-position: center, center, center !important;
  background-repeat: no-repeat, no-repeat, no-repeat !important;
  font: 700 clamp(9.5px, .58vw, 10.5px)/1.35 var(--g5-f-ui) !important;
  letter-spacing: var(--g5-track) !important;
  text-transform: uppercase;
  text-align: center;
  color: var(--g5-ink-2) !important;
  text-shadow: 0 1px 0 rgba(0,0,0,.9) !important;
  box-shadow:
    var(--g5-bevel),
    inset 0 -20px 28px -20px rgba(0,0,0,.85),
    var(--g5-e1) !important;
  transition: transform var(--g5-t-base) var(--g5-ease),
              border-color var(--g5-t-base) var(--g5-ease),
              box-shadow var(--g5-t-base) var(--g5-ease) !important;
}

/* <b> was an emoji; it becomes one tile of the medallion strip */
html body.g6-imperial #g5-feats .fcard b{
  display: block; flex: 0 0 auto;
  width: clamp(42px, 3.1vw, 54px);
  height: clamp(42px, 3.1vw, 54px);
  font-size: 0 !important;
  line-height: 0;
  color: transparent;
  background-image: url("/assets/login5/art/feat-medallions.png");
  background-repeat: no-repeat;
  background-size: 600% 100%;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,.75)) !important;
  transition: transform var(--g5-t-base) var(--g5-ease),
              filter var(--g5-t-base) var(--g5-ease);
}
/* #feat-glow is a <div>, so :nth-of-type counts the six <button>s alone */
html body.g6-imperial #g5-feats .fcard:nth-of-type(1) b{ background-position:   0% 50% }
html body.g6-imperial #g5-feats .fcard:nth-of-type(2) b{ background-position:  20% 50% }
html body.g6-imperial #g5-feats .fcard:nth-of-type(3) b{ background-position:  40% 50% }
html body.g6-imperial #g5-feats .fcard:nth-of-type(4) b{ background-position:  60% 50% }
html body.g6-imperial #g5-feats .fcard:nth-of-type(5) b{ background-position:  80% 50% }
html body.g6-imperial #g5-feats .fcard:nth-of-type(6) b{ background-position: 100% 50% }

html body.g6-imperial #g5-feats .fcard:hover{
  transform: translateY(-4px) !important;
  border-color: var(--g5-line-2) !important;
  /* aoe brightened the whole card with filter:brightness(1.12) — that also
     washed the medallion and forced a containing block. The lift is done with
     light instead, and the emblem gets its own treatment below. */
  filter: none !important;
  box-shadow:
    var(--g5-bevel),
    inset 0 -20px 28px -20px rgba(0,0,0,.8),
    var(--g5-e2),
    0 0 26px -8px color-mix(in srgb, var(--g5-gold-3) 65%, transparent) !important;
}
html body.g6-imperial #g5-feats .fcard:hover b{
  transform: scale(1.06);
  filter:
    drop-shadow(0 5px 10px rgba(0,0,0,.75))
    drop-shadow(0 0 12px color-mix(in srgb, var(--g5-gold-3) 60%, transparent)) !important;
}
html body.g6-imperial #g5-feats .fcard:active{ transform: translateY(-1px) !important; }
html body.g6-imperial #g5-feats .fcard:focus-visible{
  outline: 2px solid var(--g5-gold-3) !important;
  outline-offset: 3px !important;
}

/* ── the FEATURES nav button pulses the strip (login2.js adds .pulse to
   #feat-glow). login5.css had it display:none, so the affordance did nothing.
   It becomes a single gold sweep ACROSS the ribbon — one shot, transform only,
   pointer-events:none, and login2.js's contract (add/remove .pulse) is intact. */
html body.g6-imperial #g5-feats #feat-glow{
  display: block;
  position: absolute; z-index: 2;
  left: clamp(16px, 2.4vw, 34px); right: clamp(16px, 2.4vw, 34px);
  top: 18px; bottom: 10px;
  border-radius: var(--g5-r-lg);
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
html body.g6-imperial #g5-feats #feat-glow::before{
  content:'';
  position: absolute; top: 0; bottom: 0; left: 0; width: 38%;
  background: linear-gradient(100deg,
    transparent, color-mix(in srgb, var(--g5-gold-1) 44%, transparent), transparent);
  transform: translateX(-140%);
}
html body.g6-imperial #g5-feats #feat-glow.pulse{
  animation: g5FeatFade 1.25s linear 1 forwards;
}
html body.g6-imperial #g5-feats #feat-glow.pulse::before{
  animation: g5FeatSweep 1.25s var(--g5-ease) 1;
}
@keyframes g5FeatSweep{ from{ transform: translateX(-140%) } to{ transform: translateX(400%) } }
@keyframes g5FeatFade { 0%{ opacity:0 } 14%{ opacity:1 } 100%{ opacity:0 } }

/* ── SHORT VIEWPORTS — the same ribbon, laid on its side ──────────────────
   A 1080p browser gives ~980 CSS px of viewport and the gate above this strip
   already spends ~985 of them, so on a laptop the tall form is pushed under the
   fold. Below 900px of viewport the medallion moves beside the label: 80px of
   strip instead of ~150, same six claims, same art.
   (login5.css hides the strip outright below 780px — left alone: at that height
   the panels themselves no longer fit and the login form has to win.) */
@media (max-height: 900px){
  html body.g6-imperial #g5-feats{
    padding: 10px clamp(16px, 2.4vw, 34px) 12px !important;
  }
  html body.g6-imperial #g5-feats::before{ top: 0; }
  html body.g6-imperial #g5-feats .fcard{
    flex-direction: row;
    align-items: center; justify-content: flex-start;
    gap: 9px;
    width: auto;
    min-height: 0;
    padding: 9px 14px 9px 10px !important;
    text-align: left;
  }
  html body.g6-imperial #g5-feats .fcard b{
    width: 34px; height: 34px;
  }
  html body.g6-imperial #g5-feats #feat-glow{ top: 8px; bottom: 8px; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   4 · THE DISCORD CTA — the same object as the rest of the page.
   It was Discord blurple with a bright yellow badge: the one element on a
   medieval title screen that looked like a web widget. The mark is what carries
   the recognition, so the mark stays (white-on-dark is a sanctioned Discord
   treatment) and the container becomes forged iron with a gold rim.
   ═══════════════════════════════════════════════════════════════════════════ */

html body.g6-imperial #aon-dc-gate{
  right: clamp(12px, 1.4vw, 22px) !important;
  bottom: clamp(12px, 1.4vw, 22px) !important;
  z-index: var(--g5-z-float) !important;   /* was 100000 — above the modals */
  gap: 10px !important;
  padding: 10px 14px !important;
  border-radius: var(--g5-r-md) !important;
  border: 1px solid var(--g5-line) !important;
  background: var(--g5-plate-hi) !important;
  color: var(--g5-ink) !important;
  font: 700 11.5px/1 var(--g5-f-ui) !important;
  letter-spacing: var(--g5-track) !important;
  text-transform: uppercase;
  box-shadow: var(--g5-e2), 0 0 0 1px rgba(0,0,0,.55) !important;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: transform var(--g5-t-base) var(--g5-ease),
              box-shadow var(--g5-t-base) var(--g5-ease),
              border-color var(--g5-t-base) var(--g5-ease) !important;
}
html body.g6-imperial #aon-dc-gate:hover{
  transform: translateY(-3px) !important;
  border-color: var(--g5-line-hot) !important;
  box-shadow: var(--g5-e3), var(--g5-glow-gold) !important;
}
html body.g6-imperial #aon-dc-gate:focus-visible{
  outline: 2px solid var(--g5-gold-3) !important;
  outline-offset: 3px !important;
}
html body.g6-imperial #aon-dc-gate .dc-t{ color: var(--g5-ink-2); }

/* the gift token. index.php pulsed its BOX-SHADOW forever and unguarded — a
   full repaint per frame on top of a live WebGL scene. Killed; a scaling ring
   replaces it, and it stops on phones and under reduced motion. */
html body.g6-imperial #aon-dc-gate .dc-gift{
  position: relative;
  padding: 4px 8px !important;
  border-radius: var(--g5-r-xs) !important;
  background: linear-gradient(180deg,
    var(--g5-gold-2), var(--g5-gold-3) 52%, var(--g5-gold-4)) !important;
  color: var(--g5-ink-on) !important;
  font: 800 9px/1.15 var(--g5-f-ui) !important;
  letter-spacing: var(--g5-track) !important;
  text-transform: uppercase;
  box-shadow: var(--g5-bevel), 0 2px 6px rgba(0,0,0,.55) !important;
  animation: none !important;
}
html body.g6-imperial #aon-dc-gate .dc-gift::after{
  content:'';
  position: absolute; inset: -2px;
  border-radius: var(--g5-r-sm);
  border: 1px solid var(--g5-gold-2);
  opacity: 0;
  pointer-events: none;
  animation: g5Ping 3.2s var(--g5-ease-in-out) infinite;
}
@keyframes g5Ping{
  0%        { transform: scale(.94); opacity: .65 }
  55%, 100% { transform: scale(1.3); opacity: 0   }
}

/* ── it must never sit on the feature strip ────────────────────────────────
   The strip is centred and ~1073px wide; this button is pinned bottom-right and
   ~340px wide. Their edges meet at about 1795px of viewport, and below that the
   CTA covers LIVE BATTLES. The six claims are the page's pitch and the CTA is a
   secondary door, so the CTA yields: it becomes the same disc phones get, which
   keeps both the entry point and the gold offer dot.
   Scoped to the heights where the strip actually exists — login5.css drops
   #g5-feats below 780px of viewport, and there the full button is welcome. */
@media (max-width: 1800px) and (min-height: 781px){
  html body.g6-imperial #aon-dc-gate{
    width: 46px; height: 46px;
    padding: 0 !important;
    justify-content: center;
    border-radius: var(--g5-r-pill) !important;
  }
  html body.g6-imperial #aon-dc-gate .dc-t{ display: none !important; }
  html body.g6-imperial #aon-dc-gate .dc-gift{
    position: absolute; top: -3px; right: -3px;
    width: 12px; height: 12px;
    padding: 0 !important;
    border-radius: 50% !important;
    font-size: 0 !important;
    color: transparent !important;
    overflow: hidden;
  }
}

/* phones + narrow tablets: a disc that covers as little of the page as
   possible, with the offer reduced to a gold notification dot */
@media (max-width: 760px){
  html body.g6-imperial #aon-dc-gate{
    width: 46px; height: 46px;
    padding: 0 !important;
    justify-content: center;
    border-radius: var(--g5-r-pill) !important;
  }
  html body.g6-imperial #aon-dc-gate .dc-t{ display: none !important; }
  html body.g6-imperial #aon-dc-gate .dc-gift{
    position: absolute; top: -3px; right: -3px;
    width: 12px; height: 12px;
    padding: 0 !important;
    border-radius: 50% !important;
    font-size: 0 !important;
    color: transparent !important;
    overflow: hidden;
  }
  html body.g6-imperial #aon-dc-gate .dc-gift::after{ animation: none; opacity: 0 }
}


/* ═══════════════════════════════════════════════════════════════════════════
   5 · THE SEO FOOTER — deliberate crawlable copy, so every word stays in the
   DOM. It just stops looking like 2003: a struck top edge, a real measure on
   the prose, an engraved section label, and the keyword list set as ordered
   type instead of one 3,000-character run-on paragraph.
   Everything here needs `!important`: the <footer> and its children carry
   inline style="" attributes in index.php.
   ═══════════════════════════════════════════════════════════════════════════ */

html body.g6-imperial #seo-footer{
  position: relative !important;
  background: linear-gradient(180deg, var(--g5-iron-3) 0%, var(--g5-night) 100%) !important;
  border-top: 0 !important;
  padding: clamp(34px, 4vw, 56px) clamp(18px, 3vw, 40px) clamp(30px, 3vw, 46px) !important;
  font: 500 13px/1.75 var(--g5-f-ui) !important;
  color: var(--g5-ink-3) !important;
}
html body.g6-imperial #seo-footer::before{
  content:'';
  position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: linear-gradient(90deg,
    transparent, var(--g5-line) 18%, var(--g5-line-2) 50%, var(--g5-line) 82%, transparent);
  opacity: .75;
}
html body.g6-imperial #seo-footer > div{
  max-width: 1180px !important;
}
html body.g6-imperial #seo-footer h1{
  margin: 0 0 var(--g5-s5) !important;
  max-width: 46ch;
  font: 700 clamp(18px, 1.5vw, 25px)/1.24 var(--g5-f-display) !important;
  letter-spacing: .035em !important;
  color: var(--g5-gold-3) !important;
  text-shadow: 0 2px 10px rgba(0,0,0,.6) !important;
}
html body.g6-imperial #seo-footer p{
  margin: 0 0 var(--g5-s4) !important;
  max-width: 88ch;
  color: var(--g5-ink-3) !important;
}
html body.g6-imperial #seo-footer h2{
  display: flex; align-items: center; gap: var(--g5-s4);
  margin: var(--g5-s8) 0 var(--g5-s5) !important;
  font: 700 10px/1 var(--g5-f-ui) !important;
  letter-spacing: var(--g5-track-2) !important;
  text-transform: uppercase !important;
  color: var(--g5-ink-3) !important;
}
html body.g6-imperial #seo-footer h2::after{
  content:'';
  flex: 1 1 auto; height: 1px;
  background: linear-gradient(90deg, var(--g5-line), transparent);
}
html body.g6-imperial #seo-footer nav{
  color: var(--g5-ink-3) !important;
  font: 500 11.5px/1 var(--g5-f-ui) !important;
}
/* 10-chrome.js re-wraps the ` · `-separated keywords into spans — same words,
   same order, same text, just addressable. Non-interactive, so no hover state. */
html body.g6-imperial #seo-footer .g5-kw{
  display: inline-block;
  margin: 0 4px 6px 0;
  padding: 4px 10px;
  border-radius: var(--g5-r-pill);
  border: 1px solid color-mix(in srgb, var(--g5-ink-3) 15%, transparent);
  background: color-mix(in srgb, var(--g5-ink-3) 5%, transparent);
  color: var(--g5-ink-3);
  white-space: nowrap;
}

/* ── the trust / colophon bar, appended by 10-chrome.js ─────────────────── */
html body.g6-imperial #g5-fmeta{
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--g5-s4) var(--g5-s7);
  margin-top: clamp(26px, 3vw, 42px);
  padding-top: var(--g5-s6);
  border-top: 1px solid color-mix(in srgb, var(--g5-ink-3) 14%, transparent);
  font: 600 11px/1.5 var(--g5-f-ui);
  color: var(--g5-ink-3);
}
html body.g6-imperial #g5-fmeta .fm-mark{
  font: 700 12px/1 var(--g5-f-display);
  letter-spacing: var(--g5-track-2);
  color: var(--g5-gold-3);
}
html body.g6-imperial #g5-fmeta .fm-trust{
  display: inline-flex; align-items: center; gap: 8px;
}
html body.g6-imperial #g5-fmeta .fm-trust svg{
  width: 11px; height: 13px; flex: 0 0 auto;
  fill: var(--g5-gold-4);
}
html body.g6-imperial #g5-fmeta .fm-sp{ flex: 1 1 auto; }
html body.g6-imperial #g5-fmeta a{
  color: var(--g5-ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--g5-ink-4);
  transition: color var(--g5-t-fast) var(--g5-ease),
              border-color var(--g5-t-fast) var(--g5-ease);
}
html body.g6-imperial #g5-fmeta a:hover{
  color: var(--g5-gold-2);
  border-bottom-color: var(--g5-line-2);
}
html body.g6-imperial #g5-fmeta a:focus-visible{
  outline: 2px solid var(--g5-gold-3);
  outline-offset: 3px;
  border-radius: var(--g5-r-xs);
}


/* ═══════════════════════════════════════════════════════════════════════════
   6 · REDUCED MOTION — every raw `animation:` above, off. Transitions keyed to
   --g5-t-* are already neutralised by tokens.css.
   The FEATURES pulse keeps a plain cross-fade (no travel): the button has to
   answer, and an opacity change is not motion.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  html body.g6-imperial #aon-online .dot::after,
  html body.g6-imperial #aon-dc-gate .dc-gift::after{
    animation: none !important;
    opacity: 0 !important;
  }
  html body.g6-imperial #g5-feats #feat-glow::before{
    animation: none !important;
    transform: none !important;
    left: 0; width: 100%;
  }
  html body.g6-imperial #g5-feats .fcard,
  html body.g6-imperial #g5-feats .fcard b,
  html body.g6-imperial #aon-dc-gate{
    transition: none !important;
  }
}

/* ══ gate5 · parts/11-fold.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 11 — THE FOLD                     assets/login5/parts/11-fold.css
   ───────────────────────────────────────────────────────────────────────────
   The consolidation pass. Ten agents each verified their own component and
   every one of them is right in isolation; this file owns the one fact none of
   them could see — the VERTICAL BUDGET, which only exists once all ten are
   stacked.

   Measured with tools/gate5_probe.py before writing a line. Gate bottom vs
   viewport height, four real desktop sizes:

       1920×1080  →  1137 vs  983   the whole feature strip below the fold
       2292×958   →   993 vs  861   ditto
       1600×900   →   886 vs  803   ditto
       1366×768   →   769 vs  671   ditto

   So on EVERY desktop size the only place the page says what the game is was
   under the fold. Not one pass caused it: top bar + hero + panels + strip each
   sized itself sensibly and the sum overflowed.

   Two rules for everything below:
     · Retune, never restructure. Where a pass published a knob (part 03's
       --h-* variables, part 06's max-height) this file turns THAT knob, so
       their internal proportions survive and only the scale changes.
     · Desktop only. #mob is a scrolling column by design and part 08 owns it.

   Specificity: `html body #id` (1,1,2) with !important, because
   login5-imperial.css and login5-aoe.css both load AFTER the aggregator and
   both fire !important at these ids. Being the last part is not enough.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ── 1 · THE HERO GIVES WAY FIRST ─────────────────────────────────────────
   It is the element with the least information per pixel, so it pays first.
   Part 03 drives its whole lockup off three variables — emblem, cap size and
   rule length — so retuning those three scales the mark and keeps every
   proportion inside it. The floors are 03's own: the mark never drops below
   the size it was designed to survive at. */
@media (min-width: 869px) and (max-height: 1100px){
  html body #g5-hero{
    --h-emb:  clamp(56px, min(5.2vw, 8.8vh), 104px);
    --h-word: clamp(30px, min(3.8vw, 6.2vh),  78px);
    --h-rule: clamp(44px, 6.2vw, 118px);
    margin: clamp(8px, 2.4vh, 26px) 0 clamp(6px, 1.5vh, 15px) !important;
  }
  html body #g5-panels{ margin-bottom: clamp(8px, 1.4vh, 16px) !important; }
}
@media (min-width: 869px) and (max-height: 880px){
  html body #g5-hero{ margin: clamp(6px, 1.8vh, 20px) 0 clamp(5px, 1.1vh, 12px) !important; }
  html body #g5-panels{ margin-bottom: clamp(6px, 1vh, 12px) !important; }
}


/* ── 2 · THE NATION WALL ABSORBS THE REST ─────────────────────────────────
   Part 06 caps the wall at min(404px, 43vh) and deliberately half-cuts a row
   at the fold, under its mask, as the "there is more" signal. That signal
   works at any height — the cap is simply the largest single number in the
   register panel, so it is where the space is. Tightened to 32vh; the mask,
   the sticky lintels and the scroll behaviour are untouched, and the half-cut
   row survives because the tile height did not change. */
@media (min-width: 869px) and (max-height: 1100px){
  html body #nation-grid{ max-height: min(320px, 32vh)   !important; }
}
@media (min-width: 869px) and (max-height:  880px){
  html body #nation-grid{ max-height: min(292px, 29.5vh) !important; }
}
@media (min-width: 869px) and (max-height:  800px){
  html body #nation-grid{ max-height: min(268px, 28vh)   !important; }
}
@media (min-width: 869px) and (max-height:  720px){
  html body #nation-grid{ max-height: min(240px, 27vh)   !important; }
}


/* ── 3 · THE FEATURE STRIP, LAID ON ITS SIDE SOONER ───────────────────────
   Part 10 built a compact form — medallion beside the label, ~76px instead of
   ~152 — and gated it at `max-height: 900px`. A 1080p browser reports 983, so
   1920×1080, the single most common desktop size there is, got the TALL form
   and paid 152px for it while having the least room to spare.

   These declarations are part 10's, restated verbatim for the 901–1010 band
   only. Duplication rather than a rewrite is deliberate: 10 owns the design,
   this file owns only WHEN it switches. If 10's compact form changes, change
   it there and mirror it here. */
@media (min-height: 901px) and (max-height: 1010px) and (min-width: 869px){
  html body.g6-imperial #g5-feats{
    padding: 10px clamp(16px, 2.4vw, 34px) 12px !important;
  }
  html body.g6-imperial #g5-feats::before{ top: 0; }
  html body.g6-imperial #g5-feats .fcard{
    flex-direction: row;
    align-items: center; justify-content: flex-start;
    gap: 9px;
    width: auto;
    min-height: 0;
    padding: 9px 14px 9px 10px !important;
    text-align: left;
  }
  html body.g6-imperial #g5-feats .fcard b{ width: 34px; height: 34px; }
  html body.g6-imperial #g5-feats #feat-glow{ top: 8px; bottom: 8px; }
}


/* ── 3b · THE PANELS COMPACT SOONER TOO ───────────────────────────────────
   Once the wall was tightened the panel row stopped shrinking with it: at
   `align-items:stretch` the row equalises to the TALLER panel, and below
   ~300px of wall that is the LOGIN panel, whose height is fields and CTA —
   nothing this file should touch.

   Part 04 already drew a compact panel (tighter padding, a smaller plaque,
   a shorter rule) and gated it at `max-height:780px`. Same story as the strip:
   the band that actually needs it starts higher. Restated verbatim for the
   781–880 band; 04 owns the design, this file owns only WHEN. */
@media (min-width: 869px) and (min-height: 781px) and (max-height: 880px){
  #g5-panels .g5-panel{ padding:8px 15px 10px !important; }
  #g5-panels .g5-panel h2{
    margin:0 0 6px !important;
    padding:2px 6px 3px !important;
    font-size:21px !important;
    border-width:7px 41px 8px !important;
    border-image:var(--g5p-plaque) 10 63 12 63 fill / 7px 41px 8px stretch !important;
  }
  #g5-panels .g5-panel .g5-rule{ height:14px !important; margin-bottom:9px !important; }
}

/* the shortest desktop band — 1366×768 and friends. The strip is already gone
   by here (section 4); the last few pixels come from the hero, which is the
   right place for them: at this height the mark has done its job the moment
   the page paints. */
@media (min-width: 869px) and (max-height: 720px){
  html body #g5-hero{
    --h-emb:  clamp(50px, min(4.6vw, 7.6vh), 104px);
    --h-word: clamp(28px, min(3.4vw, 5.4vh),  78px);
  }
}


/* ── 4 · BELOW 780px OF VIEWPORT THE STRIP GOES AWAY ──────────────────────
   login5.css has always said `@media (max-height:780px){#g5-feats{display:none}}`
   — at that height the login form has to win — and part 10 explicitly left it
   alone. The probe found the strip rendering anyway at 1366×768: a later
   sheet re-declares display on the id, and login5.css's rule carries no
   !important, so it lost. Restoring the intent, not inventing it.

   `display` on #g5-feats is safe to force: nothing in login2.js toggles it.
   (#feat-glow inside it is toggled by CLASS, .pulse, not by display — and a
   strip that isn't on screen has nothing to glow.) */
@media (max-height: 780px) and (min-width: 869px){
  html body #g5-feats{ display: none !important; }
}


/* ── 5 · REDUCED MOTION ───────────────────────────────────────────────────
   Nothing here animates; every value is a static length. Listed so the next
   reader does not go looking. */

/* ══ gate5 · parts/12-scene.css ══ */
/* ═══════════════════════════════════════════════════════════════════════════
   GATE 5 · PART 12 — SCENE BALANCE                assets/login5/parts/12-scene.css
   ───────────────────────────────────────────────────────────────────────────
   Consolidation. Part 02's grade is right; it was simply tuned against a
   DIFFERENT scene than the one now underneath it.

   02 and 01 ran in parallel. While 02 was measuring, gate3d.js still had the
   bug 01 found late and fixed: three.js sizes GPU storage with texStorage2D
   (immutable) from whatever a texture holds on its FIRST upload, and the
   loader seeded a 4×4 colour before swapping the real image in — so the GPU
   kept the 4×4. Every wall, tower, keep and the ground were rendering a flat
   seed colour, and nothing said so in the console.

   02 was therefore grading a scene with no material in it. Its own report says
   as much without knowing why: "the 3D scene is FLAT", "god rays cannot read
   over a bright sky", "soft-light cannot overrule a saturated noon blue". Each
   layer was pushed hard to manufacture depth the scene wasn't providing.

   01 then gave the scene real stone, real emission maps in the windows, IBL
   off a painted sky, and 1150 units of fog doing the aerial perspective in 3D
   where it belongs. Rendered side by side (`tools/_gate5/_look.png` vs
   `_no02.png`, 1920×1080), the compensation is now over-applied: the city
   silhouette that 01 composed to sit between the panels is buried under haze.

   So this file only turns three dials down. It changes no colour, no geometry,
   no blend mode, no animation — 02's grade, its split-tone, its shaft geometry
   and its parallax are all exactly as authored, and turning these back up
   restores its render bit for bit. Nothing here is a disagreement with 02.
   ═══════════════════════════════════════════════════════════════════════════ */


/* THE SHAFTS — the loudest of the three. `screen` over a scene that now has
   its own highlights adds where the sun already put light, so the same sheet
   reads twice as strong as it did over flat colour. The shafts still cross
   the sky; they no longer fill it. */
html.g5-atm #g6-rays{ opacity: .40 !important; }

/* THE SPLIT-TONE — soft-light tints without painting over, which is why 02
   could safely run it at .88 when the stone had no value of its own to
   protect. It has one now. */
html.g5-atm #g6-grain{ opacity: .55 !important; }

/* THE HORIZON HAZE — 01's fog far plane is at 1150 and the ridge line already
   separates from the city in 3D. This band is now a top-up, not the effect. */
html.g5-atm #g7-fog{ opacity: .24 !important; }


/* Embers, motes, vignette and the frame are untouched: they sit ON the scene
   rather than over it, and the texture bug never affected how they read. */
