/* The phone as an object you can pick up.
 *
 * A real solid, not two planes. The body is an extrusion: a stack of identical rounded
 * silhouettes one pixel apart along Z, so the phone has genuine thickness and keeps its
 * rounded corners from every angle. Front and back faces cap the stack. Side buttons are
 * short stacks of their own, sitting just outside the body.
 *
 * This is why it is CSS and not WebGL. The glass has to stay a live document — tappable,
 * scrollable, readable by a screen reader — and in WebGL it would be a texture.
 *
 * The trap: overflow:hidden flattens 3D in every browser. The screen is clipped by
 * border-radius on .qb-screen, which is not itself part of the 3D context, rather than by
 * clipping .qb-phone.
 */

.qb-stage {
  position: relative;
  perspective: 1500px;
  perspective-origin: 50% 45%;
  display: grid;
  place-items: center;
  padding: 1.2rem;
  touch-action: pan-y;
}

/* The shadow lives out here, not on the phone.
   A filter — drop-shadow included — flattens a preserve-3d element in every browser, and
   does it silently: getComputedStyle still reports preserve-3d while the side rails stop
   rendering entirely. Do not put one back on .qb-phone. */
.qb-shadow {
  position: absolute;
  left: 50%;
  bottom: 2.5%;
  width: 58%;
  height: 26px;
  transform: translateX(-50%) scaleX(var(--shadow-squash, 1));
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.5), transparent 72%);
  filter: blur(10px);
  pointer-events: none;
}

.qb-phone {
  position: relative;
  /* Height-led so the frame and its controls stay on screen on a short laptop; the width
     follows from the aspect ratio, and the max-width takes over on a phone. */
  aspect-ratio: 320 / 672;
  height: min(672px, 68vh);
  width: auto;
  max-width: 82vw;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  cursor: grab;
  /* So the focus ring follows the body instead of boxing it in. */
  border-radius: var(--r, 46px);
}

.qb-phone.is-dragging { cursor: grabbing; }

/* ---- the body ---------------------------------------------------------- */

/* One slice of the extrusion. Anodised aluminium: bright along the upper edge, dark in
   the middle, with a second highlight low down, which is what makes a metal rail read as
   metal when you turn it. */
