:root{
  --bg:#0f1620; --card:#172230; --line:#26344a; --text:#e8eef5; --muted:#8aa0b6;
  --accent:#1fd18e; --accent-d:#15a872; --accent2:#2f6bff; --danger:#ef4444; --r:14px;
  /* Accent-derived glow tints. server.js overrides these (and the vars above)
     per-brand via an injected :root block, so a non-green accent loses the
     green halos. These literals are just the neutral-default fallback. */
  --accent-glow-45:rgba(31,209,142,.45); --accent-glow-18:rgba(31,209,142,.18);
  --accent-glow-22:rgba(31,209,142,.22); --accent-glow-50:rgba(31,209,142,.5);
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--text);font-family:-apple-system,"Segoe UI",Roboto,Inter,system-ui,sans-serif;font-size:15px;line-height:1.45;-webkit-tap-highlight-color:transparent}
#hdr{display:flex;align-items:center;padding:13px 16px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--bg);z-index:5}
.logo{display:flex;align-items:center;gap:9px;font-weight:800;letter-spacing:.6px;font-size:17px}
.logo-mark{width:20px;height:20px;border-radius:6px;background:linear-gradient(135deg,var(--accent),var(--accent2));box-shadow:0 0 14px var(--accent-glow-45);flex:none}
.logo-img{width:26px;height:26px;border-radius:7px;object-fit:cover;flex:none}
.hero-logo{display:block;width:128px;height:128px;border-radius:20px;object-fit:cover;margin:8px auto 18px;box-shadow:0 0 30px var(--accent-glow-18)}
.logo-text b{color:var(--accent);font-weight:800}
#app{padding:16px;max-width:600px;margin:0 auto}
.center{text-align:center}.muted{color:var(--muted)}
h2{font-size:19px;margin:2px 0 14px}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:16px;margin-bottom:14px}
.contact-card{padding:2px 0 8px}
.contact-card .ct-title{font-size:10.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;text-align:center;margin-bottom:10px}
.contact-row{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}
.cpill{display:inline-flex;align-items:center;gap:6px;padding:8px 13px;border:1px solid var(--line);border-radius:99px;background:var(--inset);color:var(--text);font-size:13px;font-weight:600;cursor:pointer;text-decoration:none;white-space:nowrap;transition:border-color .15s,background .15s,transform .1s}
.cpill:hover{border-color:var(--accent)}
.cpill:active{border-color:var(--accent);background:var(--card);transform:scale(.97)}
.balance{font-size:36px;font-weight:800;letter-spacing:-.5px}
.btn{display:block;width:100%;border:none;border-radius:12px;padding:15px;font-size:15px;font-weight:700;cursor:pointer;font-family:inherit;margin-top:10px}
.btn-primary{background:var(--accent);color:var(--on-accent)}
.btn-primary:active{background:var(--accent-d)}
.btn-ghost{background:var(--card);color:var(--text);border:1px solid var(--line)}
.btn:disabled{opacity:.5}
label{display:block;font-size:11px;color:var(--muted);margin:11px 0 4px;text-transform:uppercase;letter-spacing:.05em}
input,select,textarea{width:100%;background:var(--inset);border:1px solid var(--line);border-radius:10px;padding:12px;color:var(--text);font-size:16px;font-family:inherit;outline:none}
input:focus,select:focus,textarea:focus{border-color:var(--accent)}
textarea{resize:vertical;min-height:118px;box-sizing:border-box;line-height:1.45}
.row{display:flex;gap:8px}.row>*{flex:1;min-width:0}
.rate{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px;border:1px solid var(--line);border-radius:12px;margin-bottom:9px;cursor:pointer;background:var(--card)}
.rate:active{border-color:var(--accent)}
.rate .price{font-weight:800;color:var(--accent);white-space:nowrap}
.rate .carrier{font-weight:700}.rate .name{font-size:12.5px}
/* Pickup-point picker: a search box above a height-capped scroll box so a long
   point list scrolls inside itself instead of the whole page. dvh tracks the
   Telegram WebView's live viewport; vh is the fallback for older webviews. */
