/* ==========================================================================
   Zodiac Guardians 鈥?3D carousel section
   GENERATED by wordpress\build-guardians-embed.ps1. Do not edit by hand:
   re-run the script after changing benmingfo-3d/index.html.

   Scoped to .sa-guardians so the standalone stylesheet cannot reach the host
   theme, and the host theme cannot reach into the carousel.
   ========================================================================== */

/* The standalone :root palette, re-keyed onto the section wrapper. The JS
   writes live values (--card-w, --rig-lift, --title-bottom) to this same
   element, so both the defaults and the updates resolve here. */
.sa-guardians{

  --gold-1:#f6e6b4;
  --gold-2:#d9b662;
  --gold-3:#a9812f;
  --ink-1:#0a0908;
  --line:rgba(217,182,98,.28);
  --line-soft:rgba(217,182,98,.14);
  --text:rgba(240,232,214,.92);
  --text-dim:rgba(226,214,188,.55);
  --card-w:252px;
  --card-h:378px;
  /* How far the ring is raised inside the stage. Negative is up; set in px
     so the model lands in the same place at every viewport height. */
  --rig-lift:-78px;
  --title-bottom:150px;
  --hint-bottom:96px;
  --ease:cubic-bezier(.22,.61,.36,1);

}

/* The standalone page reset, scoped. ox-sizing is deliberately applied to
   the section's whole subtree; the margin/padding zeroing is what the host page
   must NOT inherit, so it stays inside. */
.sa-guardians, .sa-guardians *, .sa-guardians *::before, .sa-guardians *::after{
  box-sizing:border-box;
}
.sa-guardians *{margin:0;padding:0;}

/* ============================================================
   Zodiac Guardians
   Carousel mechanics adapted from Hoang Tran's 3D carousel
   (codepen.io/hoanghien0410/pen/MMPaqm, MIT) — tilted camera,
   full-orbit drag with inertia, floor plane, wheel-to-zoom.
   Single static file. No external libraries or webfonts.
   ============================================================ */



/* ------------------------------------------------------------
   PAGE-LEVEL RESET  (standalone only; stripped when embedded)
   ------------------------------------------------------------
   These four rules belong to a document the carousel owns. Embedded in a host
   page they are actively destructive: the `*` reset would zero the host's own
   margins and padding site-wide, `html,body{height:100%}` would fight the host's
   layout, and `body{overflow:hidden}` would lock the host page so it cannot
   scroll at all. The build script removes everything between these markers and
   re-adds scoped equivalents under `.sa-guardians`.

   Each marker must be a COMPLETE comment of its own — the strip is a regex that
   removes marker-to-marker, so a marker embedded in a longer comment would cut
   that comment in half and leave the stylesheet unterminated. */