.qb-slab {
  position: absolute;
  inset: 0;
  border-radius: 46px;
  background:
    linear-gradient(180deg,
      #6d7078 0%, #3d4046 4%, #17181b 16%,
      #101114 48%,
      #24262b 74%, #4b4e55 92%, #1a1b1e 100%);
}

/* The outermost slices catch the light, so the edge does not end on a flat colour. */
/* The four real sides. The slice stack is opaque at most angles, but a stack of planes
   has no width when you look straight along it — at exactly 90 degrees the phone would
   vanish. These are the surfaces you actually see edge-on. */
.qb-rail {
  position: absolute;
  left: 50%;
  top: 50%;
  border-radius: 3px;
}

.qb-rail-l, .qb-rail-r {
  width: var(--depth);
  height: calc(var(--h) - var(--r) * 2);
  background: linear-gradient(90deg, #0d0e10 0%, #4a4d54 22%, #2b2d32 50%, #55585f 78%, #101114 100%);
}

.qb-rail-t, .qb-rail-b {
  width: calc(var(--w) - var(--r) * 2);
  height: var(--depth);
  background: linear-gradient(180deg, #0d0e10 0%, #4a4d54 22%, #2b2d32 50%, #55585f 78%, #101114 100%);
}

.qb-rail-r { transform: translate(-50%, -50%) rotateY(90deg) translateZ(calc(var(--w) / 2)); }
.qb-rail-l { transform: translate(-50%, -50%) rotateY(-90deg) translateZ(calc(var(--w) / 2)); }
.qb-rail-t { transform: translate(-50%, -50%) rotateX(90deg) translateZ(calc(var(--h) / 2)); }
.qb-rail-b { transform: translate(-50%, -50%) rotateX(-90deg) translateZ(calc(var(--h) / 2)); }

/* The raised face of a side key, for when you are looking along the edge. */
.qb-keyface {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--depth) * 0.62);
  border-radius: 2px;
  background: linear-gradient(90deg, #17181b, #70747c 45%, #3a3d43 100%);
}

.qb-slab.is-rim {
  background:
    linear-gradient(180deg,
      #9aa0aa 0%, #5b5f67 5%, #2a2c31 18%,
      #1c1e22 50%,
      #34373d 76%, #6e737c 93%, #2a2c31 100%);
}

.qb-face {
  position: absolute;
  inset: 0;
  border-radius: 46px;
  backface-visibility: hidden;
}

.qb-front {
  background: #0c0c0e;
  padding: calc(11px * var(--ps, 1));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}

.qb-back {
  background:
    radial-gradient(120% 80% at 30% 12%, #34363c 0%, transparent 55%),
    linear-gradient(155deg, #26282d 0%, #121316 55%, #1d1f23 100%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
}

/* Laid out at the size the app is drawn for, then scaled to whatever glass it has. The
   app's type is in rem and does not shrink on its own, so handing it a smaller box just
   burst the layout - the ring pushed out of its card and the greeting off the screen.
   Scaling the whole screen instead means it looks the same at every size, which is what
   a smaller handset does too. (zoom would be tidier and was tried first: Chrome paints
   only the first few glyphs of a text run inside a zoomed subtree here, so it is out.) */
.qb-screen {
  position: relative;
  width: 298px;
  height: 650px;
  transform: scale(var(--ps, 1));
  transform-origin: 0 0;
  border-radius: 35px;
  background: #000;
  overflow: hidden;
  cursor: auto;
  display: flex;
  flex-direction: column;
}

/* No native scrollbar inside a phone. It still scrolls; it just does not draw a track. */
.qb-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overscroll-behavior: contain;
}

.qb-scroll::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* A sheet of glass over the screen: a soft sweep that slides as the phone turns, so the
   front reads as covered rather than open. */
.qb-glare {
  position: absolute;
  inset: calc(11px * var(--ps, 1));
  border-radius: calc(35px * var(--ps, 1));
  pointer-events: none;
  z-index: 6;
  background: linear-gradient(
    114deg,
    transparent calc(28% + var(--glare, 0%)),
    rgba(255, 255, 255, 0.09) calc(43% + var(--glare, 0%)),
    rgba(255, 255, 255, 0.03) calc(50% + var(--glare, 0%)),
    transparent calc(64% + var(--glare, 0%)));
}

/* ---- the details that sell it edge-on ---------------------------------- */

/* Side buttons, each its own short extrusion just outside the body. */
.qb-key {
  position: absolute;
  border-radius: 3px;
  background: linear-gradient(180deg, #6a6e76, #2c2e33 40%, #17181b);
}

.qb-notch {
  position: absolute;
  top: calc(11px * var(--ps, 1));
  left: 50%;
  transform: translateX(-50%);
  width: calc(96px * var(--ps, 1));
  height: calc(26px * var(--ps, 1));
  border-radius: 0 0 calc(16px * var(--ps, 1)) calc(16px * var(--ps, 1));
  background: #000;
  z-index: 5;
  pointer-events: none;
}

/* The same move as the screen. The camera, the flash and the wordmark are all drawn in
   fixed pixels for a 320px body, so on a small phone the bump swelled to half the width
   of the handset. They are laid out at the design size and scaled as one piece. */
.qb-back-art {
  position: absolute;
  top: 0;
  left: 0;
  width: 320px;
  height: 672px;
  transform: scale(var(--ps, 1));
  transform-origin: 0 0;
}

.qb-cam {
  position: absolute;
  top: 26px;
  left: 26px;
  width: 88px;
  height: 88px;
  border-radius: 26px;
  background: linear-gradient(150deg, #303238, #131417);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.qb-cam i {
  position: absolute;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #4b525d 0%, #14161a 55%, #06070a 100%);
  box-shadow: inset 0 0 0 2px #1c1e22, 0 0 6px rgba(0, 0, 0, 0.6);
}

.qb-cam i:nth-child(1) { top: 12px; left: 12px; }
.qb-cam i:nth-child(2) { top: 12px; left: 50px; }
.qb-cam i:nth-child(3) { top: 50px; left: 12px; }

/* The fourth spot in the lens block. The lenses sit on a 12/50 grid inside .qb-cam, which
   is itself at 26,26 - so their centres are 38 and 76 from the phone's edge, and the empty
   corner's centre is 89. A 16px flash centred there starts at 81, not the 58 it had, which
   put it adrift between the lenses rather than square in the gap. */
.qb-flash {
  position: absolute;
  top: 81px;
  left: 81px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #fff6d8, #b9a986 60%, #4a4636);
}

.qb-mark {
  position: absolute;
  bottom: 46px;
  left: 0;
  right: 0;
  text-align: center;
  color: rgba(255, 255, 255, 0.2);
  font-weight: 700;
  font-stretch: 112%;
  letter-spacing: 0.02em;
  font-size: 0.95rem;
}

/* ---- the line under it -------------------------------------------------- */

/* There used to be Turn it over and Straighten up buttons here. With them gone this
   sentence is the only thing that tells anyone the frame can be dragged, so it stays. */
.qb-hint {
  color: var(--ink-dim, #5f6368);
  font-size: 0.8rem;
  text-align: center;
  margin: 0.8rem auto 0;
  max-width: 26rem;
}

@media (prefers-reduced-motion: reduce) {
  .qb-phone { transition: none !important; }
}

/* ---- the app inside the glass ------------------------------------------ */

/* Colours are the app's own dark tokens from ui/theme/Tokens.kt. Layout and every label
   are HomeScreen.kt's, checked against public/img/home.webp. */
.qb-app {
  --bg: #000; --surface: #141414; --border: #2a2a2a;
  --on: #fff; --muted: #9ba1a6; --accent: #3b82f6;
  --grad-a: #3b82f6; --grad-b: #8b5cf6;
  --danger: #ef4444; --success: #22c55e;
  background: var(--bg);
  color: var(--on);
  font: 400 13px/1.45 Archivo, "Segoe UI", system-ui, sans-serif;
  min-height: 100%;
  padding: 1rem 0.9rem 1.4rem;
  position: relative;
}

.qb-app *, .qb-app *::before, .qb-app *::after { box-sizing: border-box; }

.qb-greet { font-size: 1.25rem; font-weight: 700; font-stretch: 112%; margin: 0; }
.qb-greet-sub { color: var(--muted); font-size: 0.78rem; margin: 0.1rem 0 1rem; }

.qb-head { display: flex; align-items: flex-start; justify-content: space-between; }
.qb-round { width: 30px; height: 30px; border-radius: 50%; background: var(--surface); border: 1px solid var(--border); display: grid; place-items: center; }
.qb-round svg { width: 15px; height: 15px; fill: none; stroke: var(--on); stroke-width: 1.8; }

.qb-card {
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: 14px;
  padding: 0.8rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem;
}

.qb-label { color: var(--muted); font-size: 0.68rem; }
.qb-figure { font-size: 1.35rem; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.15; }
.qb-sub { color: var(--muted); font-size: 0.64rem; }

.qb-btn {
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  color: #fff;
  background: linear-gradient(90deg, var(--grad-a), var(--grad-b));
  padding: 0.45rem 1.1rem;
}

.qb-btn[disabled] { background: #3a3a3a; color: #bfc4c9; cursor: default; }
.qb-btn-wide { width: 100%; margin-top: 0.7rem; padding: 0.6rem; }

.qb-ring { display: grid; place-items: center; position: relative; }
.qb-ring svg { width: 92px; height: 92px; transform: rotate(-90deg); }
.qb-ring circle { fill: none; stroke-width: 7; }
.qb-ring .track { stroke: #2a2a2a; }
.qb-ring .arc { stroke: var(--accent); stroke-linecap: round; transition: stroke-dasharray 600ms ease; }
.qb-ring-mid { position: absolute; text-align: center; }

.qb-section { font-weight: 700; margin: 1.1rem 0 0.5rem; font-size: 0.9rem; }

.qb-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.45rem; }

.qb-action {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.55rem 0.15rem;
  color: var(--on);
  font: inherit;
  font-size: 0.58rem;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
  display: grid;
  gap: 0.3rem;
  justify-items: center;
}

.qb-action:hover { border-color: var(--accent); }
.qb-action svg { width: 17px; height: 17px; fill: none; stroke: var(--accent); stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

.qb-alert {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--danger);
  border-radius: 12px;
  padding: 0.7rem;
  margin-top: 0.5rem;
}

.qb-alert.is-warn { border-left-color: #f59e0b; }
.qb-alert svg { width: 16px; height: 16px; flex: none; margin-top: 1px; fill: none; stroke: var(--danger); stroke-width: 2; }
.qb-alert.is-warn svg { stroke: #f59e0b; }
.qb-alert-title { font-weight: 700; font-size: 0.8rem; }
.qb-alert-body { color: var(--muted); font-size: 0.72rem; }

.qb-tabs {
  flex: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: #0a0a0a;
  border-top: 1px solid var(--border);
  --muted: #9ba1a6;
  --accent: #3b82f6;
  font: 400 13px/1.45 Archivo, "Segoe UI", system-ui, sans-serif;
}

.qb-tab {
  background: none; border: 0; color: var(--muted);
  font: inherit; font-size: 0.58rem; font-weight: 600;
  padding: 0.55rem 0 0.7rem; cursor: pointer;
  display: grid; gap: 0.25rem; justify-items: center;
}

.qb-tab svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.qb-tab[aria-current="true"] { color: var(--accent); }

/* The cover: what the app puts over the phone's own dialog so you see "checking" instead
   of a system popup flashing past. */
.qb-cover {
  position: absolute; inset: 0;
  color: #fff;
  font: 400 13px/1.45 Archivo, "Segoe UI", system-ui, sans-serif;
  background: rgba(0, 0, 0, 0.92);
  display: grid; place-items: center; gap: 0.7rem;
  align-content: center;
  text-align: center;
  padding: 2rem;
  z-index: 3;
}

.qb-spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.15);
  border-top-color: var(--accent);
  animation: qb-spin 900ms linear infinite;
}

@keyframes qb-spin { to { transform: rotate(360deg); } }

/* The system dialog underneath, briefly visible at the edges. */
.qb-ussd { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: rgba(0,0,0,.66); z-index: 2; }
.qb-ussd-card { width: 100%; background: #303134; color: #e8eaed; border-radius: 16px; padding: 1rem; font-size: 0.75rem; }
.qb-ussd-dialled { font-weight: 700; font-size: 0.9rem; margin: 0 0 0.4rem; }
.qb-ussd-timer { height: 3px; background: rgba(255,255,255,.16); margin: 0.6rem 0 0.3rem; overflow: hidden; }
.qb-ussd-timer i { display: block; height: 100%; background: #8ab4f8; transform-origin: left; animation: qb-drain 10s linear forwards; }

@keyframes qb-drain { to { transform: scaleX(0); } }

@media (prefers-reduced-motion: reduce) {
  .qb-spinner, .qb-ussd-timer i, .qb-ring .arc { animation: none; transition: none; }
}

.qb-error { color: var(--danger); font-size: 0.72rem; margin-top: 0.6rem; }

/* ---- an interactive GTT session ---------------------------------------- */

/* The app draws the network's menu as buttons rather than leaving you in a system popup. */
.qb-session { position: absolute; inset: 0; background: #000; color: #fff; z-index: 4;
  font: 400 13px/1.45 Archivo, "Segoe UI", system-ui, sans-serif; padding: 1rem 0.9rem; overflow-y: auto; }
.qb-session-code { color: var(--muted); font-size: 0.7rem; margin: 0; }
.qb-session-body { white-space: pre-wrap; font-size: 0.8rem; margin: 0.6rem 0 1rem; }

.qb-option {
  display: block; width: 100%; text-align: left;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  color: var(--on); font: inherit; font-size: 0.8rem;
  padding: 0.65rem 0.8rem; margin-bottom: 0.45rem; cursor: pointer;
}

.qb-option:hover { border-color: var(--accent); }
.qb-option b { display: block; font-weight: 700; }
.qb-option span { color: var(--muted); font-size: 0.72rem; }

/* Explanatory copy, not a warning. The yellow disclaimer box this replaces shouted about
   invented data on screens that mostly no longer show any. */
.qb-note {
  color: var(--ink-dim, #9ba1a6);
  font-size: 0.7rem;
  line-height: 1.45;
  margin: 0 0 0.6rem;
}

.qb-session-foot { display: flex; gap: 0.5rem; margin-top: 0.8rem; }

/* ---- the seven-day chart ----------------------------------------------- */

.qb-chart { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0.35rem; height: 130px; margin-top: 0.9rem; }

/* The bar needs a track of its own: a percentage height only resolves against a parent
   with a definite one, and an auto-sized grid row is not that. The 1fr row is. */
.qb-bar { display: grid; grid-template-rows: auto 1fr auto; justify-items: center; gap: 0.25rem; height: 100%; }
.qb-bar-track { width: 100%; display: flex; align-items: flex-end; justify-content: center; }
.qb-bar i { display: block; width: 64%; min-height: 2px; border-radius: 4px 4px 0 0; background: linear-gradient(180deg, var(--grad-b), var(--grad-a)); }
.qb-bar.is-blank i { background: #2a2a2a; }
.qb-bar span { color: var(--muted); font-size: 0.56rem; }
.qb-bar em { color: var(--on); font-size: 0.56rem; font-style: normal; font-variant-numeric: tabular-nums; min-height: 0.8em; }
.qb-note { color: var(--muted); font-size: 0.68rem; margin-top: 0.8rem; }

/* ---- Services (the More tab) ------------------------------------------- */

.qb-section { font-size: 0.95rem; font-weight: 700; margin: 1rem 0 0.5rem; }

/* One row per fact: the card's own grid is two columns, which splits the labels. */
.qb-idcard { display: grid; grid-template-columns: 1fr; gap: 0.55rem; }
.qb-idcard div { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.qb-idcard span { color: var(--ink-dim, #9ba1a6); font-size: 0.68rem; }
.qb-idcard b { font-size: 0.78rem; }

.qb-service {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  margin-bottom: 0.45rem;
  padding: 0.6rem 0.7rem;
  border: 0;
  border-radius: 0.7rem;
  background: var(--qb-surface, #141414);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.qb-service-icon { display: flex; flex: 0 0 auto; }
.qb-service-icon svg { width: 20px; height: 20px; }
.qb-service-text { display: grid; gap: 0.15rem; min-width: 0; }
.qb-service-text b { font-size: 0.8rem; }

/* GTT's answer once the row has been checked, its own words wrapped onto one line. */
.qb-service-sub { font-size: 0.68rem; line-height: 1.35; }
.qb-service-sub.is-muted { color: var(--ink-dim, #9ba1a6); }

/* ---- a GTT text prompt -------------------------------------------------- */

.qb-prompt { display: flex; gap: 0.4rem; margin-top: 0.2rem; }

.qb-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  border: 1px solid #333;
  border-radius: 0.5rem;
  background: #111;
  color: #fff;
  font: inherit;
  font-size: 0.78rem;
}

/* ---- the Deals toast ---------------------------------------------------- */

/* Deals has no screen in the real app either - AppScaffold gives its bar slot a null tab
   and raises a Toast. Sits above the tab bar, like Android's own. */
.qb-toast {
  position: absolute;
  left: 50%;
  bottom: 4.2rem;
  z-index: 6;
  transform: translateX(-50%);
  max-width: 80%;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  background: rgba(240, 240, 240, 0.95);
  color: #111;
  font-size: 0.72rem;
  text-align: center;
}