.ptsearch{margin-bottom:11px}
.ptscroll{max-height:calc(100vh - 190px);max-height:calc(100dvh - 190px);overflow-y:auto;-webkit-overflow-scrolling:touch;padding-right:3px}
.ptscroll::-webkit-scrollbar{width:7px}
.ptscroll::-webkit-scrollbar-thumb{background:var(--line);border-radius:99px}
.ptscroll::-webkit-scrollbar-track{background:transparent}
.pill{display:inline-block;font-size:10.5px;padding:2px 8px;border-radius:99px;background:var(--inset);border:1px solid var(--line);color:var(--muted);margin-left:6px;white-space:nowrap}
.pill-home{background:rgba(31,209,142,.12);border-color:rgba(31,209,142,.38);color:#6ee7a8}
.pill-point{background:rgba(59,130,246,.12);border-color:rgba(59,130,246,.38);color:#93b4f8}
.pill-locker{background:rgba(168,85,247,.12);border-color:rgba(168,85,247,.38);color:#c4a3f5}
.err{background:rgba(239,68,68,.12);border:1px solid rgba(239,68,68,.3);color:#fca5a5;padding:11px 13px;border-radius:10px;margin:10px 0;font-size:14px}
.ok{background:rgba(31,209,142,.12);border:1px solid rgba(31,209,142,.3);color:var(--accent);padding:11px 13px;border-radius:10px;margin:10px 0}
.mono{font-family:ui-monospace,Menlo,Consolas,monospace;word-break:break-all;font-size:13px}
.lbl{padding:13px;border:1px solid var(--line);border-radius:12px;margin-bottom:9px;background:var(--card)}
.spin{display:inline-block;width:18px;height:18px;border:2px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:sp .8s linear infinite;vertical-align:-3px}
@keyframes sp{to{transform:rotate(360deg)}}
.seg{display:flex;gap:6px;margin-top:6px}
.seg button{flex:1;padding:11px;border-radius:10px;border:1px solid var(--line);background:var(--inset);color:var(--text);font-weight:700;cursor:pointer;font-family:inherit}
.seg button.on{background:var(--accent);color:var(--on-accent);border-color:var(--accent)}
.sugg{padding:11px 12px;border:1px solid var(--line);border-top:none;background:var(--inset);cursor:pointer;font-size:14px}
.sugg:first-child{border-top:1px solid var(--line);border-radius:8px 8px 0 0}
.sugg:last-child{border-radius:0 0 8px 8px}
.sugg:active{background:var(--card)}
/* Dozens of localities can share one postal code (PL 87-600 has 49), so the
   list scrolls instead of being cut short. overscroll-behavior keeps the drag
   inside the box — otherwise Telegram reads it as swipe-to-close the app. */
.sugglist{max-height:320px;max-height:min(320px,52dvh);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.sugglist::-webkit-scrollbar{width:7px}
.sugglist::-webkit-scrollbar-thumb{background:var(--line);border-radius:99px}
.sugglist::-webkit-scrollbar-track{background:transparent}
.sel{font-size:13px;margin-top:6px;color:var(--accent);min-height:16px}
.kv{display:flex;justify-content:space-between;gap:10px;padding:6px 0;border-bottom:1px solid var(--line)}
.kv:last-child{border:none}
.big{font-size:22px;font-weight:800;color:var(--accent)}
small{color:var(--muted)}
#lang{margin-left:auto;position:relative}
#langbtn{display:flex;align-items:center;gap:5px;background:var(--card);border:1px solid var(--line);border-radius:10px;padding:5px 8px;cursor:pointer;font-family:inherit}
#langbtn img{width:24px;height:16px;object-fit:cover;border-radius:3px;display:block}
#langbtn .chev{color:var(--muted);font-size:11px;line-height:1}
#langdd{display:none;position:absolute;top:calc(100% + 6px);right:0;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:5px;min-width:158px;box-shadow:0 10px 30px rgba(0,0,0,.5);z-index:20}
.langopt{display:flex;align-items:center;gap:10px;padding:10px;border-radius:8px;cursor:pointer;font-weight:600}
.langopt:active{background:var(--inset)}
.langopt img{width:24px;height:16px;object-fit:cover;border-radius:3px}

/* ─── Rate-search loading overlay (glassmorphism) ───
   A translucent rate-search overlay themed from the brand palette (accent +
   accent2, dark glass). Markup lives in index.html
   outside #app; driven by MRLoader in app.js. */
.search-loader{
  position:fixed; inset:0; z-index:9999;
  display:flex; align-items:center; justify-content:center;
  background:rgba(15,22,32,.66);
  -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .3s ease, visibility .3s ease;
}
.search-loader.open{opacity:1; visibility:visible; pointer-events:auto}
.sl-card{
  width:min(90vw,380px); padding:2rem 1.8rem 1.6rem; text-align:center;
  border-radius:18px; background:rgba(23,34,48,.62);
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  box-shadow:0 20px 60px rgba(0,0,0,.5); position:relative;
  transform:translateY(8px) scale(.98);
  transition:transform .3s cubic-bezier(.2,.8,.2,1);
}
.search-loader.open .sl-card{transform:translateY(0) scale(1)}
/* Gradient hairline border via a masked pseudo-element so the card body stays
   translucent (a normal border would sit over the blur). */
.sl-card::before{
  content:''; position:absolute; inset:0; border-radius:18px; padding:1px;
  background:linear-gradient(135deg,var(--accent),var(--accent2));
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude; pointer-events:none; opacity:.7;
}
.sl-icon{position:relative; width:56px; height:56px; margin:0 auto 1rem; display:flex; align-items:center; justify-content:center}
.sl-logo{width:34px; height:34px; border-radius:9px; object-fit:cover; display:block; animation:sl-bob 1.6s ease-in-out infinite; -webkit-user-select:none; user-select:none}
.sl-ring{position:absolute; inset:0; border-radius:50%; border:2px solid var(--accent-glow-22); border-top-color:var(--accent); animation:sp .9s linear infinite}
.sl-title{font-size:18px; font-weight:800; color:var(--text); letter-spacing:-.01em; margin-bottom:5px}
.sl-msg{font-size:13.5px; color:var(--muted); min-height:1.2em; margin-bottom:16px; transition:opacity .22s ease; font-family:ui-monospace,Menlo,Consolas,monospace}
.sl-track{height:6px; border-radius:100px; overflow:hidden; background:rgba(255,255,255,.07); margin-bottom:8px}
.sl-bar{height:100%; width:0%; border-radius:100px; background:linear-gradient(90deg,var(--accent),var(--accent2)); box-shadow:0 0 10px var(--accent-glow-50); transition:width .18s ease-out}
.sl-pct{font-size:11.5px; color:var(--muted); font-family:ui-monospace,Menlo,Consolas,monospace; letter-spacing:.05em}
@keyframes sl-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
@media (prefers-reduced-motion:reduce){
  .sl-logo,.sl-ring{animation:none}
  .sl-card{transition:none; transform:none}
  .sl-bar{transition:none}
  .search-loader{transition:opacity .1s linear}
}

/* ─── Customer surveys (.sv-*) ───────────────────────────────────────────────
   The Home prompt card + the one-question-per-screen sheet. Deliberately
   HEX-FREE: every colour is one of the nine :root vars every fork declares, or
   a neutral rgba(). Inset surfaces use rgba(0,0,0,.25) rather than a literal so
   they darken whatever --card the fork ships instead of painting this brand's
   palette onto a white-label. Buttons, glyphs and rings all key off --accent,
   so a fork gets its own colour for free. */
.sv-card{background:var(--card);border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:var(--r);padding:14px;margin-bottom:14px;box-shadow:0 0 18px var(--accent-glow-18,transparent)}
.sv-eyebrow{font-size:10.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:5px}
.sv-c-t{font-weight:700;font-size:15px;line-height:1.35}
.sv-c-m{font-size:12.5px;color:var(--muted);margin-top:3px}
.sv-c-a{display:flex;gap:8px;margin-top:12px}
.sv-c-a .btn{flex:1;margin-top:0;padding:12px;font-size:14px}
.sv-top{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.sv-prog{flex:1;height:6px;border-radius:99px;background:rgba(0,0,0,.25);overflow:hidden}
.sv-bar{height:100%;width:0;border-radius:99px;background:var(--accent2,var(--accent));transition:width .25s ease}
.sv-step{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.sv-q{font-size:18px;font-weight:700;line-height:1.35;margin-bottom:6px}
.sv-help,.sv-intro{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:12px;white-space:pre-line}
.sv-opts{display:flex;flex-direction:column;gap:8px}
/* Real <button> rows: keyboard-reachable, >=44px tall, state in aria-pressed
   and mirrored by a TEXT glyph (Tor "Safest" blocks SVG). */
.sv-opt{display:flex;align-items:center;gap:10px;width:100%;min-height:52px;padding:12px 14px;text-align:left;
  background:rgba(0,0,0,.25);border:1px solid var(--line);border-radius:12px;color:var(--text);
  font-family:inherit;font-size:15px;line-height:1.35;cursor:pointer}
.sv-box{flex:none;width:20px;color:var(--muted);font-size:16px;line-height:1}
.sv-opt[aria-pressed="true"]{border-color:var(--accent)}
.sv-opt[aria-pressed="true"] .sv-box{color:var(--accent)}
.sv-opt:disabled{opacity:.45;cursor:default}
.sv-stars{display:flex;gap:4px;justify-content:center;margin:4px 0 2px}
.sv-star{min-width:44px;min-height:44px;padding:4px;background:none;border:none;border-radius:10px;
  color:var(--muted);font-family:inherit;font-size:26px;line-height:1;cursor:pointer}
.sv-star.on{color:var(--accent)}
.sv-ends{display:flex;justify-content:space-between;gap:10px;font-size:11.5px;color:var(--muted)}
/* 11 pills: two rows of 6+5 on a 360px phone, one row once there is room for
   each pill to stay a comfortable target. */
.sv-nps{display:grid;grid-template-columns:repeat(6,1fr);gap:6px;margin:4px 0 6px}
@media (min-width:560px){.sv-nps{grid-template-columns:repeat(11,1fr)}}
.sv-pill{min-height:44px;background:rgba(0,0,0,.25);border:1px solid var(--line);border-radius:10px;
  color:var(--text);font-family:inherit;font-size:15px;font-weight:700;cursor:pointer}
.sv-pill[aria-pressed="true"]{border-color:var(--accent);color:var(--accent)}
.sv-ex{margin-top:12px}
.sv-ex-p{font-size:13px;color:var(--muted);line-height:1.45;margin-bottom:6px}
.sv-cnt{font-size:11.5px;color:var(--muted);text-align:right;margin-top:4px;font-variant-numeric:tabular-nums}
.sv-cnt.hot{color:var(--danger)}
/* The Telegram keyboard eats half the viewport, so the forward control rides
   the bottom edge instead of scrolling away under it. */
.sv-foot{position:sticky;bottom:0;z-index:2;padding:10px 0 4px;background:var(--bg)}
.sv-foot .btn{margin-top:0}
.sv-foot:empty{display:none}
.sv-thx{text-align:center;padding:26px 6px}
.sv-thx-i{font-size:34px;line-height:1;margin-bottom:10px;color:var(--accent)}
.sv-thx-t{font-size:19px;font-weight:800;margin-bottom:6px}
.sv-opt:focus-visible,.sv-pill:focus-visible,.sv-star:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.sv-bar{transition:none}}

/* The prompt as a floating panel. Anchored high rather than dead-centre: on a
   phone the thumb sits low and a centred panel lands under it, and a card
   further down the page is simply never seen — a sibling build stacks a hero logo,
   six contact buttons and the balance above it, so the inline card fell below
   the fold. This is NOT a modal: the backdrop dismisses on tap, the page keeps
   scrolling behind it, and the inline card stays put so the survey is still
   findable afterwards. z-index sits BELOW .smsg (9500) so a support message
   always wins if the two ever coincide. */
.sv-pop{position:fixed; inset:0; z-index:9000; display:flex; align-items:flex-start;
  justify-content:center; padding:16px; background:rgba(0,0,0,.55);
  opacity:0; visibility:hidden; pointer-events:none; transition:opacity .18s ease, visibility .18s ease}
.sv-pop.on{opacity:1; visibility:visible; pointer-events:auto}
.sv-pop-in{position:relative; width:100%; max-width:380px; margin-top:13vh;
  background:var(--card); border:1px solid var(--line); border-left:3px solid var(--accent);
  border-radius:var(--r); padding:16px 16px 14px;
  box-shadow:0 18px 50px rgba(0,0,0,.55), 0 0 18px var(--accent-glow-18,transparent);
  transform:translateY(-10px); transition:transform .18s ease}
.sv-pop.on .sv-pop-in{transform:none}
.sv-pop-x{position:absolute; top:8px; right:10px; background:none; border:0; color:var(--muted);
  font-size:20px; line-height:1; padding:6px 8px; cursor:pointer; font-family:inherit}
.sv-pop-x:hover{color:var(--text)}
.sv-pop-x:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
@media (prefers-reduced-motion:reduce){.sv-pop,.sv-pop-in{transition:none}}

/* ── Caution "kraft" row ─────────────────────────────────────────────────────
   The cheapest rates on the board, from a source whose issuing genuinely fails
   more often than the rest of the catalogue. upstream flags the row with a
   NEUTRAL `caution` boolean (never the provider key — the mini-app token hides
   it), exactly like `signature`.

   The DELIBERATE INVERSE of .rate--signature: not a dimmer highlight but a
   different MATERIAL. Signature is machined metal (an animated bezel); this is
   cardboard — matte brown plane, 3% diagonal fibre, sepia frame, no motion, no
   brand accent. A dimmer bezel would read as "signature, but broken"; a different
   material reads as a different thing, which is the message: cheap, honest, plain.
   Brand-agnostic on purpose, so this block is identical in every fork. Dark-only,
   like the rest of the storefront. ── */
.rate--caution{
  border-color:#4a3a26;
  background:
    repeating-linear-gradient(46deg,rgba(201,168,119,.030) 0 1.5px,transparent 1.5px 5px),
    linear-gradient(180deg,rgba(201,168,119,.055) 0%,rgba(201,168,119,.012) 100%),
    #16120c;
}
.rate--caution:active{border-color:#7a613e}
/* Price → flat champagne. `background:none` + text-fill reset is REQUIRED: some
   forks paint the price as a brand gradient clipped to the text, and a bare
   `color` would be overridden by `-webkit-text-fill-color:transparent`. Flat,
   never the pack/brand gradient — a premium-looking price fights the message. */
.rate--caution .price{background:none;-webkit-text-fill-color:#d9b877;color:#d9b877}
/* The advisory as a FOOTNOTE not a chip: the refund promise is the half that
   turns "the shop is broken" into "I picked the cheap one", and two words cannot
   carry it. The one full sentence in the rate list, on the row with most cause. */
.rate-caution-note{margin-top:6px;font-size:12px;line-height:1.45;color:#b99a6b;display:flex;gap:5px;align-items:flex-start}
.rate-caution-note .rcn-mark{flex:none;opacity:.85}
/* Blue clock — a measured ETA ("~10 min") or the generic deferred-issuing chip.
   Same .pill family as the delivery badges (shape inherited per fork); explicit
   margin because some forks' .pill carries none. The storefront rendered NEITHER
   timing chip before, so locker/card-checkout rates showed no ETA at all. */
.pill-clock{background:rgba(59,130,246,.14);border-color:rgba(59,130,246,.42);color:#93c5fd;margin-left:6px}

/* ── Low-reliability tariff filter (Settings › Shipping) ─────────────────────
   The card wears the same kraft material as the rows it governs — matte brown
   plane, 3% diagonal fibre, sepia frame — so the switch reads as belonging to
   THOSE rows and not to the shipping defaults under it. Brand-agnostic on
   purpose, exactly like .rate--caution: this block is identical in every fork. */
.card--kraft{
  border-color:#4a3a26;
  background:
    repeating-linear-gradient(46deg,rgba(201,168,119,.030) 0 1.5px,transparent 1.5px 5px),
    linear-gradient(180deg,rgba(201,168,119,.055) 0%,rgba(201,168,119,.012) 100%),
    #16120c;
}
.kr-row{display:flex;align-items:center;gap:12px}
.kr-row .kr-txt{flex:1;min-width:0}
.kr-row .kr-txt b{display:block;font-size:14.5px;color:#e8d9b8}
.kr-row .pill{margin:4px 0 0;display:inline-block;background:#0d0b07;border-color:#4a3a26;color:#b99a6b}
.kr-help{font-size:12.5px;line-height:1.45;margin-top:8px;color:#b99a6b}
.kr-saved{font-size:12px;font-weight:700;color:#d9b877;margin-top:9px;min-height:15px}
.kr-saved.err{color:#fca5a5}
/* The switch — the one component the storefront did not have. Pure CSS (no
   image, nothing to load) on a <button role="switch">, so it is keyboard- and
   screen-reader-operable and the state lives in aria-checked, not in a class. */
.switch{flex:none;width:46px;height:27px;border-radius:99px;cursor:pointer;border:1px solid #4a3a26;background:#0d0b07;padding:0;position:relative;transition:background .18s,border-color .18s}
.switch::after{content:'';position:absolute;top:2px;left:2px;width:21px;height:21px;border-radius:50%;background:#6b5a3c;transition:transform .18s,background .18s}
.switch[aria-checked="true"]{background:rgba(217,184,119,.20);border-color:#d9b877}
.switch[aria-checked="true"]::after{transform:translateX(19px);background:#d9b877}
.switch:disabled{opacity:.55;cursor:default}
/* "N hidden · Show" footer under a filtered rate list, and the same block as
   the whole-screen message when EVERY rate on the route was filtered out. */
.rate-hidden-line{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:10px 12px;border:1px dashed #4a3a26;border-radius:12px;color:#b99a6b;font-size:12.5px;background:rgba(201,168,119,.03)}
.rate-hidden-line b{color:#d9b877;cursor:pointer;font-weight:700;white-space:nowrap}
@media (prefers-reduced-motion: reduce){.switch,.switch::after{transition:none}}

/* ---------- support-message popup ---------- */
/* Blocking dialog: a one-shot support message, or an unread ticket reply. Sits
   at z-index 9500, above the search loader, and outside #app so a repaint can't
   wipe it. Tapping the button is what POSTs the read receipt. */
.smsg{
  position:fixed; inset:0; z-index:9500;
  display:flex; align-items:center; justify-content:center; padding:18px;
  background:rgba(0,0,0,.7);
  -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .25s ease, visibility .25s ease;
}
.smsg.open{opacity:1; visibility:visible; pointer-events:auto}
.smsg-card{
  width:min(92vw,420px); padding:18px;
  border-radius:16px; background:var(--card);
  border:1px solid var(--accent-glow-45);
  box-shadow:0 18px 60px rgba(0,0,0,.55), 0 0 24px var(--accent-glow-18);
}
.smsg-head{display:flex; align-items:center; gap:10px; margin-bottom:8px}
.smsg-head img{width:34px; height:34px; border-radius:9px; object-fit:cover; flex:none}
.smsg-brand{font-weight:800; letter-spacing:.6px; font-size:14px}
.smsg-brand b{color:var(--accent)}
.smsg-title{font-size:12.5px; color:var(--muted); font-weight:700}
.smsg-date{font-size:11px; color:var(--muted); margin-bottom:8px}
.smsg-body{
  white-space:pre-wrap; overflow-wrap:anywhere; font-size:14.5px; line-height:1.5;
  max-height:48vh; overflow-y:auto; -webkit-overflow-scrolling:touch;
  background:var(--bg); border:1px solid var(--line); border-radius:12px; padding:12px;
}

/* ---------- support tickets ---------- */
.tk-badge{display:inline-block;background:var(--danger);color:#fff;font-size:11px;font-weight:700;line-height:1;padding:2px 6px;border-radius:999px;margin-left:6px;vertical-align:middle}
.tk-inc{display:block;text-decoration:none;color:var(--text);background:var(--bg);border:1px solid var(--line);border-radius:12px;padding:11px 12px;margin-top:8px}
.tk-inc:active{border-color:var(--accent)}
.tk-inc-t{font-weight:700;font-size:13.5px}
.tk-inc-s{font-size:12.5px;margin-top:3px}
.tk-row{display:block;text-decoration:none;color:var(--text);background:var(--card);border:1px solid var(--line);border-radius:12px;padding:11px 12px;margin-bottom:10px}
.tk-row:active{border-color:var(--accent)}
.tk-chat{display:flex;flex-direction:column;gap:10px}
.tk-msg{max-width:88%;align-self:flex-start}
.tk-msg.me{align-self:flex-end;text-align:right}
.tk-from{font-size:11.5px;font-weight:700;margin-bottom:3px}
.tk-bubble{display:inline-block;text-align:left;background:var(--bg);border:1px solid var(--line);border-radius:12px;padding:9px 12px;font-size:14px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}
.tk-msg.me .tk-bubble{background:var(--accent-glow-18);border-color:var(--accent-glow-45)}
.tk-when{font-size:10.5px;margin-top:3px}

/* ── account + log out, in the app bar ──────────────────────────────────────
   Where you are signed in, and how to leave, on every screen. Logging out used
   to be buried at the bottom of the Account screen: three taps and a scroll
   from anywhere else in the app, and a customer arriving in a browser never
   found it at all. Painted by renderAcct() in app.js; empty markup is the
   correct signed-out state, which is why #acct collapses when it is empty. */
#acct{display:flex;align-items:center;gap:8px;margin-left:8px}
#acct:empty{display:none}
.acctbtn{display:inline-flex;align-items:center;gap:7px;background:var(--card);
  border:1px solid var(--line);border-radius:10px;cursor:pointer;font-family:inherit;
  font-size:12px;font-weight:700;color:var(--muted);padding:8px 12px;line-height:1;
  transition:border-color .15s,color .15s}
.acctbtn:hover,.acctbtn.on{border-color:var(--accent);color:var(--text)}
/* 14ch fits the usernames people actually pick; past that it truncates rather
   than pushing the door off the bar. */
.acctbtn .who{max-width:14ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acctbtn .whoin{display:none;font-weight:800}
/* Under 560px the name goes and its initial stands in: at that width the brand,
   a language flag, a whole username and a door do not fit on one bar. Swapped
   rather than dropped, because an empty button beside a door says nothing about
   whose account it is. */
@media (max-width:559px){
  .acctbtn .who{display:none}
  .acctbtn .whoin{display:inline}
  .acctbtn{padding:8px 10px}
}
/* A door, drawn in CSS: a frame, and the leaf leaving it. NOT an SVG (Tor's
   "Safest" refuses inline SVG and the icon would vanish with no error and no
   gap) and not an emoji, which is a different picture on every platform. */
.exitbtn{display:inline-flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--line);border-radius:10px;cursor:pointer;
  padding:9px 10px;line-height:0;color:var(--muted);transition:border-color .15s,color .15s}
.exitbtn:hover{border-color:var(--accent);color:var(--text)}
.exitbtn i{display:inline-block;position:relative;width:13px;height:14px;
  border:2px solid currentColor;border-right:0}
.exitbtn i::before{content:"";position:absolute;top:50%;right:-8px;width:8px;height:2px;
  background:currentColor;transform:translateY(-1px)}
.exitbtn i::after{content:"";position:absolute;top:50%;right:-8px;width:5px;height:5px;
  border:2px solid currentColor;border-left:0;border-bottom:0;transform:translateY(-3.5px) rotate(45deg)}

/* On /web the header logo is a real <a> back to the public homepage. It has to
   keep reading as the brand, not as a link. */
.logo{text-decoration:none;color:inherit}

/* The six home actions live in a wrapper so the browser view can lay them out
   as a bento (public/desktop.css). display:contents keeps the Mini App exactly
   as it was: the buttons stay direct flow children and stack full width. */
.dgrid{display:contents}

/* The "why is this carrier here three times?" note above the rate list.
   Amber like every other advisory in the app. The BODY takes the normal text
   colour on purpose: a whole paragraph of amber-on-amber is unreadable. */
.dupq{margin-bottom:12px;padding:9px 12px;background:rgba(251,191,36,.1);border:1px solid rgba(251,191,36,.32);border-radius:12px;font-size:12.5px;line-height:1.5}
.dupq summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px;font-weight:700;color:#fbbf24;user-select:none}
.dupq summary::-webkit-details-marker{display:none}
.dupq summary::after{content:'\25BE';margin-left:auto;transition:transform .2s}
.dupq[open] summary::after{transform:rotate(180deg)}
.dupq-b{margin-top:8px;color:var(--text);opacity:.85}