/* ---------- Backdrop ---------- */
.bg{position:fixed;inset:0;z-index:0;pointer-events:none;}
.bg::before{
  content:"";position:absolute;inset:0;
  background:
    radial-gradient(120% 78% at 50% -12%, rgba(217,182,98,.20) 0%, rgba(217,182,98,.07) 34%, transparent 66%),
    radial-gradient(58% 44% at 50% 108%, rgba(217,182,98,.13) 0%, transparent 70%),
    radial-gradient(90% 90% at 50% 50%, #16130f 0%, #0a0908 58%, #050504 100%);
}
.bg::after{
  content:"";position:absolute;inset:0;opacity:.05;
  background-image:
    repeating-linear-gradient(90deg, rgba(217,182,98,.55) 0 1px, transparent 1px 128px),
    repeating-linear-gradient(0deg, rgba(217,182,98,.35) 0 1px, transparent 1px 128px);
  mask-image:radial-gradient(70% 60% at 50% 45%, #000 0%, transparent 82%);
  -webkit-mask-image:radial-gradient(70% 60% at 50% 45%, #000 0%, transparent 82%);
}
#embers{position:fixed;inset:0;z-index:1;pointer-events:none;}

/* ---------- Layout ----------
   Two arrangements:
     wide  (>=1100px)  — the desktop split: stage beside the details panel.
     app   (< 1100px)  — a fixed-height app shell: header, full-bleed stage,
                         a persistent chip rail, and a bottom sheet holding
                         the details. The page itself never scrolls, so the
                         3D model always owns the screen. */
.app{
  position:relative;z-index:2;
  height:100%;
  display:grid;
  grid-template-columns:1fr 372px;
  grid-template-rows:auto 1fr auto;
  grid-template-areas:
    "head  head"
    "stage info"
    "foot  info";
}

/* ---------- Header ---------- */
.head{
  grid-area:head;
  display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:18px clamp(16px,3vw,38px) 10px;
}
.brand{display:flex;align-items:baseline;gap:13px;min-width:0;flex-wrap:wrap;}
.brand .mark{
  font-size:17px;letter-spacing:.3em;text-transform:uppercase;
  background:linear-gradient(180deg,var(--gold-1),var(--gold-2) 46%,var(--gold-3));
  -webkit-background-clip:text;background-clip:text;color:transparent;
  white-space:nowrap;
}
.brand .sub{
  font-size:10.5px;letter-spacing:.2em;color:var(--text-dim);
  text-transform:uppercase;white-space:nowrap;
}
/* Aligns the panel eyebrow with the site title on wide screens */
.panel-title{
  width:372px;flex:none;
  padding-right:clamp(16px,2.4vw,30px);
  font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--text-dim);
}
@media (max-width:900px){
  .panel-title{display:none;}
  .head{padding:14px 14px 8px;}
  .brand{gap:9px;flex-direction:column;align-items:flex-start;}
  .brand .mark{font-size:14px;letter-spacing:.22em;}
  .brand .sub{font-size:9px;letter-spacing:.14em;}
}

/* ---------- Stage ---------- */
.stage{
  grid-area:stage;position:relative;
  display:flex;align-items:center;justify-content:center;
  perspective:1100px;perspective-origin:50% 42%;
  min-height:0;
  cursor:grab;touch-action:pan-y;
  overflow:hidden;
  user-select:none;-webkit-user-select:none;
}
.stage.dragging{cursor:grabbing;}

/* Camera rig: #drag carries pitch + yaw, #spin carries the ring.
   Lifted above centre so the statues sit high in the stage and the floor
   label plus controls get their own space underneath. */
#drag{
  position:relative;
  width:var(--card-w);height:var(--card-h);
  transform-style:preserve-3d;
  transform:translateY(var(--rig-lift)) rotateX(-10deg);
  will-change:transform;
}
#spin{
  position:absolute;inset:0;
  transform-style:preserve-3d;
}

/* Floor plane, lying flat under the ring (from the reference) */
#ground{
  position:absolute;top:calc(100% + 70px);left:50%;
  width:calc(var(--card-w) * 4.6);height:calc(var(--card-w) * 4.6);
  transform:translate(-50%,-50%) rotateX(90deg);
  border-radius:50%;
  background:radial-gradient(closest-side, rgba(217,182,98,.20), rgba(217,182,98,.07) 46%, transparent 78%);
  pointer-events:none;
}
/* Name of the current guardian, laid on the floor in front of the ring.
   Kept outside the 3D rig: inside it, the floor swings behind the front
   card and the big front card would always occlude the text. */
.ground-title{
  position:absolute;left:50%;bottom:var(--title-bottom,150px);z-index:106;
  transform:translateX(-50%) perspective(760px) rotateX(46deg);
  transform-origin:50% 100%;
  white-space:nowrap;pointer-events:none;text-align:center;
  font-size:26px;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(246,230,180,.95);
  text-shadow:0 0 22px rgba(217,182,98,.85), 0 0 54px rgba(217,182,98,.45);
}

/* ---------- Cards (image only — no captions) ---------- */
.card{
  position:absolute;
  left:50%;top:50%;
  width:var(--card-w);height:var(--card-h);
  margin-left:calc(var(--card-w) / -2);
  margin-top:calc(var(--card-h) / -2);
  transform-style:preserve-3d;
  will-change:transform,opacity,filter;
  transition:opacity .3s linear, filter .3s linear;
}
.card-inner{
  position:absolute;inset:0;
  overflow:hidden;
  border-radius:2px;
  background:#0d0b09;
  border:1px solid var(--line);
  box-shadow:
    0 0 0 1px rgba(0,0,0,.6) inset,
    0 22px 48px -18px rgba(0,0,0,.9),
    0 0 34px -6px rgba(217,182,98,.16);
}
.card-img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 42%;
  display:block;
  filter:saturate(1.04) contrast(1.03);
  pointer-events:none;
  -webkit-user-drag:none;
}
/* gold rim + faint glass sheen */
.card-inner::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(180deg, rgba(246,230,180,.16) 0%, transparent 14%),
    linear-gradient(0deg, rgba(6,5,4,.50) 0%, rgba(6,5,4,.18) 13%, transparent 32%),
    radial-gradient(80% 60% at 50% 12%, rgba(217,182,98,.12), transparent 70%);
}
.card-frame{
  position:absolute;inset:9px;pointer-events:none;
  border:1px solid rgba(217,182,98,.30);
  box-shadow:0 0 0 1px rgba(0,0,0,.35) inset;
}
.card-frame::before,.card-frame::after{
  content:"";position:absolute;width:9px;height:9px;border:1px solid var(--gold-2);
}
.card-frame::before{top:-1px;left:-1px;border-right:0;border-bottom:0;}
.card-frame::after{bottom:-1px;right:-1px;border-left:0;border-top:0;}

