/* ============================================================================
   custom.css — Mirai Boosts
   SellAuth PRESERVES this file across theme updates. Put styling here first.

   IMPORTANT: layouts/master.njk must load this file LAST in the CSS stack
   (after theme.css / shop-pdp.css / shop-pages.css). If a theme update resets
   that order, rules here silently stop winning. See MIRAI-CHANGES.md.

   Every custom property used below is defined in assets/theme.css :root —
   --t-bg --t-surface --t-card --t-card-2 --t-text --t-muted --t-faint
   --t-accent --t-accent-rgb --t-accent-hover --t-accent-soft --t-on-accent
   --t-green --t-star --t-border --t-border-subtle --t-border-hover
   --t-radius-btn --t-radius-card --t-radius-xs --t-nav-h --t-font --t-ease
   ============================================================================ */

/* ---------- existing platform tweaks (do not remove) ---------- */
#app { background: transparent; min-height: 100vh; display: flex; flex-direction: column; position: relative; }
.t-main { flex: 1 0 auto; position: relative; z-index: 1; }


/* ============================================================================
   1. Utilities
   ============================================================================ */
[x-cloak] { display: none !important; }

/* Visually hidden but announced by screen readers. */
.t-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}


/* ============================================================================
   2. Stock / availability badge (product page)
   Word + shape + colour. Never colour alone.
   ============================================================================ */
.t-stock-badge-wrap { margin-top: 10px; }

.t-stock-badge {
  display: inline-flex; align-items: center; gap: 7px;
  border-radius: 999px; border: 1px solid transparent;
  padding: 6px 12px; font-size: 0.8rem; font-weight: 800; letter-spacing: -0.01em;
  line-height: 1.2;
}
.t-stock-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.t-stock-ico { flex-shrink: 0; }

/* In stock — green, pulsing dot (motion reads as "live"). */
.t-stock-badge--in {
  color: var(--t-green);
  background: rgba(53, 208, 127, 0.10);
  border-color: rgba(53, 208, 127, 0.30);
}
.t-stock-badge--in .t-stock-dot { animation: t-pulse-dot 1.8s infinite; }

/* Out of stock — red, static dot (motion would imply availability). */
.t-stock-badge--out {
  color: #ff6b6b;
  background: rgba(255, 107, 107, 0.10);
  border-color: rgba(255, 107, 107, 0.30);
}

/* Currently unavailable — amber, static dot. */
.t-stock-badge--hold {
  color: var(--t-star);
  background: rgba(245, 166, 35, 0.10);
  border-color: rgba(245, 166, 35, 0.30);
}

@media (prefers-reduced-motion: reduce) {
  .t-stock-badge--in .t-stock-dot { animation: none; }
}

/* BUG FIX — products grid. theme.css sets `.t-product-info .t-stock { color: var(--t-green) }`
   and defines no `.t-stock--out` outside the PDP, so "Out of stock" cards rendered GREEN. */
.t-product-info .t-stock--out { color: #ff6b6b; }


/* ============================================================================
   3. Customer account area
   ============================================================================ */
.t-account-lede { color: var(--t-muted); font-weight: 500; margin-bottom: 16px; font-size: 0.94rem; }
.t-account-lede a { color: var(--t-accent); font-weight: 700; }

.t-account-row--stack { display: block; }
.t-account-row-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.t-account-row-id { min-width: 0; }
.t-account-row-title { overflow-wrap: anywhere; }

.t-account-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }

.t-mini-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 13px; border-radius: var(--t-radius-xs);
  border: 1px solid var(--t-border); background: rgba(255, 255, 255, 0.03);
  color: var(--t-muted); font-family: var(--t-font); font-size: 0.83rem; font-weight: 700;
  cursor: pointer; transition: color .15s, background .15s, border-color .15s;
}
.t-mini-btn:hover { color: var(--t-text); border-color: var(--t-border-hover); background: rgba(255, 255, 255, 0.07); }
.t-mini-btn--primary {
  color: var(--t-accent); border-color: rgba(var(--t-accent-rgb), 0.35);
  background: rgba(var(--t-accent-rgb), 0.10);
}
.t-mini-btn--primary:hover { color: var(--t-accent-hover); border-color: rgba(var(--t-accent-rgb), 0.55); background: rgba(var(--t-accent-rgb), 0.16); }

/* The one button a customer in trouble is looking for — give it weight. */
.t-mini-btn--help {
  color: var(--t-on-accent); border-color: color-mix(in srgb, var(--t-accent) 55%, white);
  background: linear-gradient(180deg, var(--t-accent-hover) 0%, var(--t-accent) 60%);
  box-shadow: 0 6px 18px rgba(var(--t-accent-rgb), 0.28);
}
.t-mini-btn--help:hover { color: var(--t-on-accent); background: linear-gradient(180deg, var(--t-accent-hover) 0%, var(--t-accent-hover) 100%); }

