/* ═══════════════════════════════════════════════════════════════════════════
   rips-glue.css — the product modules, dressed in the v3 design.

   style.css is v3 and is not edited. tokens.css is blockpacks.gg's token sheet,
   loaded so the modules' own injected CSS (rank.js, vault.js, addfunds.js …)
   resolves its var()s; the two sheets share no custom-property names
   (measured). Everything below is scoped to html[data-brand="rips"] so it
   outranks a module's own `.x__panel{…}` rule (0,1,0) without !important,
   except where a module writes inline styles.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the tokens the modules read, pointed at v3's palette ──────────── */
html[data-brand="rips"]{
  --accent:var(--acc); --accent-rgb:var(--acc-rgb);
  --font-display:var(--display); --font-body:var(--ui);
  --text:#FFFFFF; --text-dim:#A7B0BE; --text-faint:#8A94A4;
  --surface:var(--navy); --page-bg:#0B0F18;
  --hairline:rgba(255,255,255,.13);
}

/* ── header: the hidden attribute must beat the flex parents ───────── */
html[data-brand="rips"] .header__right [hidden],
html[data-brand="rips"] .pop[hidden],
html[data-brand="rips"] #railRight[hidden]{display:none!important}
/* wallet.js anchors its popovers with an inline `left`; v3's sit under the pill */
html[data-brand="rips"] .hbal .pop{left:auto!important}
/* auth.js opens the account menu with the hidden attribute, not data-open */
html[data-brand="rips"] #acctMenu:not([hidden]){opacity:1;visibility:visible;transform:none}
html[data-brand="rips"] .pop__row{display:flex;gap:7px;margin-top:11px}
html[data-brand="rips"] .pop__row .addamt{flex:1 1 0;font-size:14px;height:36px}
html[data-brand="rips"] .pop__net{display:block;margin-top:6px;font-size:13px;color:var(--ink-faint)}
html[data-brand="rips"] .pop--menu{min-width:272px;max-width:340px}
html[data-brand="rips"] .menu__head b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
html[data-brand="rips"] .menu__mail{display:block;font-size:12px;color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
html[data-brand="rips"] .menu__k{padding:8px 11px 4px;font-family:var(--display);font-size:13px;font-weight:800;letter-spacing:.1em;color:var(--ink-faint)}
html[data-brand="rips"] .menu__row{display:flex;gap:7px;padding:2px 7px 8px}
html[data-brand="rips"] .menu__row .addamt{flex:1 1 0;font-size:14px}
html[data-brand="rips"] .menu__dep{padding:2px 7px 6px}
html[data-brand="rips"] .menu__depbtn{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;border-radius:9px;background:#111;border:1.5px solid rgba(255,255,255,.2);color:#EDEDED;font-size:13px;text-align:left;cursor:pointer}
html[data-brand="rips"] .menu__depbtn:hover{border-color:var(--acc)}
html[data-brand="rips"] .menu__depdot{width:8px;height:8px;border-radius:50%;background:var(--gold);flex:0 0 auto}
html[data-brand="rips"] .menu__depaddr{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:12px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace;color:#fff}
html[data-brand="rips"] .menu__depcopy{color:var(--acc);font-weight:700;flex:0 0 auto}
html[data-brand="rips"] .menu__depwarn{margin:6px 4px 0;font-size:12px;line-height:1.35;color:var(--gold)}
html[data-brand="rips"] .menu__ref{display:flex;gap:6px;padding:2px 7px 6px}
html[data-brand="rips"] .menu__ref input{flex:1 1 auto;min-width:0;height:38px;border-radius:10px;background:#111;border:1.5px solid rgba(255,255,255,.2);color:#fff;padding:0 10px;font:inherit;font-size:14px}
html[data-brand="rips"] .menu__ref .addamt{flex:0 0 auto;padding:0 14px;font-size:14px}
html[data-brand="rips"] .menu__note{padding:2px 11px 6px;font-size:13px;line-height:1.35;color:var(--ink-dim)}
html[data-brand="rips"] .menu__linked{padding:0 11px 6px;font-size:13px;color:var(--ink-dim)}
html[data-brand="rips"] .menu__i--danger{color:#FF6B6B}
html[data-brand="rips"] .menu__i--danger:hover{background:rgba(255,107,107,.12);color:#FF8A8A}
html[data-brand="rips"] a.menu__i{text-decoration:none}
html[data-brand="rips"] #signInBtn span{text-transform:uppercase}

/* ── the daily crate is a button now; the picture is unchanged ─────── */
html[data-brand="rips"] .cratebtn{display:block;width:100%;padding:0;margin:0;border:0;background:none;cursor:pointer;text-align:center;color:inherit;font:inherit}
html[data-brand="rips"] .cratebtn .crate{display:block}
html[data-brand="rips"] .cratebtn[data-state="ready"] .crate{filter:drop-shadow(0 5px 0 rgba(11,15,24,.30)) drop-shadow(0 0 18px rgba(253,193,7,.75))}
html[data-brand="rips"] .cratebtn[data-state="locked"] .crate,
html[data-brand="rips"] .cratebtn[data-state="unavailable"] .crate,
html[data-brand="rips"] .cratebtn[data-state="needs-purchase"] .crate{opacity:.82}
html[data-brand="rips"] .ladder li.is-now{color:#fff}

/* ── the pre-reels status line ("Preparing purchase…") ─────────────── */
html[data-brand="rips"] .ripstatus{position:fixed;left:50%;bottom:max(72px,12vh);z-index:30;transform:translateX(-50%);margin:0;
  font-family:var(--display);font-size:22px;font-weight:800;font-style:italic;letter-spacing:.01em;color:#fff;
  -webkit-text-stroke:0;text-shadow:0 2px 0 var(--key),0 0 18px rgba(0,0,0,.6);pointer-events:none;white-space:nowrap}
html[data-brand="rips"][data-purchase="1"] .ripstatus{z-index:36}
html[data-brand="rips"] .ripstatus[hidden]{display:none}

/* ── wallet.js's toast (inline-styled) takes the v3 toast's clothes ── */
html[data-brand="rips"] #walletToast{font-family:var(--ui)!important;font-size:15px!important;font-weight:600!important;
  background:#050505!important;border:2px solid var(--key)!important;border-radius:14px!important;color:var(--ink-panel)!important;
  box-shadow:0 8px 0 0 rgba(11,15,24,.34)!important;padding:13px 22px!important}

/* ── the product's overlays: scrim + navy panel + leaning title ─────── */
html[data-brand="rips"] .vault,
html[data-brand="rips"] .grail,
html[data-brand="rips"] .addf,
html[data-brand="rips"] .wd,
html[data-brand="rips"] .auth,
html[data-brand="rips"] .rdm,
html[data-brand="rips"] .codds,
html[data-brand="rips"] .inspect{
  font-family:var(--ui);
  background:rgba(11,15,24,.55);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}

html[data-brand="rips"] .vault__panel,
html[data-brand="rips"] .grail__panel,
html[data-brand="rips"] .addf__panel,
html[data-brand="rips"] .wd__panel,
html[data-brand="rips"] .auth__panel,
html[data-brand="rips"] .rdm__panel,
html[data-brand="rips"] .codds__panel{
  background:var(--navy);border:3px solid var(--key);border-radius:20px;color:#fff;
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:0 14px 0 0 rgba(11,15,24,.34),0 40px 90px -30px rgba(11,15,24,.55)}

html[data-brand="rips"] .vault__title,
html[data-brand="rips"] .grail__title,
html[data-brand="rips"] .addf__title,
html[data-brand="rips"] .wd__title,
html[data-brand="rips"] .auth__title,
html[data-brand="rips"] .rdm__title,
html[data-brand="rips"] .codds__title{
  font-family:var(--display);font-weight:900;font-style:italic;text-transform:uppercase;
  line-height:.98;letter-spacing:-.01em;color:#fff;
  -webkit-text-stroke:4px var(--key);paint-order:stroke fill;
  transform:skewX(-7deg);transform-origin:left center;display:inline-block}
html[data-brand="rips"] .vault__title,
html[data-brand="rips"] .grail__title,
html[data-brand="rips"] .codds__title{font-size:clamp(32px,3.4vw,44px)}
html[data-brand="rips"] .addf__title,
html[data-brand="rips"] .wd__title,
html[data-brand="rips"] .auth__title,
html[data-brand="rips"] .rdm__title{font-size:clamp(28px,3vw,38px)}

html[data-brand="rips"] .vault__sub,
html[data-brand="rips"] .grail__sub,
html[data-brand="rips"] .wd__sub,
html[data-brand="rips"] .auth__sub,
html[data-brand="rips"] .rdm__sub,
html[data-brand="rips"] .codds__sub{color:#A7B0BE}
html[data-brand="rips"] .vault__sub b,
html[data-brand="rips"] .grail__sub b{color:var(--acc-hi)}

/* the close control, v3's .ov__x */
html[data-brand="rips"] .vault__close,
html[data-brand="rips"] .addf__x,
html[data-brand="rips"] .wd__x,
html[data-brand="rips"] .auth__x,
html[data-brand="rips"] .rdm__x,
html[data-brand="rips"] .codds__close,
html[data-brand="rips"] .inspect__close{
  width:clamp(44px,4.4vw,58px);height:clamp(44px,4.4vw,58px);border-radius:14px;
  border:2px solid var(--acc);background:transparent;color:#fff;font-size:24px;line-height:1;cursor:pointer}
html[data-brand="rips"] .vault__close:hover,
html[data-brand="rips"] .addf__x:hover,
html[data-brand="rips"] .wd__x:hover,
html[data-brand="rips"] .auth__x:hover,
html[data-brand="rips"] .rdm__x:hover,
html[data-brand="rips"] .codds__close:hover{background:rgba(var(--acc-rgb),.16)}

/* the gold sticker on every primary control */
html[data-brand="rips"] .addf__copy,
html[data-brand="rips"] .wd__primary,
html[data-brand="rips"] .auth__primary,
html[data-brand="rips"] .rdm__btn,
html[data-brand="rips"] .vault__redeem,
html[data-brand="rips"] .pvcard__sell{
  cursor:pointer;
  font-family:var(--display);font-weight:900;font-style:italic;text-transform:uppercase;letter-spacing:.01em;
  color:var(--stick-ink);border:var(--ring-w) solid var(--ring-in);border-radius:12px;
  background:linear-gradient(180deg,var(--acc-hi) 0%,var(--acc) 48%,var(--acc-lo) 100%);
  box-shadow:0 0 0 var(--ring-out-w) var(--ring-out),0 5px 0 0 rgba(11,15,24,.30)}
html[data-brand="rips"] .addf__copy,
html[data-brand="rips"] .wd__primary,
html[data-brand="rips"] .auth__primary,
html[data-brand="rips"] .rdm__btn{font-size:20px;min-height:46px}
html[data-brand="rips"] .vault__redeem,
html[data-brand="rips"] .pvcard__sell{font-size:17px}
html[data-brand="rips"] .addf__copy:active,
html[data-brand="rips"] .wd__primary:active,
html[data-brand="rips"] .auth__primary:active,
html[data-brand="rips"] .rdm__btn:active,
html[data-brand="rips"] .vault__redeem:active,
html[data-brand="rips"] .pvcard__sell:active{transform:translateY(2px)}
html[data-brand="rips"] .pvcard__sell:disabled,
html[data-brand="rips"] .wd__primary:disabled,
html[data-brand="rips"] .rdm__btn:disabled{opacity:.55;cursor:default;transform:none}

/* the quiet controls */
html[data-brand="rips"] .wd__ghost,
html[data-brand="rips"] .vault__stab{
  font-family:var(--display);font-weight:800;font-style:italic;text-transform:uppercase;
  border:2px solid rgba(255,255,255,.22);border-radius:10px;background:transparent;color:#EDEDED;cursor:pointer}
html[data-brand="rips"] .vault__stab[aria-selected="true"]{border-color:var(--acc);color:var(--acc);background:rgba(var(--acc-rgb),.12)}

/* vault cards on the navy ground */
html[data-brand="rips"] .pvcard{background:#0B0F18;border:2px solid var(--key);border-radius:16px}
html[data-brand="rips"] .pvcard__name{font-family:var(--display);font-weight:800;font-style:italic;font-size:17px;color:#fff}
html[data-brand="rips"] .pvcard__val{color:var(--acc-hi);font-weight:900}
html[data-brand="rips"] .pvcard__grade{color:#A7B0BE}
html[data-brand="rips"] .vault__empty-h{font-family:var(--display);font-weight:900;font-style:italic;font-size:30px;color:#fff}
html[data-brand="rips"] .vault__net{color:#8A94A4}

/* the deposit panel: the address is the control, so it reads big and clean */
html[data-brand="rips"] .addf__addr{font:14px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;color:#fff;word-break:break-all;
  background:#0B0F18;border:2px solid var(--key);border-radius:10px;padding:10px 12px;display:block}
html[data-brand="rips"] .addf__warn{color:var(--gold);font-weight:700}
html[data-brand="rips"] .addf__gatehead{font-family:var(--display);font-weight:900;font-style:italic;font-size:26px;color:#fff}
html[data-brand="rips"] .addf__gatesub,
html[data-brand="rips"] .addf__sub,
html[data-brand="rips"] .addf__note{color:#A7B0BE}

/* withdraw / redeem inputs */
html[data-brand="rips"] .wd input,
html[data-brand="rips"] .rdm input,
html[data-brand="rips"] .rdm select,
html[data-brand="rips"] .auth input{background:#0B0F18;border:2px solid var(--key);border-radius:10px;color:#fff;font:inherit;font-size:16px;padding:10px 12px}
html[data-brand="rips"] .wd input:focus,
html[data-brand="rips"] .rdm input:focus,
html[data-brand="rips"] .auth input:focus{outline:none;border-color:var(--acc)}

/* ── THE SLAB SETTLES UNDER THE RAIL — ported from blockpacks.gg ─────────
   shell.css ("DURATION, after Luke saw it"): when the post-rip rail is up the
   WebGL canvas itself slides down 14.3vh over .95s, so the held slab sits
   centred beside the rail instead of high. pack3d.js writes its own
   `#stageLayer>canvas{transition:opacity …}` at runtime, so the selector
   carries html[data-state] to out-specify it and re-declares the opacity leg.
   v3's ground is the halftone plate the canvas already draws, so the strip the
   travel uncovers matches; no black backing is needed here. */
@media (min-width:1024px){
  html[data-state] #stageLayer>canvas{
    transition:transform .95s cubic-bezier(.16,.78,.29,1),
               opacity .5s cubic-bezier(.2,.7,.3,1)}
  html[data-state="rip"][data-postrip="1"] #stageLayer>canvas{
    transform:translateY(var(--postrip-settle,14.3vh))}
  @media (prefers-reduced-motion:reduce){
    html[data-state] #stageLayer>canvas{transition:opacity .5s cubic-bezier(.2,.7,.3,1)}
  }
}

/* ── HEADER POPOVERS OVER THE POST-RIP RAIL ──────────────────────────────
   Luke, 8 Sep 02:50, on the demo: "When I hover over the rip tokens, we can't
   see what it says because your pull is covering it. Same with the dropdown
   from the profile button, and same when you hover over the USDC balance ...
   These should come over the top of everything always."

   WHY IT HAPPENS, MEASURED (scratchpad/popz2.mjs — the stacking ancestry of
   both sides). The pop's chain is
       #acctMenu z40 -> .header z6 -> .page z1 -> .fit position:FIXED z:auto
   and the panel's is
       #postrip position:fixed z:36 -> body
   `.fit` is position:fixed, which makes a stacking context in every modern
   browser, so the pop is sealed inside it and its 40 counts for nothing
   outside. `.fit` itself has z-index AUTO, which paints in the SAME layer as
   z-index 0 — and #postrip is a body child appended at runtime, i.e. LATER in
   the DOM. Later wins. That is why the rule that stood here since 7 Sep,
   `.postrip{z-index:0}`, changed nothing: it moved the panel from 36 to 0,
   which is the very layer .fit is already in, and DOM order still decided.
   Verified on prod at 387830ec81 before this fix: the pop was BLOCKED by
   .postrip__eyebrow — the words YOUR PULL, printing through the tooltip.

   THE FIX, and why it is this one. The panel cannot come down (0 and -1 both
   land in or below the layer .fit occupies, and negative would hide it
   outright), so the PAGE goes up — one rank above the panel's 36 — for
   exactly as long as a header pop is open, and only while the post-rip panel
   is up, which is the only state where the two ever fight.
   `pointer-events:none` on the lifted page is the other half and it is not
   optional: measured, lifting .fit alone put #stage over the panel and every
   one of RIP AGAIN / SELL & RIP / VAULT IT / SELL NOW went dead. Inert page,
   live header, so clicks fall straight through to the panel underneath while
   the pop still takes its own. Measured after: pop ok, trigger ok, all four
   buttons ok, and unchanged the moment the pop closes. */
html[data-brand="rips"][data-postrip="1"]:has(.header__right .pop:not([hidden])) .fit{
  z-index:37;pointer-events:none}
html[data-brand="rips"][data-postrip="1"]:has(.header__right .pop:not([hidden])) .header{
  pointer-events:auto}

/* ── the vault's sort row and header controls, on the phone and desktop ──
   Luke, iPhone: a grey bar behind the sort tabs (the module's sticky-row
   fill on the old dark panel); the tabs touching; REDEEM touching the X. */
html[data-brand="rips"] .vault__sort{background:var(--navy);gap:10px;box-shadow:none;border-bottom:0}
html[data-brand="rips"] .vault__sort::after{background:linear-gradient(var(--navy),rgba(31,36,50,0))}
html[data-brand="rips"] .pvault__grid{padding-top:8px}
html[data-brand="rips"] .vault__stab{margin-bottom:0}
html[data-brand="rips"] .vault__redeem{right:calc(var(--s3) + clamp(44px,4.4vw,58px) + 14px)}

/* ── THE PHONE SHEET KEEPS ITS BUTTONS ON SCREEN ────────────────────────
   Luke's iPhone, 2 Sep: the sheet's bottom sat under Safari's toolbar and
   the buttons needed a scroll. Two changes: the sheet's cap uses the dynamic
   viewport (dvh — the toolbar is subtracted), and the DETAILS become the
   scrolling part, so the collapse row and the four buttons are always in
   view. The collapse animation (grid-rows 1fr→0fr) is untouched. */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__rail{max-height:min(82vh,84dvh);overflow:hidden;
    display:flex;flex-direction:column}
  html[data-brand="rips"] .postrip__infoclip{min-height:0;flex:0 1 auto}
  html[data-brand="rips"] .postrip__info{max-height:44dvh;overflow:auto;
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  html[data-brand="rips"] .postrip__info::-webkit-scrollbar{width:0}
  html[data-brand="rips"] .postrip__collapse,
  html[data-brand="rips"] .postrip__row{flex:0 0 auto}
}
/* Luke's zoom, 2 Sep: on the phone the sheet's keylines are the desktop's
   5-6px on 23-24px type, which closes the counters of P and R in YOUR PULL;
   and the first glyph's stroke was clipped by the details' scroll box. The
   strokes scale with the type here, and the scroll box is widened by the
   stroke so nothing at the left edge is cut. */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__eyebrow{-webkit-text-stroke:3px var(--key)}
  html[data-brand="rips"] .postrip__name{-webkit-text-stroke:3.5px var(--key)}
  html[data-brand="rips"] .postrip__r--big dd{-webkit-text-stroke:3px var(--key)}
  html[data-brand="rips"] .postrip__info{margin:0 -10px;padding:0 10px}
}

/* ── Luke, 2 Sep, second phone rip ─────────────────────────────────────
   1. "now I have to scroll to see the info": the 44dvh cap on the details
      is gone. The sheet is a flex column capped at the dynamic viewport, so
      the details only shrink and scroll if a name runs long on a short
      phone; otherwise everything is in view, buttons included.
   2. "don't remove the logo from the top when ripping": the phone header
      stays through the rip. It sits above the reels at z-index 6 and the
      logo is a way home once the reveal holds (rip-flow.js wires it).
   3. "there's a black/grey header on the home page, remove it": the phone
      header's gradient bar is gone; the logo and the balance sit on the
      sky, like the desktop header. */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__info{max-height:none}
  html[data-brand="rips"] .mhead{background:none}
  html[data-brand="rips"][data-state="rip"] .mhead{transform:none;opacity:1}
}

/* ── Luke, 2 Sep 00:44: the phone overlays ─────────────────────────────
   The LIVE-strip card detail sized to its photograph (too big, scrollable);
   the profile sheet cut its content against the header with no fade, ran
   YOUR BALANCE into the button, and SILVER sank into the ground. */
@media (max-width:1023px){
  html[data-brand="rips"] .ov__panel--sm{max-height:92dvh}
  html[data-brand="rips"] .hitov__body{grid-template-columns:1fr;gap:14px}
  html[data-brand="rips"] .hitov__art{display:grid;place-items:center;max-height:44dvh}
  html[data-brand="rips"] .hitov__art img{width:auto;max-width:100%;height:auto;max-height:44dvh;object-fit:contain}
  html[data-brand="rips"] .ov--prof .ov__body,
  html[data-brand="rips"] .ov--sheet .ov__body{padding-top:18px;
    -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 22px,#000 calc(100% - 22px),transparent 100%);
    mask-image:linear-gradient(180deg,transparent 0,#000 22px,#000 calc(100% - 22px),transparent 100%)}
  html[data-brand="rips"] .mprof__lbl{margin-bottom:12px}
  html[data-brand="rips"] .mprof__add .addgo{margin-top:4px}
  html[data-brand="rips"] .mrank .rank__name{color:#fff;-webkit-text-stroke:3px var(--key);paint-order:stroke fill}
}
html[data-brand="rips"] .hitov__art img{max-height:62vh}
/* the real grail pool's cards, now free of v3's own .gcard rules */
html[data-brand="rips"] .pgcard{min-width:0;overflow:hidden}
html[data-brand="rips"] .pgcard__name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/* ── Luke, 2 Sep 01:xx ─────────────────────────────────────────────────
   Pay marks off (no on-ramp yet); grail names get two lines; ODDS body
   fades under its tab row and the row shows it scrolls; SILVER's letters
   stop touching; the share pill and the slab hit zone beside the held card. */
html[data-brand="rips"] .pay,
html[data-brand="rips"] .mpay{display:none!important}
html[data-brand="rips"] .pgcard__name{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;line-height:1.25;min-height:2.5em}
html[data-brand="rips"] .ov--odds .ov__body{
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 20px,#000 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 20px,#000 100%)}
html[data-brand="rips"] .otabs{position:relative;overflow-x:auto;scrollbar-width:none;
  -webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 56px),transparent 100%);
  mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 56px),transparent 100%)}
html[data-brand="rips"] .otabs::-webkit-scrollbar{display:none}
html[data-brand="rips"] .mrank .rank__name{-webkit-text-stroke:2px var(--key);letter-spacing:.035em}
html[data-brand="rips"] .postrip__share{position:fixed;z-index:38;display:none;flex-direction:column;align-items:center;gap:6px;
  text-decoration:none;color:#fff;font-family:var(--display);font-weight:900;font-style:italic;font-size:14px;letter-spacing:.08em;
  -webkit-text-stroke:2px var(--key);paint-order:stroke fill}
html[data-brand="rips"][data-postrip="1"] .postrip__share{display:flex}
html[data-brand="rips"] .postrip__share[hidden]{display:none!important}
html[data-brand="rips"] .postrip__sharex{width:48px;height:48px;border-radius:50%;background:#050505;border:2px solid #fff;
  display:grid;place-items:center;color:#fff;box-shadow:0 5px 0 0 rgba(11,15,24,.3)}
html[data-brand="rips"] .postrip__slabhit{position:fixed;z-index:37;background:transparent;border:0;padding:0;cursor:zoom-in}
html[data-brand="rips"] .postrip__slabhit[hidden]{display:none!important}
/* the hold ring around a hidden post-rip button goes with it (rip-flow showBtn;
   style.css:1621 .postrip__row .hring--inline{display:block} would otherwise win) */
html[data-brand="rips"] .postrip__row .hring[hidden],
html[data-brand="rips"] .postrip__row > button[hidden]{display:none!important}   /* VAULT IT has no ring and its display rule beat [hidden] too (measured 7 Sep) */
/* CLOSE SHARES THE ROW WITH RIP AGAIN on an auto-sold pull (Luke, 8 Sep 02:40,
   reversing his 7 Sep "CLOSE stands alone": "it should say 'Rip Again' and then
   a 'Close' button next to it"). No grid-column: the row is two 1fr columns and
   the hidden buttons are display:none, so RIP AGAIN takes cell 1 and this takes
   cell 2. display:block is still needed — it is what beats the [hidden] rule
   above once the button is shown again. */
html[data-brand="rips"] .postrip__row > .postrip__close:not([hidden]){display:block}
@media (min-width:1024px){
  /* Luke, 2 Sep, first mainnet rip: the share button UNDER the card on
     desktop, not beside it, and a touch bigger.
     R6D, 10 Sep 05:40 — IT MOVES ABOVE THE SLAB. Under the card is where the
     clip toast lands, and at 1147x655 the two overlapped by 38.6px (measured:
     share y 551.6-636.6, #clipbar y 598-649), which is why record.css used to
     hide the control whenever a clip was up. Luke: the SHARE control "moves to
     the top of that panel so the two never collide".
     ANCHORED TO THE SLAB, NOT THE HEADER, and by its BOTTOM edge so the label
     can grow upwards without ever touching the card: the slab's hit zone starts
     at 11vh + settle, so 100vh - (11vh + settle) = 89vh - settle is the gap
     from the foot of the window to the top of the slab, and +10px holds the
     control that far clear of it. Measured after the change, both of Luke's
     windows, in the real post-rip state (RECORD-R2-NOTES §8):
       1147x655  control y 70.7-155.7  slab top 165.7  header bottom 96.7
       1512x982  control y 153.4-238.4 slab top 248.4  header bottom 127.6
     The lead's open question (LEAD-DECISIONS-R2 20) was the header: it DOES
     paint in this state, but its centre is empty — the brand ends at x 176 and
     the first pill starts at x 813.7 at 1147x655, and the control is 58px wide
     on the window's centre line, so it clears both at every window. */
  html[data-brand="rips"] .postrip__share{left:50%;transform:translateX(-50%);
    bottom:calc(89vh - var(--postrip-settle,14.3vh) + 10px);
    font-size:17px;gap:7px}
  html[data-brand="rips"] .postrip__sharex{width:58px;height:58px}
  html[data-brand="rips"] .postrip__sharex svg{width:22px;height:22px}
  html[data-brand="rips"] .postrip__slabhit{left:50%;top:calc(11vh + var(--postrip-settle,14.3vh));width:min(34vw,420px);height:58vh;transform:translateX(-50%)}
}
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__share{right:14px;top:calc(var(--mh-top,0px) + var(--mh-head,60px) + 8px)}
  html[data-brand="rips"] .postrip__slabhit{left:50%;top:9vh;width:64vw;height:40vh;transform:translateX(-50%)}
}

/* ── Luke, 2 Sep 01:3x ─────────────────────────────────────────────────── */
/* no pinch/double-tap zoom anywhere: JS catches iOS Safari, and touch-action
   backs it up on the stage/canvas and every app control. When the browser is
   already zoomed, the JS guard flips this to manipulation so pinch-out can
   recover instead of trapping the phone at the bad scale. */
html[data-brand="rips"], html[data-brand="rips"] body{touch-action:manipulation}
html[data-brand="rips"] button,
html[data-brand="rips"] a,
html[data-brand="rips"] [role="button"]{touch-action:manipulation}
html[data-brand="rips"] #stageLayer,
html[data-brand="rips"] #stageLayer>canvas,
html[data-brand="rips"] .stage,
html[data-brand="rips"] .stage__inner,
html[data-brand="rips"] .pack3d,
html[data-brand="rips"] .pack3d canvas,
html[data-brand="rips"] .multiPicker,
html[data-brand="rips"] .multiPicker *{touch-action:none}
html[data-brand="rips"][data-browser-zoomed] #stageLayer,
html[data-brand="rips"][data-browser-zoomed] #stageLayer>canvas,
html[data-brand="rips"][data-browser-zoomed] .stage,
html[data-brand="rips"][data-browser-zoomed] .stage__inner,
html[data-brand="rips"][data-browser-zoomed] .pack3d,
html[data-brand="rips"][data-browser-zoomed] .pack3d canvas,
html[data-brand="rips"][data-browser-zoomed] .multiPicker,
html[data-brand="rips"][data-browser-zoomed] .multiPicker *{touch-action:manipulation}
/* the four buttons stop touching the bottom of the phone */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__rail{padding-bottom:calc(26px + env(safe-area-inset-bottom,0px));
    max-height:min(90vh,92dvh)}
  /* the sheet fits without a scroll: tighter stack, no wasted rows */
  html[data-brand="rips"] .postrip__eyebrow{font-size:20px}
  html[data-brand="rips"] .postrip__head .swoosh{margin:2px 0 6px 3px}
  html[data-brand="rips"] .postrip__name{font-size:clamp(20px,5.8vw,26px);margin-bottom:3px}
  html[data-brand="rips"] .postrip__grade{margin:7px 0 0;padding:4px 11px 3px;font-size:16px}
  html[data-brand="rips"] .postrip__rows,html[data-brand="rips"] .postrip__vals{margin-top:6px}
  html[data-brand="rips"] .postrip__r{padding:5px 0}
  html[data-brand="rips"] .postrip__r--big dd{font-size:21px}
  html[data-brand="rips"] .postrip__row{margin-top:10px}
  html[data-brand="rips"] .minfo{width:34px;height:34px;flex:0 0 auto;border-radius:50%;
    border:2px solid rgba(255,255,255,.7);background:rgba(0,0,0,.55);color:#fff;
    font:900 15px/1 var(--display);font-style:italic}
}
/* the vault's sort row: three equal tabs, centred, with air before the fade */
html[data-brand="rips"] .vault__sort{justify-content:center;padding-bottom:16px}
html[data-brand="rips"] .vault__stab{flex:1 1 0;max-width:150px;text-align:center;padding:9px 6px}
/* the turbo pill steps left so the i dot has room and reads as a control */
html[data-brand="rips"] .turborow .turbo{transform:translateX(-10px)}
html[data-brand="rips"] .turborow__side .info{border:2px solid rgba(255,255,255,.85);background:rgba(0,0,0,.55);
  color:#fff;cursor:pointer;font:900 14px/1 var(--display);font-style:italic}
html[data-brand="rips"] .turborow__side .info:hover{border-color:var(--acc);color:var(--acc)}
html[data-brand="rips"] .turbotip{position:fixed;z-index:80;max-width:280px;padding:12px 14px;border-radius:14px;
  background:#050505;border:2px solid var(--acc);color:#EDEDED;font-family:var(--ui);font-size:14px;line-height:1.4;
  box-shadow:0 8px 0 0 rgba(11,15,24,.34)}
html[data-brand="rips"] .turbotip b{display:block;font-family:var(--display);font-style:italic;font-weight:900;
  font-size:18px;color:var(--acc);margin-bottom:4px}
html[data-brand="rips"] .turbotip[hidden]{display:none!important}
/* "Preparing purchase…" is a spinner now, not a sentence on an empty stage */
html[data-brand="rips"] .ripstatus{display:flex;align-items:center;gap:14px}
html[data-brand="rips"] .ripstatus::before{content:"";width:34px;height:34px;border-radius:50%;flex:0 0 auto;
  background:conic-gradient(from 0deg,var(--acc) 0 25%,transparent 25% 50%,var(--gold) 50% 75%,transparent 75% 100%);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 7px),#000 calc(100% - 6px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 7px),#000 calc(100% - 6px));
  filter:drop-shadow(0 0 0 var(--key)) drop-shadow(0 2px 0 var(--key));
  animation:ripspin .7s linear infinite}
@keyframes ripspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){html[data-brand="rips"] .ripstatus::before{animation:none}}

/* ── Luke, 2 Sep 01:22 — MEASURED, not guessed ─────────────────────────
   Headless phone (390 wide): the sheet was 302px tall with 597px allowed,
   yet the details box was 130px against 188px of content — my flex/grid
   shrink was squeezing it for no reason. Back to v3's own sheet: block
   layout, whole-sheet scroll only if it ever exceeds the cap. */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__rail{display:block;overflow:auto}
  html[data-brand="rips"] .postrip__infoclip{flex:none}
  html[data-brand="rips"] .postrip__info{max-height:none;overflow:hidden}
  html[data-brand="rips"] .postrip__grade{display:block;width:max-content;margin-left:auto;margin-right:auto}
}
/* the turbo pill goes back where it was; the i dot sits above it, to the left */
html[data-brand="rips"] .turborow .turbo{transform:none}
html[data-brand="rips"] .turborow.stage__row{position:relative}
html[data-brand="rips"] .turborow__side{position:absolute;left:calc(50% - 150px);top:-38px;margin:0}
@media (max-width:1023px){
  html[data-brand="rips"] .mdock__row{position:relative}
  html[data-brand="rips"] .minfo{position:absolute;left:0;top:-40px}
}
/* the pack loader: one line, readable, centred on the stage */
html[data-brand="rips"] .loader{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:max-content}
html[data-brand="rips"] .loader__txt{white-space:nowrap;color:#fff;font-family:var(--display);font-weight:900;font-style:italic;
  font-size:18px;letter-spacing:.06em;-webkit-text-stroke:3px var(--key);paint-order:stroke fill;text-align:center}
/* MEASURED (headless phone): the rail's box was 302px for 360px of content
   and setting top:auto alone restored it — a `top` still reaches the rail on
   the phone. Pinned here at higher specificity: bottom-anchored, content-sized. */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__rail{top:auto;bottom:0;height:auto}
}

/* ── THE REELS ON A PHONE GPU (Luke, 2 Sep: "laggy as f***", "shows two
   digits mid-spin") ───────────────────────────────────────────────────
   Two of the concept's reel treatments are per-frame GPU work on a moving
   layer: a 7px keyline rasterised on every one of ~130 spinning items, and a
   gradient mask over each reel (which is ALSO what fades a passing digit to
   nothing, so a year reads as two digits). Both come off while spinning; the
   keyline stays on the landed digit, where the eye rests. A hard clip keeps
   every reel showing one whole glyph at all times. Desktop keeps v3's look. */
@media (max-width:1023px){
  html[data-brand="rips"] .sus__reel{-webkit-mask-image:none;mask-image:none;overflow:hidden;
    transform:none;contain:paint}
  html[data-brand="rips"] .sus__item{-webkit-text-stroke:0;paint-order:normal;
    text-shadow:0 2px 0 var(--key),0 0 3px var(--key)}
  html[data-brand="rips"] .sus__reel[data-set="1"] .sus__item[data-hit="1"]{
    -webkit-text-stroke:6px var(--key);paint-order:stroke fill;text-shadow:none}
}
/* the lockbox wheel: digits stacked with NO slack, so whatever the strip's
   offset, the window always shows glyph, never the gap between two glyphs
   (Luke's 01:44 screenshot — a wheel that read as "digit 2 missing") */
@media (max-width:1023px){
  html[data-brand="rips"] .sus__reel{height:1em;line-height:1}
  html[data-brand="rips"] .sus__item{height:1em;line-height:1;padding:0 .04em}
  html[data-brand="rips"] .sus--year .sus__reel,html[data-brand="rips"] .sus--company .sus__reel{font-size:clamp(44px,6.6vh,80px)}
}

/* ── Luke, 2 Sep 03:43, from two WhatsApp screenshots ─────────────────
   1. Collapsed sheet: "INSTANT SELLBACK $62.90" was 13px pink with a soft
      shadow, hard to read over the burst. It now wears the Instant sellback
      figure's own face — the display font, 900 italic, 21px on the phone,
      pink, the same 3px black keyline — so the collapsed line and the
      expanded row are the same object.
   2. "POKÉMON · 2020" under the card name: the display font, white with
      the black keyline like the name above it, clearly smaller than it. */
@media (max-width:1023px){
  html[data-brand="rips"] .postrip__sellmini{font-size:21px;letter-spacing:-.004em;
    color:var(--acc);-webkit-text-stroke:3px var(--key);paint-order:stroke fill;text-shadow:none;
    transform:var(--slant);transform-origin:left center;line-height:1;white-space:nowrap}
  html[data-brand="rips"] .postrip__sub{font-family:var(--display);font-weight:900;font-style:italic;
    font-size:15px;letter-spacing:.02em;text-transform:uppercase;color:#FFF;
    -webkit-text-stroke:2.2px var(--key);paint-order:stroke fill;line-height:1.2;
    transform:var(--slant);transform-origin:left center;margin-top:1px}
}

/* ── Luke, 2 Sep 03:50 — the desktop rails and the rank colours ─────────
   1. "Choose a pack" and its swoosh come off; the franchise picker moves up
      a little, not all the way (the rest of the freed height is padding).
   2. "Rank" and its swoosh come off; the rank block rises, and RANKS &
      CRATE ODDS stays exactly where it was (margin below carries the gap).
   3. Whatever the rank is, that colour is that colour: the big shield, the
      rank name and the "more to X" word wear the tier's own colour — the
      same five the ladder shields already use. `html[data-tier]` is set by
      rips-glue.js's mirror from rank.js's tier, so the phone's profile
      sheet, which builds the same classes, follows for free.
   4. What's Inside is the second button on the page, not the first: smaller
      box, smaller type, smaller stars. RIP PACK is untouched. */
@media (min-width:1024px){
  html[data-brand="rips"] .rail--left .rail__title,html[data-brand="rips"] .rail--left>.swoosh{display:none}
  html[data-brand="rips"] .rail--left .picker{margin-top:34px}
  html[data-brand="rips"] .rail--right .rail__title,html[data-brand="rips"] .rail--right>.swoosh{display:none}
  html[data-brand="rips"] .rail--right .odds{margin-top:49px}   /* measured: the title+swoosh were 49px; the link stays put */
  html[data-brand="rips"] .whatsinside{width:214px;height:46px;border-radius:14px;gap:10px}
  html[data-brand="rips"] .whatsinside b{font-size:18px}
  html[data-brand="rips"] .whatsinside i:not(.sparkle){width:19px;height:19px;font-size:11px;border-width:1.5px;border-radius:5px}
  html[data-brand="rips"] .whatsinside .sparkle:nth-of-type(1){width:18px!important;height:18px!important;top:-11px!important;right:2px!important}
  html[data-brand="rips"] .whatsinside .sparkle:nth-of-type(2){width:13px!important;height:13px!important;top:-3px!important;right:-10px!important}
  html[data-brand="rips"] .whatsinside .sparkle:nth-of-type(3){width:9px!important;height:9px!important;top:12px!important;right:-4px!important}
}
html[data-tier="bronze"]{--tier:#C87B2A}
html[data-tier="silver"]{--tier:#D8D8D8}
html[data-tier="gold"]{--tier:#FDC107}
html[data-tier="platinum"]{--tier:#3FD8C5}
html[data-tier="diamond"]{--tier:#4FA8F5}
html[data-tier] .rank__name{color:var(--tier)}
html[data-tier] .rank__shield path{stroke:var(--tier)}
.rank__next b[data-tier="bronze"]{color:#C87B2A}
.rank__next b[data-tier="silver"]{color:#D8D8D8}
.rank__next b[data-tier="gold"]{color:#FDC107}
.rank__next b[data-tier="platinum"]{color:#3FD8C5}
.rank__next b[data-tier="diamond"]{color:#4FA8F5}

/* ── the daily crate's pop-up wears BlockRips' type (Luke, 2 Sep 03:49:
   "the crate still shows the old font when you open it") ─────────────── */
.cr{--font-brand:'Barlow Condensed',system-ui,sans-serif}
.cr .cr__hint{font-family:var(--display);font-weight:900;font-style:italic;font-size:18px;letter-spacing:.06em;color:#FFF;
  -webkit-text-stroke:3px var(--key);paint-order:stroke fill}
.cr .cr__done{font:italic 900 20px var(--display);letter-spacing:.03em;text-transform:uppercase;color:var(--key);
  background:var(--yellow,#FDC107);border:2.5px solid var(--key);border-radius:14px;padding:12px 34px}

/* ── NO TEXT SELECTION ON A HOLD (Luke, 2 Sep, phone vault: "when I click and
   hold, it highlights the text instead of selling it"). iOS turns a long
   press into a text selection / callout unless the whole hit area says no;
   hold.js's button carries it, the card and the ring around it did not. */
.vault .pvcard,.vault .pvcard *,.hring,.hring *,.postrip__row,.postrip__row *{
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}

/* ── Luke, 2 Sep, first mainnet withdraw + deposit ──────────────────────
   "Sent" reads bigger; the add-funds panel does not scroll on a laptop
   (the QR was 196px + the solana: deep link that does nothing on desktop
   Chrome); the deep link and its caption are phone-only. */
html[data-brand="rips"] .wd__done{font-family:var(--display);font-weight:900;font-style:italic;font-size:34px;letter-spacing:.02em;
  color:#fff;-webkit-text-stroke:3px var(--key);paint-order:stroke fill}
@media (min-width:1024px){
  html[data-brand="rips"] .addf__panel{max-height:none;overflow:visible}
  html[data-brand="rips"] .addf__link,html[data-brand="rips"] .addf__linknote{display:none}
  html[data-brand="rips"] .addf__qrbox{width:172px;height:172px;margin-top:12px}
  html[data-brand="rips"] .addf__qrbox svg{width:144px;height:144px}
  html[data-brand="rips"] .addf__addr,html[data-brand="rips"] .addf__warn{margin-top:12px}
  html[data-brand="rips"] .addf__copy{margin-top:12px}
}

/* ── HEADINGS DO NOT TAKE CLICKS (Luke, 2 Sep, mainnet: the vault's X and
   REDEEM, the redeem panel's X "have to be clicked in the exact right
   position... click them twice"). The restyled titles are skewed with a
   transform, and a transformed box paints in the positioned layer — above
   the absolutely positioned close/redeem controls wherever the two boxes
   overlap. Measured headless: single clicks on the vault X landed 6 of 10,
   the misses all reported H2.vault__title under the cursor. Decorative text
   is now transparent to the pointer, and the controls sit above it anyway. */
html[data-brand="rips"] .vault__title,html[data-brand="rips"] .grail__title,html[data-brand="rips"] .addf__title,
html[data-brand="rips"] .wd__title,html[data-brand="rips"] .auth__title,html[data-brand="rips"] .rdm__title,
html[data-brand="rips"] .codds__title,html[data-brand="rips"] .vault__sub,html[data-brand="rips"] .grail__sub,
html[data-brand="rips"] .addf__sub,html[data-brand="rips"] .wd__sub,html[data-brand="rips"] .auth__sub,
html[data-brand="rips"] .rdm__sub,html[data-brand="rips"] .codds__sub{pointer-events:none}
html[data-brand="rips"] .vault__close,html[data-brand="rips"] .vault__redeem,html[data-brand="rips"] .addf__x,
html[data-brand="rips"] .wd__x,html[data-brand="rips"] .auth__x,html[data-brand="rips"] .rdm__x,
html[data-brand="rips"] .codds__close,html[data-brand="rips"] .inspect__close{z-index:3}

/* ── the pack list's scroll cue (Luke, 2 Sep): pink, and up over the last
   visible button so it reads as "more below", not as an arrow at What's
   Inside ────────────────────────────────────────────────────────────── */
@media (min-width:1024px){
  /* 4 Sep: OUT OF FLOW. It used to be pulled up with a negative margin, which
     meant its position was a function of the list's bottom margin — so every
     time the list was resized the arrow drifted back down towards What's
     Inside and read as an arrow AT that button. Absolute, driven by
     --cue-bottom (app.js sets it from the measured list edge every paintFade),
     it always sits over the peeking half-row and costs the list no height. */
  html[data-brand="rips"] .rail--left{position:relative}
  html[data-brand="rips"] .packscroll{color:var(--acc);z-index:2;
    position:absolute;left:21px;width:270px;margin:0;
    bottom:var(--cue-bottom,58px);
    filter:drop-shadow(0 2px 0 var(--key)) drop-shadow(0 0 6px rgba(0,0,0,.35))}
  html[data-brand="rips"] .packscroll svg{width:40px;height:22px}
}

/* ── THE STORE (2 Sep). site/store.js is the live product's panel; these are
   the same v3 treatments the vault gets above: the skewed display title, the
   pink-ringed close, decorative text transparent to the pointer. The credit
   card art is 4:3 (brand/store/credit-card-*.png), so the 16:9 crop it shipped
   with is lifted. */
html[data-brand="rips"] .store__title{
  font-family:var(--display);font-weight:900;font-style:italic;text-transform:uppercase;
  line-height:.98;letter-spacing:-.01em;color:#fff;font-size:clamp(32px,3.4vw,44px);
  -webkit-text-stroke:4px var(--key);paint-order:stroke fill;
  transform:skewX(-7deg);transform-origin:left center;display:inline-block;pointer-events:none}
html[data-brand="rips"] .store__sub{color:#A7B0BE;pointer-events:none}
html[data-brand="rips"] .store__close{
  width:clamp(44px,4.4vw,58px);height:clamp(44px,4.4vw,58px);border-radius:14px;
  border:2px solid var(--acc);background:transparent;color:#fff;font-size:24px;line-height:1;cursor:pointer;z-index:3}
html[data-brand="rips"] .store__close:hover{border-color:var(--acc-hi);color:#fff}
html[data-brand="rips"] .scard__art{aspect-ratio:802/609;max-width:520px;margin:0 auto}
html[data-brand="rips"] .saisle__name{font-family:var(--display);font-weight:900;font-style:italic;letter-spacing:0;font-size:22px}
/* the merch art is our own die-cut sticker render (brand/store/merch), not a
   supplier photo on white, so every tile sits on the panel's dark ground */
html[data-brand="rips"] .sitem__shot,html[data-brand="rips"] .sitem__shot--light{background:#0f131b}
html[data-brand="rips"] .sitem__shot img{padding:7%;box-sizing:border-box}
html[data-brand="rips"] .sct{display:inline-flex;align-items:center;gap:7px}
html[data-brand="rips"] .sct__i{width:20px;height:20px;object-fit:contain;display:block}

/* ── the pack list ends higher (Luke, 2 Sep, again): the box is shortened
   from the BOTTOM only — the column's flexible item is the list, so What's
   Inside and the cue stay exactly where they are and the peeking last button
   is cut off behind the fade. And the cue is button-pink at every width
   (style.css:1870 paints the svg itself, which is why colour on the wrapper
   never showed). */
/* ── the rank badges are OFF (Luke, 4 Sep: "get rid of these") ────────
   visibility, not display:none and not deleting the <ul>: the row under the
   rank bar held 74.5px at 1512x820 and a different number at every other
   breakpoint (the label font-size and the ladder's own margin both move), so
   removing the element shoved RANKS & CRATE ODDS and the crate up the rail.
   Luke's constraint was the badges and NOTHING else, so the element stays and
   keeps its exact box; only the paint is off. Deleting it later means giving
   that space back deliberately. rips-glue.js still repaints it — harmless. */
html[data-brand="rips"] .ladder{visibility:hidden}
html[data-brand="rips"] .packscroll svg{color:var(--acc)}
@media (min-width:1024px){
  /* the pre-JS fallback only. app.js's snapPeek() overwrites this inline with
     the value that lands the list's bottom edge halfway down a row, which is
     what makes the peek read at EVERY window height instead of only at the one
     it was eyeballed at (this number was re-tuned by hand twice, 2 and 4 Sep,
     which is the tell that a constant was the wrong tool). */
  html[data-brand="rips"] .packlist{margin-bottom:44px}
}

/* ── Luke, 5 Sep: the new comic-sky plate ────────────────────────────────
   The landscape plate is bg-plate.png (style.css:99) and pack3d draws the
   same file as its in-scene backdrop. A phone gets its own PORTRAIT crop of
   the same artwork instead: cropping the landscape one to a phone loses the
   left and right edges, which is where its bolts and clouds live.
   Both layouts, not just the stage one — there is one background now. */
@media (max-width:1023px){
  html[data-brand="rips"] .bg{background-image:url(../bg-plate-mobile.png)}
}

/* Refer a friend (20260907a): your own code under REWARDS. The deposit row's shell; the sub-line is a plain note, not a gold warning. */
html[data-brand="rips"] .menu__code .menu__depwarn{color:var(--ink-dim)}
html[data-brand="rips"] .mrow__v--code{color:var(--key);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.4px}
html[data-brand="rips"] .mprof__ref{padding:0;margin:-2px 0 2px}
html[data-brand="rips"] .mprof__ref input{height:48px;font-size:17px}
html[data-brand="rips"] .mprof__ref .addamt{height:48px;font-size:16px}

/* CLOSE SHARES THE ROW WITH RIP AGAIN on an auto-sold pull (Luke, 8 Sep 02:40,
   reversing his 7 Sep "CLOSE stands alone": "it should say 'Rip Again' and then
   a 'Close' button next to it"). No grid-column: the row is two 1fr columns and
   the hidden buttons are display:none, so RIP AGAIN takes cell 1 and this takes
   cell 2. display:block is still needed — it is what beats the [hidden] rule
   above once the button is shown again. */
html[data-brand="rips"] .postrip__row > .postrip__close:not([hidden]){display:block}