/* Reflection (the reference uses -webkit-box-reflect; this works everywhere) */
.card-reflect{
  position:absolute;top:calc(100% + 6px);left:0;
  width:var(--card-w);height:calc(var(--card-h) * .46);
  background-image:var(--img);background-size:cover;background-position:50% 42%;
  transform:scaleY(-1);transform-origin:top center;
  opacity:.22;filter:blur(1.6px) saturate(.9);pointer-events:none;
  mask-image:linear-gradient(0deg,transparent 4%,rgba(0,0,0,.85) 96%);
  -webkit-mask-image:linear-gradient(0deg,transparent 4%,rgba(0,0,0,.85) 96%);
}
.card.is-front .card-inner{
  border-color:rgba(246,230,180,.6);
  box-shadow:
    0 0 0 1px rgba(0,0,0,.6) inset,
    0 30px 62px -20px rgba(0,0,0,.95),
    0 0 62px -6px rgba(217,182,98,.42);
}
.card.is-front .card-reflect{opacity:.4;}
/* Depth cues without blur: dim and fade the cards swinging away from the
   front, and let a short transition smooth the hand-over between them. */
.card{transition:opacity .28s linear, filter .28s linear;}
/* ...except while fitRadius() is measuring. That sweep walks the ring through
   four phases and calls render() on each, so every card's opacity is retargeted
   dozens of times in a few milliseconds. With the transition live, those
   targets are all queued and chased rather than applied, so the cards spend the
   whole sweep sliding between opacity values instead of settling on the final
   one — which is why the stage could paint as an empty black panel while the
   model was being re-fitted. Measurements must be immediate, not animated. */
.app.measuring .card{transition:none;}

/* ---------- Auto-rotate pill + zoom hint ----------
   z-index 120 clears the 3D cards, whose own z-index runs to ~150. */