/* Order status chip */
.t-order-chip {
  flex-shrink: 0; display: inline-flex; align-items: center;
  padding: 4px 10px; border-radius: 999px; border: 1px solid var(--t-border);
  background: rgba(255, 255, 255, 0.04); color: var(--t-muted);
  font-size: 0.74rem; font-weight: 800; text-transform: capitalize;
}
.t-order-chip--completed { color: var(--t-green); border-color: rgba(53, 208, 127, 0.30); background: rgba(53, 208, 127, 0.10); }
.t-order-chip--pending,
.t-order-chip--confirming,
.t-order-chip--partially_completed,
.t-order-chip--out_of_stock { color: var(--t-star); border-color: rgba(245, 166, 35, 0.30); background: rgba(245, 166, 35, 0.10); }
.t-order-chip--refunded { color: var(--t-faint); }

/* Ticket status chip — human labels, colour is a bonus not the message */
.t-ticket-chip {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px; border-radius: 999px; border: 1px solid var(--t-border);
  background: rgba(255, 255, 255, 0.04); color: var(--t-muted);
  font-size: 0.76rem; font-weight: 800; white-space: nowrap;
}
.t-ticket-chip i { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.t-ticket-chip.is-open    { color: var(--t-accent); border-color: rgba(var(--t-accent-rgb), 0.35); background: rgba(var(--t-accent-rgb), 0.10); }
.t-ticket-chip.is-pending { color: var(--t-star);   border-color: rgba(245, 166, 35, 0.30);  background: rgba(245, 166, 35, 0.10); }
.t-ticket-chip.is-closed  { color: var(--t-green);  border-color: rgba(53, 208, 127, 0.30);  background: rgba(53, 208, 127, 0.10); }
.t-ticket-chip.is-open i { animation: t-pulse-dot 1.8s infinite; }
@media (prefers-reduced-motion: reduce) { .t-ticket-chip.is-open i { animation: none; } }

.t-ticket-hint { color: var(--t-muted); font-size: 0.84rem; font-weight: 500; margin-top: 10px; }

/* Empty states — these carry the reassurance, so they get room to breathe */
.t-account-empty { text-align: center; padding: 34px 26px; }
.t-account-empty h3 { font-size: 1.15rem; font-weight: 900; color: var(--t-text); margin-bottom: 10px; }
.t-account-empty p { color: var(--t-muted); font-weight: 500; margin-bottom: 10px; }
.t-account-empty-note { font-size: 0.86rem; color: var(--t-faint); }
.t-account-empty .t-btn { margin-top: 14px; }

.t-account-latest { margin-top: 16px; }
.t-account-latest h3 { font-size: 1rem; font-weight: 900; margin-bottom: 14px; }
.t-account-welcome .t-account-actions { margin-top: 0; }

@media (max-width: 560px) {
  .t-account-row-head { flex-direction: column; }
  .t-account-actions .t-mini-btn,
  .t-account-actions .t-btn { flex: 1 1 auto; justify-content: center; }
}


/* ============================================================================
   4. Ticket thread (/customer/tickets/<id>)
   ============================================================================ */
.t-ticket-view { display: block; }
.t-ticket-head { margin: 14px 0 20px; }
.t-ticket-head .t-legal-title { margin-bottom: 12px; overflow-wrap: anywhere; }
.t-ticket-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.t-ticket-since { color: var(--t-faint); font-size: 0.82rem; font-weight: 600; }

.t-ticket-thread { padding: 0; overflow: hidden; }
.t-ticket-messages {
  display: flex; flex-direction: column; gap: 14px;
  padding: 20px; max-height: min(58vh, 520px); min-height: 220px; overflow-y: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}
.t-ticket-msg { max-width: 86%; border-radius: var(--t-radius-card); border: 1px solid var(--t-border); padding: 12px 14px; }
.t-ticket-msg.is-theirs { align-self: flex-start; background: rgba(255, 255, 255, 0.03); }
.t-ticket-msg.is-mine   { align-self: flex-end; background: rgba(var(--t-accent-rgb), 0.10); border-color: rgba(var(--t-accent-rgb), 0.25); }
.t-ticket-msg-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 5px; }
.t-ticket-msg-top strong { font-size: 0.8rem; font-weight: 800; }
.t-ticket-msg-time { font-size: 0.72rem; color: var(--t-faint); font-weight: 600; }
.t-ticket-msg-body { font-size: 0.92rem; font-weight: 500; color: var(--t-text); overflow-wrap: anywhere; }
.t-ticket-msg-body a { color: var(--t-accent); text-decoration: underline; }