.controls{
  position:absolute;left:50%;bottom:12px;transform:translateX(-50%);
  display:flex;align-items:center;gap:8px;z-index:120;
  padding:5px;border-radius:999px;
  background:rgba(12,10,8,.72);
  border:1px solid var(--line-soft);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
.btn{
  appearance:none;border:1px solid transparent;background:transparent;
  color:var(--text-dim);font-family:inherit;
  height:34px;border-radius:999px;
  display:flex;align-items:center;gap:7px;padding:0 16px;
  font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  cursor:pointer;transition:.26s var(--ease);
}
.btn:hover{color:var(--gold-1);border-color:var(--line);background:rgba(217,182,98,.08);}
.btn:focus-visible{outline:1px solid var(--gold-2);outline-offset:2px;}
.btn[aria-pressed="true"]{color:var(--gold-1);border-color:var(--line);background:rgba(217,182,98,.10);}
.btn svg{width:15px;height:15px;display:block;}

/* ---------- Info panel ---------- */
.info{
  grid-area:info;
  position:relative;
  margin:6px clamp(16px,2.4vw,30px) clamp(16px,2.4vw,30px) 0;
  padding:24px 24px 22px;
  border:1px solid var(--line-soft);
  background:
    linear-gradient(180deg, rgba(217,182,98,.055), transparent 30%),
    rgba(11,10,8,.72);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  display:flex;flex-direction:column;
  min-height:0;
  /* overflow-y:auto alone forces overflow-x to compute to auto, and the corner
     accents below are deliberately offset to -1px so they sit ON the border.
     That 1px is enough to raise a horizontal scrollbar across the panel footer.
     Clipping the x axis keeps the accents and loses the scrollbar. */
  overflow-y:auto;overflow-x:hidden;
  scrollbar-width:thin;scrollbar-color:rgba(217,182,98,.3) transparent;
}
/* The sheet head and body exist only for the app shell; on the wide layout
   the panel is always open, so the toggle and the wrapper are neutralised. */
.sheet-head{display:none;}
.sheet-body{display:contents;}
@media (max-width:900px){.info{margin:0 clamp(14px,4vw,24px) 14px;}}
.info::-webkit-scrollbar{width:6px;}
.info::-webkit-scrollbar-thumb{background:rgba(217,182,98,.26);border-radius:3px;}

/* The panel is a full-height column, but its content is much shorter than the
   box: at 1080p the fields ended at y=652 while the panel ran to 993, leaving
   341px of empty bordered box in the bottom-right corner — the void that made
   the layout read as lopsided, because the chip rail beside it does fill that
   height.
   Let the four detail fields share the leftover height instead, each keeping
   its label and value centred together as one block (the divider lines then
   sit evenly down the panel). Expanding the panel's own children with
   space-between would instead wedge a gap between the title and its subtitle,
   so the growth belongs on the fields. */
@media (min-width:1100px){
  .info .field{
    flex:1 1 auto;
    display:flex;flex-direction:column;justify-content:center;
  }
}

.info .corner{position:absolute;width:12px;height:12px;border:1px solid var(--gold-2);opacity:.55;}
.info .corner.tl{top:-1px;left:-1px;border-right:0;border-bottom:0;}
.info .corner.tr{top:-1px;right:-1px;border-left:0;border-bottom:0;}
.info .corner.bl{bottom:-1px;left:-1px;border-right:0;border-top:0;}
.info .corner.br{bottom:-1px;right:-1px;border-left:0;border-top:0;}

.info .zodiac-line{
  font-size:10.5px;letter-spacing:.26em;text-transform:uppercase;
  color:var(--gold-2);margin-bottom:10px;
}
.info h2{
  font-size:27px;font-weight:600;line-height:1.24;
  background:linear-gradient(180deg,#fbf3dc,var(--gold-2) 52%,var(--gold-3));
  -webkit-background-clip:text;background-clip:text;color:transparent;
  margin-bottom:7px;
}
.info .sanskrit{
  font-size:11.5px;letter-spacing:.12em;color:var(--text-dim);
  font-style:italic;margin-bottom:14px;
}
.info .rank{
  font-size:10px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--text-dim);margin-bottom:16px;
}
.info .seed{
  display:flex;align-items:center;gap:12px;
  padding:12px 14px;margin-bottom:16px;
  border:1px solid var(--line-soft);
  background:radial-gradient(90% 130% at 50% 40%,rgba(217,182,98,.13),transparent 72%);
}
.info .seed .glyph{
  /* The seed syllables ship as black artwork on transparency. They are shown
     with a plain <img> recoloured by a CSS filter, NOT as a CSS mask: under
     file:// a masked image is cross-origin, the mask silently resolves to
     nothing and the glyph disappears (verified in-browser). A filtered <img>
     works everywhere, including a double-clicked local file. */
  width:48px;height:48px;flex:0 0 48px;
  display:flex;align-items:center;justify-content:center;
}
.info .seed .glyph img{
  width:100%;height:100%;display:block;object-fit:contain;
  filter:invert(78%) sepia(38%) saturate(560%) hue-rotate(2deg) brightness(96%) contrast(92%)
         drop-shadow(0 0 8px rgba(217,182,98,.55));
}
.info .seed .lbl{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--text-dim);}

.field{padding:13px 0;border-top:1px solid var(--line-soft);}
.field .k{
  font-size:10px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--gold-2);opacity:.85;
  margin-bottom:8px;display:flex;align-items:center;gap:8px;
}
.field .k::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,var(--line-soft),transparent);}
.field .v{font-size:14px;line-height:1.85;color:var(--text);}
.field .v.mono{font-size:14.5px;letter-spacing:.06em;color:var(--gold-1);text-shadow:0 0 16px rgba(217,182,98,.3);}
.field .v.small{font-size:12.5px;line-height:1.85;color:rgba(240,232,214,.82);}

.flash-in{animation:flashIn .5s var(--ease);}
@keyframes flashIn{from{opacity:0;transform:translateY(7px);}to{opacity:1;transform:none;}}

/* ---------- Footer: centred guardian picker + year lookup ---------- */
.foot{
  grid-area:foot;
  padding:2px clamp(16px,3vw,38px) 20px;
  display:flex;flex-direction:column;gap:11px;
  align-items:center;justify-content:center;
  text-align:center;
}
.zodiacs{display:flex;flex-wrap:wrap;gap:7px;align-items:center;justify-content:center;}

/* Each chip names the guardian, with the animals it governs beneath */
.zchip{
  appearance:none;font-family:inherit;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:2px;
  border:1px solid var(--line-soft);background:rgba(255,255,255,.015);
  color:var(--text-dim);
  padding:7px 13px 6px;border-radius:10px;
  transition:.26s var(--ease);
}
.zchip .zn{
  font-size:12.5px;line-height:1.15;letter-spacing:.03em;
  color:var(--text);white-space:nowrap;
}
.zchip .zz{
  font-size:9.5px;line-height:1.1;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold-2);opacity:.72;white-space:nowrap;
}
.zchip:hover{border-color:var(--line);background:rgba(217,182,98,.09);}
.zchip:hover .zn{color:var(--gold-1);}
.zchip[aria-pressed="true"]{
  background:linear-gradient(180deg,var(--gold-1),var(--gold-2));
  border-color:var(--gold-2);
  box-shadow:0 0 22px -2px rgba(217,182,98,.6);
}
.zchip[aria-pressed="true"] .zn,
.zchip[aria-pressed="true"] .zz{color:#12100c;opacity:1;font-weight:600;}
.zchip:focus-visible{outline:1px solid var(--gold-2);outline-offset:2px;}
@media (max-width:600px){
  .zchip{padding:6px 10px 5px;}
  .zchip .zn{font-size:11px;}
  .zchip .zz{font-size:8.5px;letter-spacing:.1em;}
}

.birth{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:10px;
  font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--text-dim);
}
.birth input{
  font-family:inherit;font-size:14px;letter-spacing:.06em;
  width:118px;padding:9px 16px;text-align:center;
  color:var(--gold-1);background:rgba(255,255,255,.03);
  border:1px solid var(--line-soft);border-radius:999px;outline:none;
  transition:.26s var(--ease);
  /* hide the browser's number spinner — it renders as a white +/- widget */
  -moz-appearance:textfield;
  appearance:textfield;
}
.birth input::-webkit-outer-spin-button,
.birth input::-webkit-inner-spin-button{
  -webkit-appearance:none;appearance:none;margin:0;
}
.birth input::placeholder{color:rgba(226,214,188,.32);text-transform:none;}
.birth input:focus{border-color:var(--gold-2);background:rgba(217,182,98,.08);}
.birth .go{
  appearance:none;font-family:inherit;cursor:pointer;
  font-size:11.5px;letter-spacing:.18em;text-transform:uppercase;
  padding:9px 20px;border-radius:999px;
  color:#12100c;font-weight:600;
  background:linear-gradient(180deg,var(--gold-1),var(--gold-2));
  border:1px solid var(--gold-2);
  transition:.26s var(--ease);
}
.birth .go:hover{box-shadow:0 0 24px -2px rgba(217,182,98,.7);}
.birth .result{color:var(--gold-1);letter-spacing:.06em;text-transform:none;font-size:13px;}
.birth .result b{font-weight:600;color:#fff3d0;}

.hint{
  position:absolute;left:50%;transform:translateX(-50%);
  bottom:var(--hint-bottom, 96px);z-index:120;
  font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(238,228,204,.5);
  text-shadow:0 0 14px rgba(0,0,0,.95), 0 1px 3px rgba(0,0,0,.9);
  pointer-events:none;transition:opacity .6s linear;white-space:nowrap;
}
@media (max-width:900px){
  .ground-title{font-size:18px;letter-spacing:.12em;}
  .hint{font-size:8.5px;letter-spacing:.08em;width:100%;text-align:center;}
  .controls{bottom:8px;}
}

/* ---------- Accessibility ---------- */
@media (prefers-reduced-motion:reduce){
  *{transition-duration:.01ms !important;animation-duration:.01ms !important;}
}
@media (max-width:1099px){
  .app{
    height:100vh;
    height:100dvh;              /* survives mobile browser chrome */
    grid-template-columns:1fr;
    /* details sheet sits above the persistent bottom bar */
    grid-template-areas:
      "head"
      "stage"
      "info"
      "foot";
    grid-template-rows:auto minmax(0,1fr) auto auto;
    padding-bottom:env(safe-area-inset-bottom,0px);
    overflow-x:hidden;
  }
  /* The app shell also pins the page itself so the 3D model owns the screen.
     Embedded the host must keep scrolling, so this is stripped too. Each marker
     is again a complete comment of its own so the strip cannot break the
     surrounding block. */
  
  /* Grid children default to min-width:auto, so the non-wrapping chip rail
     would stretch the whole column to the rail's full intrinsic width and
     push the page sideways. Zeroing it lets the rail scroll in its own box. */
  .app > *{min-width:0;}
  .stage,.foot,.info{max-width:100vw;}

  /* --- header: one compact line --- */
  .head{padding:11px 16px 5px;align-items:center;}
  .brand{flex-direction:column;align-items:flex-start;gap:2px;}
  .brand .mark{font-size:13.5px;letter-spacing:.2em;}
  .brand .sub{font-size:8px;letter-spacing:.13em;}
  .panel-title{display:none;}

  /* --- details: collapsible bottom sheet --- */
  .info{
    margin:0;padding:0;position:relative;
    border:0;border-top:1px solid var(--line-soft);
    background:rgba(9,8,7,.94);
    backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
    overflow:hidden;
  }
  .info .corner{display:none;}
  .sheet-head{
    display:flex;position:relative;align-items:center;gap:12px;width:100%;
    appearance:none;font-family:inherit;cursor:pointer;
    padding:13px 16px 10px;
    background:transparent;border:0;text-align:left;
    color:var(--text);
  }
  .sheet-head:focus-visible{outline:1px solid var(--gold-2);outline-offset:-2px;}
  /* grabber, so the sheet reads as draggable/app-like */
  .sheet-head::before{
    content:"";position:absolute;left:50%;top:5px;
    width:38px;height:3px;margin-left:-19px;border-radius:2px;
    background:rgba(217,182,98,.34);
  }
  .sheet-head .sh-text{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1;}
  .sheet-head .sh-zodiac{
    font-size:8.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--gold-2);
  }
  .sheet-head .sh-name{
    font-size:15px;line-height:1.25;color:var(--gold-1);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .sheet-head .sh-chev{
    width:26px;height:26px;flex:none;border-radius:50%;
    display:grid;place-items:center;
    border:1px solid var(--line);color:var(--gold-2);
    transition:transform .34s var(--ease);
  }
  .sheet-head .sh-chev svg{width:14px;height:14px;display:block;}
  .app.sheet-open .sheet-head .sh-chev{transform:rotate(180deg);}
  /* the body becomes a real collapsible block in the app shell */
  .sheet-body{display:block;max-height:0;overflow:hidden;padding:0 18px;transition:max-height .36s var(--ease);}
  .app.sheet-open .sheet-body{
    max-height:min(56vh,440px);
    overflow-y:auto;
    padding-bottom:16px;
    scrollbar-width:thin;
  }
  .info h2{font-size:22px;}
  .info .seed{margin-bottom:12px;}
  .field{padding:11px 0;}
  .field .v{font-size:13.5px;line-height:1.75;}

  /* --- bottom bar: one thumb-scrollable chip rail + the lookup --- */
  /* align-items must be stretch, not center: as a centred flex child the
     rail would size to its own max-content width (~950px) and hang off both
     sides of the viewport instead of scrolling inside it. */
  .foot{padding:0 0 8px;gap:6px;align-items:stretch;}
  /* scroll-padding keeps a snapped chip clear of the screen edge */
  .zodiacs{scroll-padding:0 16px;}
  .zodiacs{
    flex-wrap:nowrap;justify-content:flex-start;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;
    gap:8px;padding:6px 16px 2px;
    scrollbar-width:none;
    /* fade the rail's edges so the row reads as scrollable */
    mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 14px),transparent 100%);
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 14px),transparent 100%);
  }
  .zodiacs::-webkit-scrollbar{display:none;}
  .zchip{
    flex:0 0 auto;scroll-snap-align:center;
    min-height:48px;                /* thumb-sized */
    justify-content:center;
    padding:8px 14px 7px;
  }
  .zchip .zn{font-size:12.5px;}
  .birth{
    gap:8px;font-size:9.5px;letter-spacing:.12em;
    padding:0 16px;
    justify-content:center;
  }
  .birth input{height:44px;font-size:16px;width:108px;}  /* 16px stops iOS zoom-on-focus */
  .birth .go{height:44px;font-size:11px;padding:0 18px;}
  .birth .result{flex-basis:100%;font-size:12px;line-height:1.5;padding-top:2px;}
  .birth label{flex-basis:100%;text-align:center;opacity:.75;}
}