.t-ticket-composer { border-top: 1px solid var(--t-border); padding: 16px 20px; background: rgba(255, 255, 255, 0.02); }
.t-ticket-composer-row { display: flex; align-items: flex-end; gap: 10px; }
.t-ticket-input {
  flex: 1 1 auto; min-height: 44px; max-height: 140px; resize: vertical;
  padding: 11px 13px; border-radius: var(--t-radius-xs);
  border: 1px solid var(--t-border); background: rgba(0, 0, 0, 0.25);
  color: var(--t-text); font-family: var(--t-font); font-size: 0.94rem; font-weight: 500;
}
.t-ticket-input:focus { outline: none; border-color: rgba(var(--t-accent-rgb), 0.6); }
.t-ticket-send { flex-shrink: 0; }
.t-ticket-error { color: #ff6b6b; font-size: 0.84rem; font-weight: 700; margin-top: 8px; }
.t-ticket-note { color: var(--t-faint); font-size: 0.8rem; font-weight: 500; margin-top: 10px; }
.t-ticket-closed { text-align: center; }
.t-ticket-closed p { color: var(--t-muted); font-weight: 500; margin-bottom: 14px; }


/* ============================================================================
   5. Modals (login + create ticket)
   ============================================================================ */
.t-modal { position: fixed; inset: 0; z-index: 200; }
.t-modal-backdrop { position: absolute; inset: 0; background: rgba(3, 4, 8, 0.72); backdrop-filter: blur(3px); }
.t-modal-scroll {
  position: absolute; inset: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain; display: flex; align-items: center; justify-content: center; padding: 20px;
}
.t-modal-panel { position: relative; width: 100%; max-width: 520px; padding: 24px; }
.t-modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.t-modal-title { font-size: 1.25rem; font-weight: 900; letter-spacing: -0.02em; }
.t-modal-close {
  flex-shrink: 0; display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: var(--t-radius-xs); border: 1px solid var(--t-border);
  background: rgba(255, 255, 255, 0.03); color: var(--t-muted); cursor: pointer;
}
.t-modal-close:hover { color: var(--t-text); border-color: var(--t-border-hover); }
.t-modal-lede { color: var(--t-muted); font-weight: 500; font-size: 0.92rem; margin: 10px 0 18px; }
.t-modal-submit { width: 100%; margin-top: 16px; }
.t-modal-note { color: var(--t-faint); font-size: 0.8rem; font-weight: 500; margin-top: 12px; text-align: center; }

.t-field { margin-bottom: 14px; }
.t-label { display: block; font-size: 0.85rem; font-weight: 800; margin-bottom: 6px; }
.t-field-help { display: block; color: var(--t-faint); font-size: 0.8rem; font-weight: 500; margin-bottom: 8px; }
.t-input, .t-textarea {
  width: 100%; padding: 11px 13px; border-radius: var(--t-radius-xs);
  border: 1px solid var(--t-border); background: rgba(0, 0, 0, 0.25);
  color: var(--t-text); font-family: var(--t-font); font-size: 0.94rem; font-weight: 500;
}
.t-textarea { resize: vertical; min-height: 120px; line-height: 1.5; }
.t-input:focus, .t-textarea:focus { outline: none; border-color: rgba(var(--t-accent-rgb), 0.6); }
.t-input::placeholder, .t-textarea::placeholder { color: var(--t-whisper); }
.t-input.is-readonly { color: var(--t-muted); background: rgba(255, 255, 255, 0.03); pointer-events: none; }
.t-form-error { color: #ff6b6b; font-size: 0.85rem; font-weight: 700; margin-top: 8px; }

.t-otp-row { display: flex; gap: 8px; }
.t-otp-input {
  width: 44px; height: 50px; text-align: center; border-radius: var(--t-radius-xs);
  border: 1px solid var(--t-border); background: rgba(0, 0, 0, 0.25);
  color: var(--t-text); font-family: var(--t-font); font-size: 1.1rem; font-weight: 800;
}
.t-otp-input:focus { outline: none; border-color: rgba(var(--t-accent-rgb), 0.6); }

@media (max-width: 560px) {
  .t-modal-scroll { align-items: flex-start; padding: 0; }
  .t-modal-panel { max-width: 100%; min-height: 100%; border-radius: 0; }
  .t-otp-input { width: 100%; }
}


/* ============================================================================
   6. /support  (page removed — it now redirects to Discord)
   ============================================================================
   The /support landing and the language dropdown that used to live in sections
   6 and 7 were both removed at the owner's request. custom.js section 0 sends
   /support straight to the Discord invite, and templates/custom-page.njk does
   the same server-side for anyone with JS off.

   Kept from old section 7: the navbar action row still needs a reserved height
   so it does not reflow when custom.js injects the account icon.
   ============================================================================ */
.t-nav-actions { min-height: 42px; }

/* ============================================================================
   8. NAVBAR — three-zone flex row
   ============================================================================

   THE BUG THIS REPLACES
   ---------------------
   theme.css:180 laid the bar out as
       .t-nav-inner  { grid-template-columns: minmax(0,1fr) auto minmax(0,1fr); }
       .t-nav-links  { justify-self: center; }
       .t-nav-actions{ justify-self: end; }
   `minmax(0,1fr)` removes the automatic minimum from the outer tracks, so the
   third track is allowed to be narrower than the buttons inside it. Because the
   actions are `justify-self:end`, the overflow spills LEFTWARD, straight across
   the centred links. It is not a 1920-only problem: it collides at every width
   at or above 981px (where the burger has not taken over yet).

   Measured at 1920: brand 322 + links 459 + actions 446 + 2 x 26px zone gap
   = 1279px required, against an inner box of
   min(1200px, 92vw) - 2 x clamp(14px,3vw,22px) = 1156px.  Deficit 123px.

   THE FIX
   -------
   A flex row. Flex items are laid out one after another and CANNOT overlap by
   construction — there is no `justify-self:end` escape hatch to abuse. Equal
   `flex-basis: 0` + `flex-grow: 1` on the brand and the actions makes the two
   outer zones claim the same amount of free space, which keeps the links
   optically centred without positioning them.

   DO NOT "fix" the centring with `position:absolute; left:50%; translateX(-50%)`
   on .t-nav-links. That takes the links out of flow again and reintroduces
   exactly this bug class.

   Then a four-tier ladder frees the ~200px the bar was short of.
   ============================================================================ */

/* ---- 8.1 the mechanism -------------------------------------------------- */
.t-nav-inner   { display: flex; align-items: center; flex-wrap: nowrap; }
.t-nav-brand   { flex: 1 1 0; min-width: 0; overflow: hidden; }
.t-nav-links   { flex: 0 1 auto; min-width: 0; overflow: hidden; justify-content: center; white-space: nowrap; }
.t-nav-actions { flex: 1 0 0; min-width: auto; justify-content: flex-end; }
.t-nav-word    { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The links zone is the designed shrink sink (`flex: 0 1 auto; min-width: 0`
   above), but theme.css:194 gives the anchors no overflow rule, so a squeezed
   zone hard-clipped them mid-glyph instead of truncating. `min-width: 0` lets
   each anchor shrink below its own text width — flex items refuse to by
   default — and the ellipsis then reads as deliberate. `white-space: nowrap`
   is inherited from .t-nav-links; it is repeated here so the rule still works
   if that ever changes. */
.t-nav-links a { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The actions zone is the one thing that must never be squeezed: `min-width:auto`
   above restores the automatic minimum size, and shrink:0 on each child stops the
   icons themselves collapsing. Any deficit is therefore absorbed by the brand and
   the links, which both have `min-width: 0` and clip/ellipsis instead. */
.t-nav-actions > * { flex-shrink: 0; }
.t-nav-brand .t-nav-logo { flex: 0 1 auto; min-width: 0; }

/* ---- 8.2 one permanent removal ------------------------------------------ */

/* TELEGRAM IS BACK. The earlier build hid it because Discord + Telegram as full
   pills need 117 + 127 + 9 = 253px, and that did not fit once the brand, FIVE
   nav links and the language button were paid for. Two of those are now gone —
   the "Support" nav link (~89px + gap) and the language button (~62px + gap) —
   which hands back ~186px, more than the 136px the Telegram pill costs.

   Budget at >=1440, against an inner box of min(1200px,92vw) - 2 x 22 = 1156px:
       brand 322 + gap 26 + links 344 + gap 26
       + [cart 42 + 9 + Discord 117 + 9 + Telegram 127 + 9 + account 42] = 355
       = 1073px.   83px of slack.
   Tiers 8.3-8.5 below cover every narrower width. And because 8.1 made this a
   flex row, the worst case if a future change eats that slack is the brand
   ellipsing — never the overlap the old grid produced. */
.t-nav-drawer-social .t-nav-telegram { display: inline-flex; }

/* The magnifying glass linked to /#products and searched nothing. custom.js
   removes the node; this hides it first so it never flashes on a slow boot. */
.t-nav-actions .t-nav-icon[aria-label="Search"] { display: none !important; }

/* ---- 8.3 tier 2 — 1240-1439: shrink the brand (322 -> ~255) -------------- */
@media (max-width: 1439px) {
  .t-nav-logo { max-width: 120px; }
  .t-nav-word { font-size: 1.15rem; }
}

/* ---- 8.4 tier 3 — 1121-1239: Discord + Telegram go icon-only ------------- */
/* theme.css already drops the social label at 1180; this moves it to 1239 so it
   matches the tier. Two pills at 42px + gaps cost 102px instead of 262px. */
@media (max-width: 1239px) {
  .t-nav-actions .t-nav-social span { display: none; }
  .t-nav-actions .t-nav-social { padding: 0; width: 42px; justify-content: center; }
}

/* ---- 8.5 tier 4 — <=1120: burger drawer ---------------------------------- */
/* This moves the drawer breakpoint from 980 to 1120. theme.css:264 uses
   `!important` on .t-nav-hide-mobile, so this block must too — it then wins on
   source order (custom.css is loaded last; see MIRAI-CUSTOM #9 in master.njk).
   The `!important` on .t-nav-links is also load-bearing for a subtler reason:
   the unprefixed `.t-nav-links { ... }` rule in 8.1 above sits LATER in the
   cascade than theme.css's own `@media (max-width:980px){ .t-nav-links{display:none} }`,
   and media queries add no specificity — without this block the links would
   reappear on phones. */
@media (max-width: 1120px) {
  .t-nav-inner       { justify-content: space-between; }
  .t-nav-links       { display: none !important; }
  .t-nav-hide-mobile { display: none !important; }
  .t-nav-burger      { display: flex !important; }
}

/* ---- 8.6 phones — hand the width back to the wordmark -------------------- */
/* At 390px the inner box is min(1200px,92vw) - 2 x 14px = 330.8px. Cart + burger
   + gaps take 105px, leaving 225.8px for the brand. 84 + 12 + ~123 = 219. */
@media (max-width: 560px) {
  .t-nav-logo { max-width: 84px; }
  .t-nav-actions .t-nav-account { display: none !important; }
}

/* ---- 8.7 drawer hardening (paired with custom.js section 9d) ------------- */
.t-nav-drawer-inner {
  max-height: calc(100vh - var(--t-nav-h));
  overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}
/* Body scroll lock while the drawer is open. */
html.t-nav-open, html.t-nav-open body { overflow: hidden; }


/* ============================================================================
   9. PDP — MOBILE SOURCE ORDER
   ============================================================================

   shop-pdp.css:19-22 keeps .t-pdp-grid at one column until 992px, and the DOM
   order inside it is:
       .t-pdp-main  -> product image, then the description accordion (open by default)
       .t-pdp-rail  -> h1, stock badge, price, trust chips, buy form
   So on a 390px iPhone the price and the Add-to-cart button land somewhere
   between 500px and 900px below the fold. That is ~50% of all traffic, on the
   one page where the decision is made.

   `display: contents` promotes .t-pdp-main's own children to grid items of
   .t-pdp-grid, which lets the buy rail be ordered between the image and the
   description without touching product-page.njk. The Alpine `x-data` on
   .t-pdp-main is a JS scope, not a box, so it is unaffected.
   ============================================================================ */
@media (max-width: 991px) {
  .t-pdp-grid .t-pdp-main { display: contents; }

  /* image -> buy card -> description */
  .t-pdp-grid .t-pdp-main > .t-pdp-media { order: 1; }
  .t-pdp-grid > .t-pdp-rail              { order: 2; }
  .t-pdp-grid .t-pdp-main > .t-pdp-acc   { order: 3; margin-top: 0; }

  /* .t-pdp-rail only becomes a flex column at >=992px, so give its two cards a
     gap here too now that it sits between two other grid items. */
  .t-pdp-grid > .t-pdp-rail { display: flex; flex-direction: column; gap: 14px; }
}

/* MANDATORY fallback. If `display: contents` is unsupported the rule above is a
   no-op and the rail would drop back below the description, so move the whole
   rail up instead: buy card first, then image + description. Worse than the
   primary layout, far better than the current one. */
@supports not (display: contents) {
  @media (max-width: 991px) {
    .t-pdp-grid > .t-pdp-rail { order: -1; }
  }
}


/* ============================================================================
   10. MOBILE POLISH
   ============================================================================ */

/* A 78px bar eats 12% of a 390x664 viewport. Everything sticky in this theme
   (the PDP rail offset, the toast stack, the PDP section glow, the drawer
   max-height above) reads --t-nav-h, so they all follow this one number. */
@media (max-width: 640px) {
  :root { --t-nav-h: 62px; }
}

/* iPhone home-indicator clearance. No env() existed anywhere in the loaded CSS
   before this, so the last row of the drawer and the bottom of every full-screen
   sheet sat underneath the indicator on an X-and-later handset.
   The 0px fallback keeps this exact on browsers without env(). */
.t-nav-drawer-inner { padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }

@media (max-width: 640px) {
  .t-group-modal-panel,
  .t-manual-panel { padding-bottom: calc(22px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 560px) {
  .t-modal-panel { padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
}



/* ============================================================================
   11. NEW UI — restock block, footer payments, account icon.
       All t-*, all built from tokens that already exist.
       (11.1 rating chip and 11.2 vouch wall were removed with the MyVouches
       trust numbers — reviews render as SellAuth ships them.)
   ============================================================================ */

/* ---- 11.3 restock block (out-of-stock PDP) ------------------------------- */
.t-restock {
  margin-top: 14px; padding: 18px;
  border-radius: var(--t-radius-card);
  border: 1px solid rgba(245, 166, 35, 0.28);
  background: rgba(245, 166, 35, 0.07);
}
.t-restock-title { font-size: 1rem; font-weight: 900; letter-spacing: -0.02em; margin-bottom: 6px; }
.t-restock-text { color: var(--t-muted); font-weight: 500; font-size: 0.9rem; }
.t-restock-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.t-restock-actions .t-btn { width: 100%; justify-content: center; }
.t-restock-alt {
  display: block; margin-top: 12px; text-align: center;
  color: var(--t-accent); font-weight: 700; font-size: 0.88rem; text-decoration: underline;
}

/* ---- 11.4 footer payment + reassurance strip ---------------------------- */
.t-footer-pay {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 12px;
  margin-top: 30px; padding-top: 22px;
  border-top: 1px solid var(--t-border-subtle);
  color: var(--t-muted); font-weight: 600; font-size: 0.86rem; text-align: center;
}
.t-footer-pay-lock { display: inline-flex; align-items: center; gap: 7px; color: var(--t-text); font-weight: 700; }
.t-footer-pay-names { color: var(--t-muted); font-weight: 700; }
.t-footer-pay-sep { width: 1px; height: 16px; background: var(--t-border); }
.t-footer-pay a { color: var(--t-accent); font-weight: 700; }
.t-footer-pay .t-hero-pay-icons { flex-wrap: wrap; justify-content: center; }
/* The footer strip sits above the copyright line, so pull that line's rule back. */
.t-footer-pay + .t-footer-bottom { margin-top: 22px; }
@media (max-width: 560px) {
  .t-footer-pay { gap: 10px; }
  .t-footer-pay-sep { display: none; }
}

/* ---- 11.5 account icon injected into .t-nav-actions ---------------------- */
/* Reuses .t-nav-icon for its 42x42 box, so the width budget is unchanged when
   it takes the removed search icon's slot. */
.t-nav-account { position: relative; }
.t-nav-account.is-authed { color: var(--t-accent); }
.t-nav-drawer-account { display: flex; align-items: center; gap: 9px; }
.t-nav-drawer-account svg { flex-shrink: 0; color: var(--t-muted); }


/* ============================================================================
   12. MODALS MUST BE OPAQUE
   ============================================================================

   THE BUG
   -------
   Both modals — "Get help with this order" (snippets/ticket-create-modal.njk)
   and "Log in to get help" (snippets/customer-login-modal.njk) — are built as
       <div class="t-modal-panel t-pdp-card">
   and shop-pdp.css:55 paints .t-pdp-card with

       background: var(--t-pdp-card-bg);

   That custom property is declared on ONE selector, shop-pdp.css:6

       .t-pdp { --t-pdp-card-bg: rgba(17, 20, 32, 0.72); }

   so it has two separate failure modes, and the site hits both:

     1. INSIDE a product page the value resolves — but to 72% alpha, so the page
        shows through the panel.
     2. OUTSIDE a product page (/customer/invoices, /customer/tickets, the
        homepage login modal) the variable is not in scope at all. An unresolved
        var() with no fallback computes to the *initial* value of `background`,
        which is `transparent`. The panel is then 100% see-through and the order
        list reads straight through the words you are typing.

   THE FIX
   -------
   Paint the panel from a real token instead of an out-of-scope variable, and
   give it the same surface as the ticket thread card so the modal and the page
   behind it look like one system. `--t-card` (#111420) is declared on :root in
   theme.css, so it is in scope on every page.

   The `!important` is deliberate: .t-pdp .t-pdp-card is a 2-class selector and
   would otherwise beat this 1-class rule inside a product page, which is one of
   the two places the customer opens this modal from.
   ============================================================================ */
.t-modal-panel {
  background: var(--t-card, #111420) !important;
  border: 1px solid var(--t-border);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
  backdrop-filter: none;
}

/* The hairline gradient .t-pdp-card::after draws is a product-card flourish.
   On a form it reads as a stray artefact above the title — drop it. */
.t-modal-panel::after { display: none; }

/* Fields sit ON the solid panel now, so they need their own contrast rather
   than borrowing it from whatever happened to be behind the modal. */
.t-modal-panel .t-input,
.t-modal-panel .t-textarea,
.t-modal-panel .t-otp-input {
  background: var(--t-bg, #05060a);
  border-color: var(--t-border);
}
.t-modal-panel .t-input.is-readonly { background: rgba(255, 255, 255, 0.05); }

/* With an opaque panel the backdrop no longer has to carry legibility on its
   own, but a heavier scrim still tells the eye which layer is live. Alpha is
   raised rather than the blur, because backdrop-filter is the expensive part
   and Discord's in-app browser is where most of this traffic opens. */
.t-modal-backdrop { background: rgba(3, 4, 8, 0.86); }

/* ============================================================================
   MIRAI-CUSTOM #28 — touch device performance (phones + tablets)
   Complaint: scroll jank when flicking fast on phone. The JS half of this fix
   lives in theme-motion.js (Lenis no longer hijacks touch scrolling) and
   theme-joins.js (feeds pause offscreen). This block removes the GPU-heavy
   paint work. Gated on (pointer: coarse) so a desktop browser, at any window
   size, is never affected: PC keeps the exact look it has today.
   ========================================================================== */
@media (pointer: coarse) {

  /* Aurora: keep the ambient color wash, stop moving it. Three full-viewport
     composited layers animating forever is constant GPU drain on phones.
     Frozen, they cost one paint. The third blob adds the least and is cut. */
  .t-aurora span { animation: none !important; }
  .t-aurora .a3 { display: none; }

  /* Decorative glow layers: the radial gradients are already soft, the
     blur(44-72px) on top of them just multiplies rasterization cost. */
  .t-hero-haze-off, .t-hero-core, .t-demo-glow { filter: none !important; }
  .t-stats::before { filter: none !important; }

  /* Scroll reveals: opacity + shorter travel only. Animating a 10px blur on
     every card that enters the viewport is the classic fast-scroll stutter. */
  [data-reveal] { filter: none !important; transform: translateY(24px); }
  .t-mock-line { filter: none !important; }

  /* Backdrop filters force live re-blurs of everything behind them. Solid-ish
     backgrounds read the same on a phone screen and cost nothing. */
  .t-product-badge { -webkit-backdrop-filter: none; backdrop-filter: none; }
  /* Scoped so the --best / --auto gradient variants keep their colors;
     custom.css loads last and an unscoped background would flatten them. */
  .t-product-badge:not(.t-product-badge--best):not(.t-product-badge--auto) {
    background: rgba(0, 0, 0, 0.72); }
  .t-modal-backdrop { -webkit-backdrop-filter: none; backdrop-filter: none; }
}

/* ============================================================================
   13. Invite link requirements popup  (MIRAI-CUSTOM #30)
   The popup itself reuses the Nitro Yearly "Manual Delivery" classes
   (.t-manual-*, theme.css), so it matches that popup exactly. This section
   styles the extras: yellow warning icon + glow, the rules list, the red
   refund box, the Nitro Yearly popup's gem icon (13.2), and a compact
   centered popup on phones instead of a full-screen sheet (13.3).
   Markup is injected by custom.js section 10.
   ========================================================================== */
.t-invite-modal { z-index: 210; }

/* Yellow alert icon (overrides the purple .t-manual-icon tile) */
.t-invite-panel .t-invite-icon {
  width: 58px; height: 58px; border-radius: 16px;
  color: #f5b638;
  background: rgba(245, 182, 56, 0.14);
  border: 1px solid rgba(245, 182, 56, 0.35);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), 0 0 28px rgba(245, 182, 56, 0.35);
  animation: t-inv-glow 2.4s ease-in-out infinite;
}
.t-invite-panel .t-invite-icon svg { filter: drop-shadow(0 0 6px rgba(245, 182, 56, 0.55)); }
.t-invite-panel .t-invite-icon.is-ringing svg { animation: t-inv-wiggle 0.9s 0.2s ease-in-out both; }
/* soft yellow glow behind the top of the panel */
.t-invite-panel::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 150px; pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(55% 100% at 50% 0%, rgba(245, 182, 56, 0.12), transparent 70%);
}
.t-invite-panel > * { position: relative; }
.t-invite-panel .t-manual-msg { text-wrap: balance; }
.t-invite-panel > .t-manual-close { position: absolute; }
@keyframes t-inv-glow {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), 0 0 20px rgba(245, 182, 56, 0.22); }
  50% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), 0 0 36px rgba(245, 182, 56, 0.45); }
}
@keyframes t-inv-wiggle {
  0%, 100% { transform: rotate(0); } 20% { transform: rotate(-12deg); } 40% { transform: rotate(10deg); }
  60% { transform: rotate(-6deg); } 80% { transform: rotate(3deg); }
}
@media (prefers-reduced-motion: reduce) {
  .t-invite-panel .t-invite-icon, .t-invite-panel .t-invite-icon svg { animation: none !important; }
}

.t-invite-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.t-invite-list li { position: relative; padding-left: 18px; }
.t-invite-list li::before {
  content: '\30FB'; /* katakana middle dot */
  position: absolute; left: -5px; top: -2px;
  color: var(--t-accent-hover, #7d79e8); font-weight: 900; font-size: 1.25em; line-height: 1.4;
}
.t-invite-list b { color: var(--t-text, #f7f8fb); font-weight: 700; }

.t-invite-warn {
  display: flex; gap: 10px; align-items: flex-start; text-align: left;
  margin: -6px 0 18px; padding: 11px 14px;
  border-radius: 10px;
  background: rgba(241, 109, 109, 0.08);
  border: 1px solid rgba(241, 109, 109, 0.22);
  border-left: 3px solid #f16d6d;
  font-size: 0.85rem; font-weight: 500; line-height: 1.5;
  color: var(--t-muted, rgba(233, 237, 247, 0.6));
}
.t-invite-warn svg { flex-shrink: 0; color: #f16d6d; margin-top: 2px; }
.t-invite-warn b { color: #ff9a9a; font-weight: 700; }
/* ---- 13.2 Nitro Yearly popup: gem icon, pink/purple glow ---- */
.t-nitro-panel::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 160px; pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(55% 100% at 50% 0%, rgba(217, 70, 239, 0.14), rgba(124, 58, 237, 0.06) 45%, transparent 72%);
}
.t-nitro-panel > * { position: relative; }
.t-nitro-panel > .t-manual-close { position: absolute; }
.t-nitro-panel .t-manual-msg { text-wrap: balance; }
.t-manual-panel .t-nitro-icon {
  position: relative; overflow: visible;
  width: 58px; height: 58px; border-radius: 16px;
  color: #f5c2ff;
  background: linear-gradient(135deg, rgba(236, 72, 153, 0.28), rgba(139, 92, 246, 0.30));
  border: 1px solid rgba(232, 121, 249, 0.40);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 0 30px rgba(192, 38, 211, 0.35), 0 0 60px rgba(124, 58, 237, 0.18);
}
.t-nitro-icon svg { filter: drop-shadow(0 0 6px rgba(240, 171, 252, 0.6)); animation: t-nitro-float 3.2s ease-in-out infinite; }
.t-nitro-spark {
  position: absolute; width: 8px; height: 8px; pointer-events: none;
  background: #fff; opacity: 0;
  clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
  filter: drop-shadow(0 0 4px rgba(240, 171, 252, 0.9));
  animation: t-nitro-twinkle 2.6s ease-in-out infinite;
}
.t-nitro-spark.s1 { top: -4px; right: -5px; }
.t-nitro-spark.s2 { bottom: 2px; left: -7px; width: 6px; height: 6px; animation-delay: .9s; }
.t-nitro-spark.s3 { top: 8px; left: -4px; width: 5px; height: 5px; animation-delay: 1.7s; }
@keyframes t-nitro-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes t-nitro-twinkle { 0%, 100% { opacity: 0; transform: scale(.4) rotate(0); } 40%, 60% { opacity: 1; transform: scale(1) rotate(45deg); } }
@media (prefers-reduced-motion: reduce) {
  .t-nitro-icon svg, .t-nitro-spark { animation: none !important; }
  .t-nitro-spark { opacity: .8; }
}
/* ---- 13.3 Phones: compact centered popup, not a full-screen sheet ----
   theme.css and the inline <style id="theme-styles"> in master.njk force
   .t-manual-panel to 100% x 100% with !important at <=640px. These rules
   use a higher specificity (.t-manual-modal ...) with !important so they
   win. Scrolling still happens on the absolute .t-manual-scroll layer
   (the iOS-safe pattern), and margin:auto centers the panel when it fits
   without ever clipping its top when it doesn't. */
@media (max-width: 640px) {
  .t-manual-modal .t-manual-scroll {
    align-items: flex-start !important;
    padding: 16px 14px calc(16px + env(safe-area-inset-bottom, 0px)) !important;
  }
  .t-manual-modal .t-manual-panel {
    width: min(360px, 100%) !important;
    max-width: 100% !important;
    min-height: 0 !important;
    margin: auto !important;
    border-radius: 18px !important;
    padding: 22px 18px 18px !important;
  }
  .t-manual-modal .t-manual-close { top: 10px; right: 10px; width: 34px; height: 34px; }
  .t-manual-modal .t-manual-icon,
  .t-manual-modal .t-manual-panel .t-invite-icon,
  .t-manual-modal .t-manual-panel .t-nitro-icon { width: 46px; height: 46px; border-radius: 13px; margin-bottom: 10px; }
  .t-manual-modal .t-manual-icon svg { width: 22px; height: 22px; }
  .t-manual-modal .t-manual-title { font-size: 1.15rem; margin-bottom: 6px; }
  .t-manual-modal .t-manual-msg { font-size: 0.88rem; line-height: 1.5; margin-bottom: 12px; }
  .t-manual-modal .t-manual-box { padding: 12px 13px; margin-bottom: 14px; }
  .t-manual-modal .t-manual-box-title { font-size: 0.85rem; margin-bottom: 4px; }
  .t-manual-modal .t-manual-box-text { font-size: 0.82rem; line-height: 1.5; }
  .t-manual-modal .t-invite-list { gap: 6px; }
  .t-manual-modal .t-invite-warn { margin: -4px 0 14px; padding: 9px 11px; font-size: 0.78rem; gap: 8px; }
  .t-manual-modal .t-invite-warn svg { width: 16px; height: 16px; }
  .t-manual-modal .t-manual-btn { height: 44px; font-size: 0.92rem; }
  .t-manual-modal .t-nitro-panel::before,
  .t-manual-modal .t-invite-panel::before { height: 120px; }
}
/* ======================== /13. Invite popup (#30) ======================== */