/* iPad portrait: wide enough for the desktop split but the panel squeezes
   the stage and leaves the model small. Keep the app shell out to 1099px. */
/* iPad portrait: wide enough for the desktop split but the panel squeezes
   the stage and leaves the model small. Keep the app shell out to 1099px.
   The height guard matters: a landscape phone is 852px WIDE but only ~390px
   tall, so keying this on width alone handed it the wrapped, centred rail —
   112px of chips plus a 54px birth row left the 3D stage just 111px high.
   Only the wide-and-tall case may wrap; anything short keeps the scrolling
   single-row rail. */
@media (min-width:700px) and (max-width:1099px) and (min-height:560px){
  .zodiacs{justify-content:center;flex-wrap:wrap;overflow:visible;
    mask-image:none;-webkit-mask-image:none;}
  .birth label{flex-basis:auto;}
  .app.sheet-open .sheet-body{max-height:min(58vh,620px);}

  /* A tablet is a phone shell drawn on a 700-1100px canvas. Leaving the phone
     type scale in place made the panel read as a cramped phone strip with tiny
     text adrift in a wide box, and the 26px chevron was a thumb-hostile target
     on a device held at arm's length. Scale the chrome up and split the body
     into two columns: at 1032px a single column ran ~110 characters per line,
     which is unreadable regardless of font size. Two columns keep the measure
     sane AND let the taller type fit without scrolling. */
  .head{padding:14px 22px 10px;}
  .brand .mark{font-size:16px;letter-spacing:.26em;}
  .brand .sub{font-size:10px;letter-spacing:.16em;}

  .sheet-head{padding:16px 22px 13px;}
  .sheet-head::before{top:7px;}
  .sheet-head .sh-zodiac{font-size:10px;letter-spacing:.24em;}
  .sheet-head .sh-name{font-size:19px;}
  /* 44px: the minimum comfortable touch target */
  .sheet-head .sh-chev{width:44px;height:44px;}
  .sheet-head .sh-chev svg{width:20px;height:20px;}

  .sheet-body{display:grid;grid-template-columns:1fr 1fr;column-gap:34px;}
  .app.sheet-open .sheet-body{padding:0 26px 20px;}
  /* the deity's own header block reads across the full width */
  .sheet-body .zodiac-line,
  .sheet-body h2,
  .sheet-body .sanskrit,
  .sheet-body .rank,
  .sheet-body .seed{grid-column:1 / -1;}

  .info .zodiac-line{font-size:11.5px;}
  .info h2{font-size:28px;}
  .info .sanskrit{font-size:13px;}
  .info .rank{font-size:11px;}
  .info .seed{padding:14px 16px;margin-bottom:14px;}
  .info .seed .glyph{width:58px;height:58px;flex:0 0 58px;}
  .info .seed .lbl{font-size:11px;}
  #iSeedRoman{font-size:17px !important;}
  .field{padding:14px 0;}
  .field .k{font-size:11px;margin-bottom:9px;}
  .field .v{font-size:16.5px;line-height:1.8;}
  .field .v.mono{font-size:17px;}
  .field .v.small{font-size:15px;line-height:1.8;}

  /* Same problem in the footer: the chip rail and the birth-year row were
     still on the phone scale, so on a tablet the chips read as tiny buttons
     and the labels as fine print. Scale them for a device held further away. */
  .foot{padding:0 0 14px;gap:10px;}
  .zodiacs{gap:10px;padding:8px 22px 4px;scroll-padding:0 22px;}
  .zchip{min-height:56px;padding:10px 18px 9px;border-radius:12px;}
  .zchip .zn{font-size:15px;}
  .zchip .zz{font-size:10.5px;letter-spacing:.14em;}
  .birth{gap:12px;font-size:11px;letter-spacing:.16em;padding:0 22px;}
  .birth input{height:50px;font-size:18px;width:132px;}
  .birth .go{height:50px;font-size:12.5px;padding:0 24px;}
  .birth .result{font-size:14px;}
}

/* Short landscape (a phone on its side). Height is the scarce axis here, so
   the footer's stacked rows would leave the 3D stage barely 140px tall and the
   statues unreadable. Put the birth row back on one line and give the stage a
   floor of its own; if that no longer fits the viewport the shell scrolls
   instead of crushing the model, which is the better trade at this size. */
@media (max-height:560px) and (max-width:1099px){
  .app{grid-template-rows:auto minmax(190px,1fr) auto auto;overflow-y:auto;overscroll-behavior-y:contain;}
  .birth{flex-wrap:nowrap;align-items:center;}
  .birth label{flex-basis:auto;}
  .birth .result{flex-basis:auto;}
  .head{padding:10px 14px 6px;}
  .sheet-head{padding:10px 16px 8px;}
  /* No room for the decorative hint: it would sit on top of the floor title.
     fitRadius() drops it from the height budget too, so the model does not
     reserve space for a line that is not drawn. */
  .hint{display:none;}
  /* Same reasoning for the big floor label. At this height the stage cannot
     hold both it and the Auto-rotate pill without them colliding, and the
     sheet header directly below already names the same deity — so the label
     is the one to lose. fitRadius() measures the height and adapts. */
  .ground-title{display:none;}
}

/* ============================================================
   Embedded in a host page (the WordPress homepage section)
   ============================================================
   The widget is written to own the viewport. Dropped into one section of a
   long page, four assumptions break. Each is corrected here rather than in the
   layout rules above, and every rule is scoped to `.sa-guardians` — the wrapper
   the host page provides. The standalone build has no such wrapper, so it
   matches none of this and behaves exactly as before.

     1. `.bg` and `#embers` are position:fixed — inside a section they would
        paint the starfield and the ember canvas over the ENTIRE site, above
        the host's own header and footer. They must be confined to the box.
     2. The host page must keep its own scrolling; the shell is given a real
        height instead of the viewport's.
     3. fitRadius() sizes the ring from `innerWidth`, which is the wrong ruler
        inside a section (a 1440px window with a 700px section would build the
        desktop split inside a short box). The JS switches to element
        measurements when embedded — see the EMBED flag.
     4. Arrow keys and Space are bound to `window`, which would hijack them for
        the whole page. Embedded, they bind to the stage instead.

   The wrapper is height-driven because that is what this layout needs. */
.sa-guardians{
  position:relative;
  isolation:isolate;          /* no z-index or blend leaking into the host */
  contain:paint;
  overflow:hidden;
  /* The page-level `body{...}` reset above is stripped when embedded, so the
     wrapper must carry that typography itself or the tuned type scale inside
     would inherit the host theme's font and line-height. The palette defaults
     are re-keyed onto this element by the build script, and updated live by
     cssRoot(), so the same names resolve here as they do at :root standalone. */
  background:var(--ink-1, #0a0908);
  color:var(--text, rgba(240,232,214,.92));
  font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif;
  font-size:16px;
  line-height:1.5;
  text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
  height:clamp(560px, 92vh, 900px);
  height:clamp(560px, 92dvh, 900px);
}
@media (min-width:1100px){
  /* tall enough for the desktop split: stage beside the details panel */
  .sa-guardians{height:clamp(660px, 88vh, 940px);height:clamp(660px, 88dvh, 940px);}
}

/* 1 — confine the decorative layers, which are fixed by default */
.sa-guardians .bg,
.sa-guardians #embers{position:absolute;}

/* 2 — fill the section box; never the viewport */
.sa-guardians .app{height:100%;max-height:100%;}
.sa-guardians .stage,
.sa-guardians .foot,
.sa-guardians .info{max-width:100%;}
@media (max-width:1099px){
  .sa-guardians .app{height:100%;max-height:100%;}
}

/* 2b — the space budget while the details sheet is open.
   The sheet sizes itself from the VIEWPORT (`min(56vh,440px)` on the phone
   shell, `min(58vh,620px)` on a tablet), but this wrapper is only 92dvh tall
   and is hard-capped at 900px. The two rulers disagree on a tablet, so opening
   the sheet starved the stage down to 65px and fitRadius() shrank the cards to
   a sliver — the ring was still turning, there was just nowhere to show it.
   Budget against the SECTION instead: the stage keeps 34% of it (never under
   190px), the panel takes what is left and scrolls inside itself. `cqh` needs
   the wrapper to be a size query container, hence the @supports guard — without
   it the px floor above still applies and the layout stays usable. */
@media (max-width:1099px){
  .sa-guardians .app.sheet-open{grid-template-rows:auto minmax(190px,1fr) auto auto;}
}
@supports (container-type:size){
  @media (max-width:1099px){
    .sa-guardians{container-type:size;}
    .sa-guardians .app.sheet-open{grid-template-rows:auto minmax(max(34cqh,190px),1fr) auto auto;}
  }
}

/* 3 — the standalone hint advertises wheel-zoom. In a section that instruction
      is wrong and the line only adds height, so it is dropped. */
.sa-guardians .hint{display:none;}

/* A soft inner vignette and hairline edges, so the section reads as a
   deliberate band in the page rather than a broken region of it. */
.sa-guardians::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:3;
  box-shadow:inset 0 0 90px rgba(0,0,0,.5);
  border-top:1px solid rgba(217,182,98,.16);
  border-bottom:1px solid rgba(217,182,98,.16);
}

