  :root {
    --bg: #05070b;
    --bg-soft: #0a0d13;
    --panel: #121822;
    --panel-hi: #1a212d;
    --line: #1f2531;
    --line-hi: #2d3442;
    --text: #eef2f8;
    --muted: #8f9bad;
    --dim: #67717f;
    --accent: #3ddc84;
    --accent-glow: rgba(61, 220, 132, .14);
    --warn: #f0b429;
    --danger: #f2555a;
    --r: 14px;
    --shadow: 0 8px 28px rgba(0,0,0,.45);
  }
  * { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; }
  body {
    margin: 0; background: var(--bg); color: var(--text);
    font: 15px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
    position: relative;
  }
  .wrap { max-width: 880px; margin: 0 auto; padding: 0 20px 72px; position: relative; z-index: 1; }

  /* ---------- animated background ----------
   * Three blurred colour fields drifting on a slow loop.
   *
   * Only `transform` is animated, never width/left/opacity: a transform on an
   * already-blurred layer is composited on the GPU, so the expensive blur is
   * rasterised once and merely moved. Animating anything else would re-run an
   * 80px blur every frame, which is what makes this pattern chug on phones.
   */
  .bg {
    position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
    background: radial-gradient(140% 100% at 50% 0%, #0b1120 0%, #05070b 60%);
  }

  /* Nebula: cool gas clouds behind the stars. Deliberately NO green — the
     accent is reserved for text, prices and buttons, so it reads as
     information rather than decoration. */
  .blob {
    position: absolute; border-radius: 50%; z-index: 0;
    filter: blur(90px); opacity: .26; will-change: transform;
  }
  .b1 {
    width: 540px; height: 540px; background: #24509c;
    top: -180px; left: -140px; animation: drift1 24s ease-in-out infinite alternate;
  }
  .b2 {
    width: 460px; height: 460px; background: #1d7f9c;
    top: 8%; right: -170px; animation: drift2 31s ease-in-out infinite alternate;
  }
  .b3 {
    width: 620px; height: 620px; background: #4a2f9e;
    bottom: -300px; left: 20%; animation: drift3 38s ease-in-out infinite alternate;
    opacity: .22;
  }

  /* ---------- starfield ----------
   * Each layer is a 1px element carrying a few hundred box-shadows, plus an
   * ::after that inherits the same shadow list 2000px lower. Translating the
   * layer by exactly -2000px therefore loops seamlessly.
   *
   * Three layers at different speeds and sizes give parallax — the small faint
   * stars drift slowest, which is what sells depth.
   *
   * The shadow list is painted once and then only transformed, so this costs
   * about the same as the blobs no matter how many stars are in it.
   */
  .stars {
    position: absolute; top: 0; left: 0; width: 1px; height: 1px;
    background: transparent; border-radius: 50%; z-index: 2; will-change: transform;
  }
  .stars::after {
    content: ''; position: absolute; top: 2000px; left: 0;
    width: inherit; height: inherit; border-radius: inherit;
    box-shadow: inherit;
  }
  .s1 { animation: rise 150s linear infinite, twinkle 4.2s ease-in-out infinite; }
  .s2 { animation: rise 100s linear infinite, twinkle 5.7s ease-in-out infinite .8s; }
  .s3 { animation: rise  62s linear infinite, twinkle 3.4s ease-in-out infinite 1.6s; }

  @keyframes rise {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(0, -2000px, 0); }
  }
  @keyframes twinkle {
    0%, 100% { opacity: .62; }
    50%      { opacity: 1; }
  }

  /* ---------- logo adrift ----------
   * The mark floating among the stars, on the same depth rule as everything
   * else back here: bigger means nearer, so it drifts further and faster.
   *
   * Opacity stays low. This is scenery — the moment it competes with a price
   * or a Buy button it has stopped helping. All three share one cached image.
   */
  .float {
    position: absolute; top: 0; z-index: 2;
    user-select: none; will-change: transform, opacity;
    filter: drop-shadow(0 0 9px rgba(150,195,255,.35));
  }

  /* Kept to the outer margins, four a side. The content column is 880px
     centred, so on a desktop these stay clear of the products.
     Bigger rises faster — the same depth rule the star layers use. */
  .f1 { width: 44px; left:  3%; animation: floatUp 52s linear  0s infinite both; }
  .f2 { width: 36px; left: 13%; animation: floatUp 64s linear 12s infinite both; }
  .f3 { width: 26px; left:  8%; animation: floatUp 88s linear 30s infinite both; }
  .f4 { width: 22px; left: 17%; animation: floatUp 98s linear 55s infinite both; }
  .f5 { width: 40px; left: 96%; animation: floatUp 56s linear  6s infinite both; }
  .f6 { width: 34px; left: 84%; animation: floatUp 68s linear 47s infinite both; }
  .f7 { width: 30px; left: 92%; animation: floatUp 74s linear 38s infinite both; }
  .f8 { width: 24px; left: 88%; animation: floatUp 94s linear 20s infinite both; }

  /*
   * Straight up, no rotation, full opacity in the middle of the run.
   *
   * `both` in the shorthand above is load-bearing: during animation-delay an
   * element otherwise sits at its STATIC position, so a logo with a 55s delay
   * would be parked at top:0 in plain sight until its turn came round. With
   * fill-mode backwards it holds this 0% frame instead — off the bottom of the
   * screen and invisible.
   *
   * Opacity ramps at both ends so a mark never pops in or clips out at an
   * edge; it fades up out of the bottom and dissolves off the top.
   */
  @keyframes floatUp {
    0%   { transform: translate3d(0, 104vh, 0); opacity: 0; }
    9%   { opacity: 1; }
    80%  { opacity: 1; }
    100% { transform: translate3d(0, -170px, 0); opacity: 0; }
  }

  /* Shooting stars: mostly invisible, streaking for ~8% of a long loop so they
     feel occasional rather than decorative. */
  .shoot {
    position: absolute; width: 2px; height: 2px; border-radius: 50%;
    background: #fff; box-shadow: 0 0 7px 2px rgba(255,255,255,.45);
    opacity: 0; z-index: 3;
  }
  .shoot::after {
    content: ''; position: absolute; right: 1px; top: 0;
    width: 90px; height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.75));
  }
  .sh1 { top: 12%; left: 82%; animation: shoot 13s linear infinite 3s; }
  .sh2 { top: 34%; left: 96%; animation: shoot 19s linear infinite 11s; }

  @keyframes shoot {
    0%   { transform: translate3d(0,0,0) rotate(18deg); opacity: 0; }
    1%   { opacity: 1; }
    7%   { opacity: 1; }
    9%   { transform: translate3d(-460px, 150px, 0) rotate(18deg); opacity: 0; }
    100% { transform: translate3d(-460px, 150px, 0) rotate(18deg); opacity: 0; }
  }
  @keyframes drift1 {
    from { transform: translate3d(0,0,0) scale(1); }
    to   { transform: translate3d(120px, 90px, 0) scale(1.18); }
  }
  @keyframes drift2 {
    from { transform: translate3d(0,0,0) scale(1.1); }
    to   { transform: translate3d(-140px, 130px, 0) scale(.9); }
  }
  @keyframes drift3 {
    from { transform: translate3d(0,0,0) scale(1); }
    to   { transform: translate3d(90px, -110px, 0) scale(1.22); }
  }

  /* Keeps text readable over whatever the blobs are doing underneath, and
   * stops the colour reaching full strength at the edges of the viewport. */
  /* Sits ABOVE the nebula but BELOW the stars (z-index 1 against their 2), so
     it mutes the colour fields without dulling the stars on top of them. */
  .bg::after {
    content: ''; position: absolute; inset: 0; z-index: 1;
    background:
      radial-gradient(120% 80% at 50% 0%, transparent 30%, rgba(5,7,11,.58) 100%),
      linear-gradient(180deg, rgba(5,7,11,.24) 0%, rgba(5,7,11,.74) 100%);
  }

  /* Fewer, smaller, cheaper fields on phones -- and a lighter blur radius,
   * which is the part that actually costs on a mobile GPU. Star counts are
   * cut in JS rather than here, since they are generated, not declared. */
  @media (max-width: 640px) {
    .blob { filter: blur(60px); opacity: .26; }
    .b1 { width: 340px; height: 340px; }
    .b2 { width: 300px; height: 300px; }
    .b3 { display: none; }
    .sh2 { display: none; }
    /* On a phone the content spans the full width, so there is no "outer
       margin" to hide in. Keep four, hugging the screen edges, smaller. */
    .f2, .f4, .f6, .f8 { display: none; }
    .f1 { width: 30px; left:  2%; }
    .f3 { width: 22px; left:  8%; }
    .f5 { width: 28px; left: 90%; }
    .f7 { width: 20px; left: 83%; }
  }

  /* A moving background is exactly what this setting exists to stop. The stars,
   * the logos and the colour stay; drift, twinkle and streaking go. */
  @media (prefers-reduced-motion: reduce) {
    .blob, .stars, .float { animation: none; }
    .shoot { display: none; }
  }

  /* Set on the body when the tab is hidden -- no reason to burn a phone's
   * battery animating a page nobody is looking at. */
  body.bg-paused .blob,
  body.bg-paused .stars,
  body.bg-paused .float,
  body.bg-paused .shoot { animation-play-state: paused; }

  /* ---------- header ---------- */
  header { padding: 52px 0 8px; text-align: center; }
  .logo {
    display: inline-flex; align-items: center; gap: 12px;
    font-size: 27px; font-weight: 780; letter-spacing: -.032em;
  }
  .logo img {
    width: 46px; height: 46px; flex: none; display: block;
    /* The mark's inner disc is solid black, which would read as a hole on this
     * background. A cool halo lifts it off the page. Deliberately not green —
     * that is reserved for the wordmark and the UI. */
    filter: drop-shadow(0 0 15px rgba(140,190,255,.28));
  }
  .logo .tld { color: var(--accent); font-weight: 620; }
  .logo .sep { color: var(--dim); font-weight: 400; }
  /* The name wraps as a unit on narrow screens rather than splitting away
     from the mark, so "Profit Vending" never ends up orphaned on its own line. */
  .logo > span { display: inline-block; }
  @media (max-width: 480px) {
    .logo { font-size: 23px; gap: 10px; }
    .logo img { width: 38px; height: 38px; }
  }
  .tagline { color: var(--muted); margin: 12px 0 0; font-size: 16px; }

  .trust {
    display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
    margin: 22px 0 40px; padding: 0; list-style: none;
  }
  .trust li {
    font-size: 12.5px; color: var(--muted); background: var(--bg-soft);
    border: 1px solid var(--line); border-radius: 999px; padding: 6px 13px;
    display: inline-flex; align-items: center; gap: 6px;
  }
  .trust b { color: var(--text); font-weight: 600; }

  .cta-row {
    display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
    margin: 0 0 34px;
  }

  /* ---------- the two shops ----------
   * Whole-card links rather than a card with a button inside: the entire
   * surface is the target, which is a far easier tap on a phone. */
  .duo { display: grid; gap: 12px; grid-template-columns: 1fr; }
  @media (min-width: 640px) { .duo { grid-template-columns: 1fr 1fr; } }

  .duo-card {
    display: flex; flex-direction: column; gap: 7px;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
    padding: 20px; text-decoration: none; color: var(--text);
    box-shadow: 0 4px 18px rgba(0,0,0,.45);
    transition: border-color .16s, transform .16s, box-shadow .16s;
  }
  .duo-card:hover {
    border-color: var(--accent); transform: translateY(-3px);
    box-shadow: 0 10px 26px rgba(0,0,0,.55);
  }
  .duo-icon {
    width: 40px; height: 40px; border-radius: 11px; background: var(--accent-glow);
    display: grid; place-items: center; font-size: 21px; margin-bottom: 4px;
  }
  .duo-card h3 { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -.015em; }
  .duo-card p { margin: 0; color: var(--muted); font-size: 13.5px; }
  .duo-sub { color: var(--text) !important; font-weight: 640; font-size: 14px; }
  .duo-go { color: var(--accent); font-size: 13.5px; font-weight: 640; margin-top: auto; padding-top: 8px; }
  .duo-card:hover .duo-go { text-decoration: underline; }

  /* One step per line. The flow is short but it is a sequence, and a sequence
     crammed into a paragraph is the thing people skip. */
  .duo-list { list-style: none; padding: 0; margin: 2px 0 0; display: grid; gap: 7px; }
  .duo-list li {
    color: var(--muted); font-size: 13.5px; line-height: 1.45;
    padding-left: 21px; position: relative;
  }
  .duo-list li::before {
    content: '→'; position: absolute; left: 0; top: 0;
    color: var(--accent); font-weight: 700;
  }
  .duo-list b { color: var(--text); font-weight: 640; }

  .duo-price {
    align-self: flex-start; margin-top: 4px;
    background: var(--accent-glow); color: var(--accent);
    border: 1px solid rgba(61,220,132,.34); border-radius: 999px;
    padding: 6px 14px; font-weight: 720; font-size: 14px;
  }

  .duo-brands { display: flex; flex-wrap: wrap; gap: 5px; margin: 4px 0 0; padding: 0; list-style: none; }
  .duo-brands li {
    font-size: 12px; font-weight: 560; color: var(--text);
    background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 7px; padding: 4px 9px;
  }

  /* A section-closing call to action, under a block of explanation. */
  .sec-cta { margin-top: 18px; }

  /* ---------- what we sell ---------- */
  .range { display: grid; gap: 8px; }
  .range-row {
    display: flex; align-items: flex-start; gap: 16px;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: 12px; padding: 14px 17px;
  }
  .range-main { flex: 1; min-width: 0; }
  .range-row h4 { margin: 0 0 3px; font-size: 15px; font-weight: 660; }
  .range-row p { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.5; }
  .range-price {
    font-size: 17px; font-weight: 740; font-variant-numeric: tabular-nums;
    flex: none; color: var(--accent);
  }
  .btn.ghost-link {
    background: transparent; color: var(--text); border: 1px solid var(--line-hi);
  }
  .btn.ghost-link:hover { background: var(--panel); filter: none; }

  /* ---------- sticky nav ----------
   * Three plain links, no dropdowns. The active page is marked purely in CSS
   * off <body data-page="...">, so no JavaScript is involved in showing where
   * you are — it is correct before a single script has run.
   */
  .nav {
    position: sticky; top: 0; z-index: 40;
    background: rgba(5,7,11,.82); backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--line);
  }
  /* Three zones: brand hard left, links truly centred, account hard right.
     A grid with 1fr on both outer tracks is what makes the middle centre on
     the NAV rather than on whatever is left over after the brand. */
  .nav-in {
    max-width: 880px; margin: 0 auto; padding: 9px 20px;
    display: grid; grid-template-columns: 1fr auto 1fr;
    align-items: center; gap: 10px;
  }
  .nav-brand {
    display: flex; align-items: center; gap: 9px; text-decoration: none;
    color: var(--text); font-weight: 720; font-size: 15px; letter-spacing: -.02em;
  }
  .nav-brand img { width: 26px; height: 26px; }

  .nav-items { display: flex; gap: 2px; justify-content: center; flex-wrap: wrap; }
  .nav-right { display: flex; justify-content: flex-end; align-items: center; gap: 4px; position: relative; }

  /* Phones only: opens the page links as a column under the top bar. */
  .nav-menu-btn {
    display: none; width: 40px; height: 40px; padding: 0; border-radius: 10px;
    background: transparent; color: var(--text); place-items: center;
  }
  .nav-menu-btn:hover, .nav.menu-open .nav-menu-btn { background: var(--panel); filter: none; }

  /* ---------- notification bell ---------- */
  .nav-bell {
    position: relative; width: 38px; height: 38px; padding: 0; border-radius: 10px;
    background: transparent; color: var(--muted); display: grid; place-items: center;
  }
  .nav-bell:hover, .nav-bell[aria-expanded="true"] { background: var(--panel); color: var(--text); filter: none; }
  .bell-count {
    position: absolute; top: 3px; right: 3px; min-width: 17px; height: 17px; padding: 0 4px;
    border-radius: 999px; background: #e5484d; color: #fff; font-size: 10.5px; font-weight: 800;
    line-height: 17px; text-align: center; box-shadow: 0 0 0 2px rgba(5,7,11,.9);
  }
  .bell-count[hidden] { display: none; }
  .bell-panel {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
    width: min(360px, calc(100vw - 24px)); max-height: 440px; overflow-y: auto;
    background: var(--panel); border: 1px solid var(--line-hi); border-radius: 14px;
    box-shadow: 0 18px 44px rgba(0,0,0,.55); padding: 6px;
  }
  .bell-head { padding: 10px 12px 8px; font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--dim); }
  .bell-item {
    display: flex; gap: 10px; align-items: flex-start; padding: 11px 12px; border-radius: 10px;
    color: var(--text); text-decoration: none;
  }
  .nav-right a.bell-item { padding: 11px 12px; white-space: normal; font-weight: 400; }
  .bell-item:hover { background: var(--panel-hi); }
  .bell-item.new { background: rgba(61,220,132,.06); }
  .bell-dot { flex: none; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--accent); }
  .bell-text { display: grid; gap: 3px; min-width: 0; }
  .bell-text b { font-size: 13.5px; font-weight: 700; color: var(--text); }
  .bell-text span { font-size: 13px; color: var(--muted); line-height: 1.45; }
  .bell-text i { font-style: normal; font-size: 11.5px; color: var(--dim); }
  .bell-empty { margin: 0; padding: 14px 12px 16px; color: var(--muted); font-size: 13px; }

  /* Admin: sent notifications. */
  .nt-list { display: grid; gap: 8px; }
  .nt-row {
    display: flex; gap: 12px; align-items: flex-start; justify-content: space-between;
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px;
  }
  .nt-main { display: grid; gap: 3px; min-width: 0; }
  .nt-main b { font-size: 14px; }
  .nt-main span { font-size: 13px; color: var(--muted); }
  .nt-main i { font-style: normal; font-size: 11.5px; color: var(--dim); }
  .nt-mail { flex: none; font-size: 11.5px; color: var(--dim); white-space: nowrap; }
  .nav-right a {
    color: var(--muted); text-decoration: none; font-size: 13.5px; font-weight: 620;
    padding: 8px 13px; border-radius: 8px; white-space: nowrap;
    transition: background .14s, color .14s;
  }
  .nav-right a:hover { background: var(--panel); color: var(--text); }
  /* Signed in, the greeting is the label — mark it so it reads as "you" rather
     than as another destination. */
  .nav-right a.signed-in { color: var(--accent); }
  .nav-items a {
    color: var(--muted); text-decoration: none; font-size: 13.5px; font-weight: 620;
    padding: 8px 13px; border-radius: 8px; white-space: nowrap;
    transition: background .14s, color .14s;
  }
  .nav-items a:hover { background: var(--panel); color: var(--text); }
  .nav-items a[aria-current="page"] { background: var(--panel); color: var(--accent); }

  body[data-page="vending"] .nav-items a[href="/vending"],
  body[data-page="product"] .nav-items a[href="/vending"],
  body[data-page="warehouse"] .nav-items a[href="/warehouse"],
  body[data-page="support"] .nav-items a[href="/support"],
  body[data-page="account"] .nav-right a[href="/account"] {
    background: var(--panel); color: var(--accent);
  }

  @media (max-width: 560px) {
    .nav-in { padding: 8px 12px; gap: 4px; }
    .nav-brand span { display: none; }   /* mark only, links keep the room */
    .nav-items a, .nav-right a { padding: 7px 9px; font-size: 12.5px; }
  }

  /* ---------- page sections ---------- */
  section { padding-top: 46px; scroll-margin-top: 62px; }
  .lede-h { font-size: 21px; font-weight: 700; letter-spacing: -.02em; margin: 0 0 6px; }
  .lede-p { color: var(--muted); margin: 0 0 18px; font-size: 14.5px; }

  /* ---------- faq ---------- */
  .faq { display: grid; gap: 8px; }
  .faq details {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  }
  .faq summary {
    cursor: pointer; padding: 14px 16px; font-size: 14.5px; font-weight: 620;
    list-style: none; display: flex; justify-content: space-between; gap: 12px;
  }
  .faq summary::-webkit-details-marker { display: none; }
  .faq summary::after { content: '+'; color: var(--dim); font-weight: 400; font-size: 18px; }
  .faq details[open] summary::after { content: '−'; }
  .faq p { margin: 0; padding: 0 16px 15px; color: var(--muted); font-size: 13.5px; }

  /* ---------- proof ---------- */
  .ticker { display: grid; gap: 7px; }
  .tick {
    display: flex; align-items: center; gap: 11px;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: 10px; padding: 11px 14px; font-size: 13.5px;
  }
  .tick .dotg {
    width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-glow); flex: none;
  }
  .tick .when { margin-left: auto; color: var(--dim); font-size: 12px; flex: none; }

  /* ---------- recent success: Discord embeds ----------
     Discord's own embed metrics and dark-theme colours, so a Taco Bell order
     reads the same here as it does in the server. */
  /* One row of same-size cards, slid along by app.js. The edges fade out so a
     card entering or leaving reads as moving, not as being cut off. */
  .feed { position: relative; }
  .feed-viewport {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%);
  }
  .feed-track { display: flex; gap: 12px; width: max-content; will-change: transform; }

  /* Every card the same size, whatever it holds. */
  .feed .dc-embed {
    flex: 0 0 290px; height: 220px; box-sizing: border-box; overflow: hidden;
    gap: 10px; padding: 6px 12px 12px 10px; font-size: 13px;
  }
  @media (max-width: 560px) { .feed .dc-embed { flex-basis: 250px; } }
  .feed .dc-main { display: flex; flex-direction: column; min-height: 0; }
  .feed .dc-author { margin-top: 6px; font-size: 12.5px; }
  .feed .dc-author img { width: 20px; height: 20px; }
  .feed .dc-title { margin-top: 5px; font-size: 14.5px; }
  .feed .dc-desc {
    margin-top: 5px;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
  }
  .feed .dc-fields { margin-top: 6px; gap: 6px; }
  .feed .dc-fname { margin-bottom: 1px; }
  .feed .dc-thumb { width: 52px; height: 52px; margin-top: 6px; }
  /* The footer sits on the bottom edge, so short cards line up with long ones. */
  .feed .dc-foot { margin-top: auto; padding-top: 6px; font-size: 11px; }
  .feed .dc-foot img { width: 16px; height: 16px; }
  .dc-embed {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px;
    background: #2b2d31; border-left: 4px solid var(--bar, #1e1f22); border-radius: 4px;
    padding: 8px 16px 16px 12px; color: #dbdee1;
    font: 14px/1.375 "gg sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  }
  .dc-main { min-width: 0; }
  .dc-author { display: flex; align-items: center; gap: 8px; margin-top: 8px;
    font-size: 14px; font-weight: 600; color: #f2f3f5; }
  .dc-author img { width: 24px; height: 24px; border-radius: 50%; }
  .dc-title { margin-top: 8px; font-size: 16px; font-weight: 600; color: #f2f3f5; }
  .dc-desc { margin-top: 8px; white-space: pre-wrap; overflow-wrap: anywhere; }
  .dc-fields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 8px; }
  .dc-field { grid-column: 1 / -1; min-width: 0; }
  .dc-field.inline { grid-column: auto; }
  .dc-fname { font-weight: 600; color: #f2f3f5; margin-bottom: 2px; }
  .dc-fval { white-space: pre-wrap; overflow-wrap: anywhere; }
  .dc-embed b { color: #f2f3f5; }
  .dc-embed a { color: #00a8fc; text-decoration: none; }
  .dc-embed a:hover { text-decoration: underline; }
  .dc-embed code { background: #1e1f22; border-radius: 3px; padding: 0 3px; font-size: 85%; }
  .dc-thumb { width: 80px; height: 80px; border-radius: 3px; object-fit: contain; margin-top: 8px; }
  .dc-foot { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 12px; color: #b5bac1; }
  .dc-foot img { width: 20px; height: 20px; border-radius: 50%; }
  .empty-note {
    background: var(--bg-soft); border: 1px dashed var(--line-hi); border-radius: 12px;
    padding: 16px; color: var(--muted); font-size: 13.5px;
  }

  /* ---------- section furniture ---------- */
  /* A solid bar, not a floating label. Against a moving starfield a bare
     heading reads as weightless — a real surface anchors each section and
     makes the four of them scan as chapters. */
  .sec-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin: 0 0 20px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-left: 3px solid var(--accent);
    border-radius: 12px;
    padding: 15px 20px;
    box-shadow: 0 4px 18px rgba(0,0,0,.45);
  }
  h2 {
    font-size: 23px; font-weight: 780; letter-spacing: -.025em;
    text-transform: none; color: var(--text); margin: 0; line-height: 1.2;
  }
  @media (max-width: 560px) { h2 { font-size: 20px; } .sec-head { padding: 13px 16px; } }

  .live { font-size: 12px; color: var(--dim); display: inline-flex; align-items: center; gap: 6px; flex: none; }
  .live .pulse {
    width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
    animation: pulse 2.4s ease-in-out infinite;
  }
  @keyframes pulse { 0%,100% { opacity: .35 } 50% { opacity: 1 } }

  /* ---------- product grid ---------- */
  .grid { display: grid; gap: 12px; grid-template-columns: 1fr; }
  @media (min-width: 640px) { .grid { grid-template-columns: 1fr 1fr; } }

  /* Solid, opaque, and deliberately lighter than the sky behind it. Against a
     near-black background a card only reads as a physical surface if it has
     real contrast and a shadow — otherwise it looks like a hole. */
  .card {
    background: var(--panel);
    border: 1px solid var(--line); border-radius: var(--r);
    padding: 18px; display: flex; flex-direction: column; gap: 12px;
    box-shadow: 0 4px 18px rgba(0,0,0,.45);
    transition: border-color .16s, transform .16s, box-shadow .16s;
  }
  .card:not(.out):hover {
    border-color: var(--line-hi); transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(0,0,0,.55);
  }
  /* Dim the CONTENT, never the card itself — fading the whole element would
     let the starfield show through and undo the surface. */
  .card.out > * { opacity: .45; }

  /* A card that opens its product page: the whole card is the target, so the
     hover says so — lift, accent outline, and the name picks up the accent. */
  .card.link { cursor: pointer; transition: transform .16s ease, border-color .16s ease, box-shadow .16s ease; }
  .card.link:hover, .display .card.link:hover {
    transform: translateY(-3px); border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-glow), 0 10px 26px rgba(0,0,0,.35);
  }
  .card.link:hover h3 { color: var(--accent); }
  .card.link.out:hover > * { opacity: .7; }

  /* ---------- product page ---------- */
  /* "Back to all items" on a product page: a red button in the top-left corner,
     so the way out of a product is the first thing on the screen. */
  .back-link {
    display: inline-flex; align-items: center; gap: 6px;
    margin: 22px 0 8px; padding: 9px 16px; border-radius: 10px;
    background: #d63a3f; color: #fff; font-size: 13.5px; font-weight: 700;
    text-decoration: none; box-shadow: 0 2px 8px rgba(214,58,63,.3);
    transition: background .15s ease, transform .15s ease;
  }
  .back-link:hover { background: #b92d32; color: #fff; transform: translateY(-1px); }
  .back-link:focus-visible { outline: 3px solid rgba(214,58,63,.45); outline-offset: 2px; }
  /* It is also a <button> on the Warehouse terminal, where it hides on the stock pane. */
  button.back-link { border: 0; cursor: pointer; font-family: inherit; line-height: 1.2; }
  .back-link[hidden] { display: none; }
  .prod {
    display: grid; gap: 22px; grid-template-columns: 1fr; align-items: center;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
    padding: 22px; margin-top: 8px; box-shadow: 0 4px 18px rgba(0,0,0,.45);
  }
  @media (min-width: 720px) { .prod { grid-template-columns: 260px minmax(0, 1fr); padding: 28px; gap: 30px; } }
  .prod-media {
    display: grid; place-items: center; aspect-ratio: 1; width: 100%; max-width: 260px; margin: 0 auto;
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 16px;
  }
  .prod-icon { font-size: 104px; line-height: 1; display: grid; place-items: center; }
  .prod-icon .bi.xl { width: 128px; height: 128px; }
  .prod-icon.logo {
    width: 64%; aspect-ratio: 1; padding: 18px; background: #f2f6fa;
    border-radius: 28px; box-shadow: 0 8px 22px rgba(0,0,0,.5);
  }
  .prod-icon.logo .bi.xl { width: 100%; height: 100%; }
  .prod-title { margin: 0 0 8px; font-size: 26px; font-weight: 760; letter-spacing: -.02em; line-height: 1.2; }
  .prod-price { font-size: 30px; font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; margin-bottom: 10px; }
  .prod-price .was { color: var(--dim); font-size: 18px; font-weight: 600; text-decoration: line-through; margin-right: 4px; }
  .prod-desc { color: var(--muted); font-size: 15px; margin: 14px 0 0; white-space: pre-line; }
  .prod-buy { width: 100%; margin-top: 18px; padding: 14px 22px; font-size: 16px; }
  @media (min-width: 720px) { .prod-buy { width: auto; min-width: 220px; } }
  #how-to-use .steps { margin-top: 14px; }

  /* Brief pulse when a card is jumped to from the Product menu, so it is
     obvious which one of six you were sent to. */
  .card.flash { animation: flash 1.5s ease-out; }
  @keyframes flash {
    0%   { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
    100% { border-color: var(--line);   box-shadow: 0 4px 18px rgba(0,0,0,.45); }
  }

  .card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
  .card h3 { margin: 0; font-size: 16px; font-weight: 660; letter-spacing: -.01em; line-height: 1.35; }
  .price { font-size: 20px; font-weight: 760; font-variant-numeric: tabular-nums; letter-spacing: -.02em; flex: none; }
  .desc { color: var(--muted); font-size: 13.5px; margin: 0; flex: 1; }

  .card-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 2px; }
  .badge {
    font-size: 11.5px; font-weight: 620; letter-spacing: .02em; padding: 4px 9px;
    border-radius: 999px; border: 1px solid transparent; white-space: nowrap;
  }
  .badge.ok   { color: var(--accent); background: rgba(61,220,132,.10); border-color: rgba(61,220,132,.22); }
  .badge.low  { color: var(--warn);   background: rgba(240,180,41,.10); border-color: rgba(240,180,41,.24); }
  .badge.none { color: var(--danger); background: rgba(242,85,90,.09);  border-color: rgba(242,85,90,.22); }

  /* ---------- buttons ---------- */
  button, .btn {
    font: inherit; border: 0; border-radius: 10px; cursor: pointer;
    padding: 11px 18px; font-size: 14px; font-weight: 660;
    background: var(--accent); color: var(--accent-ink, #05230f);
    transition: filter .14s, transform .1s; text-decoration: none;
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  }
  /* An author display on `button` outranks the user agent's [hidden] rule —
     origin beats specificity — so a hidden button would still show. */
  [hidden] { display: none !important; }

  button:hover:not(:disabled), .btn:hover { filter: brightness(1.09); }
  button:active:not(:disabled) { transform: scale(.985); }
  button:disabled { background: #232935; color: #5d6673; cursor: not-allowed; }
  button.ghost {
    background: transparent; color: var(--text);
    border: 1px solid var(--line-hi);
  }
  button.ghost:hover { background: var(--panel-hi); filter: none; }
  :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

  /* ---------- how it works ---------- */
  .steps { display: grid; gap: 10px; grid-template-columns: 1fr; margin: 44px 0 0; }
  @media (min-width: 640px) { .steps { grid-template-columns: repeat(3, 1fr); } }
  /* Four steps go 2x2 rather than four-across — at this container width four
     columns leaves each one too narrow to read comfortably. */
  @media (min-width: 640px) { .steps.four { grid-template-columns: repeat(2, 1fr); } }
  .step {
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 12px; padding: 15px 16px;
  }
  .step .n {
    width: 22px; height: 22px; border-radius: 6px; background: var(--accent-glow);
    color: var(--accent); font-size: 12px; font-weight: 720;
    display: grid; place-items: center; margin-bottom: 9px;
  }
  .step h4 { margin: 0 0 3px; font-size: 14px; font-weight: 640; }
  .step p { margin: 0; font-size: 13px; color: var(--muted); }

  /* ---------- checkout dialog ---------- */
  dialog {
    background: var(--panel); color: var(--text); border: 1px solid var(--line-hi);
    border-radius: 16px; padding: 0; max-width: 430px; width: calc(100% - 28px);
    box-shadow: var(--shadow);
  }
  dialog::backdrop { background: rgba(5,7,10,.76); backdrop-filter: blur(3px); }
  .modal { padding: 22px 22px 24px; }

  .m-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
  .m-head h3 { margin: 0; font-size: 17px; font-weight: 680; line-height: 1.3; }
  .x {
    background: none; border: 0; color: var(--dim); font-size: 22px; line-height: 1;
    padding: 0 2px; cursor: pointer; flex: none;
  }
  .x:hover { color: var(--text); filter: none; }
  .amount { font-size: 30px; font-weight: 780; letter-spacing: -.03em; margin: 6px 0 2px; }
  .amount small { font-size: 13px; font-weight: 500; color: var(--muted); letter-spacing: 0; }

  /* method tabs */
  .methods { display: flex; gap: 6px; margin: 18px 0 14px; }
  .methods button {
    flex: 1; background: var(--bg-soft); color: var(--muted); border: 1px solid var(--line);
    padding: 9px 4px; font-size: 13px; font-weight: 600; border-radius: 9px;
  }
  .methods button[aria-selected="true"] {
    background: var(--accent-glow); color: var(--accent); border-color: rgba(61,220,132,.34);
  }

  /* copy rows */
  .field { margin-bottom: 10px; }
  .field label { display: block; font-size: 11.5px; color: var(--dim); margin-bottom: 5px;
                 text-transform: uppercase; letter-spacing: .07em; font-weight: 620; }
  .copyrow {
    display: flex; align-items: stretch; gap: 8px;
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px;
    padding: 4px 4px 4px 13px;
  }
  .copyrow .val {
    flex: 1; min-width: 0; align-self: center; overflow-x: auto; white-space: nowrap;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 15px; user-select: all;
    scrollbar-width: none;
  }
  .copyrow .val::-webkit-scrollbar { display: none; }
  .copyrow.code-row { border-color: rgba(61,220,132,.32); background: rgba(61,220,132,.055); }
  .copyrow.code-row .val { font-size: 20px; font-weight: 720; letter-spacing: .13em; color: var(--accent); }
  .copyrow button {
    flex: none; padding: 8px 13px; font-size: 12.5px; border-radius: 7px;
    background: var(--panel-hi); color: var(--text); border: 1px solid var(--line-hi);
  }
  .copyrow button.done { background: var(--accent); color: #05230f; border-color: transparent; }

  .hint { font-size: 12.5px; color: var(--muted); margin: 8px 0 0; }
  .hint strong { color: var(--warn); font-weight: 640; }

  .deeplink { width: 100%; margin-top: 12px; }
  /* Links inside a checkout dialog, e.g. "Sign in" on a guest order. */
  dialog .hint a { color: var(--accent); font-weight: 640; }

  /* Credit offered inside the checkout, for an order that is already open. */
  .credit-strip {
    display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
    margin-top: 12px; padding: 9px 10px 9px 13px; border-radius: 11px; font-size: 13.5px;
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.3);
  }
  .credit-strip button { padding: 8px 13px; font-size: 13px; }
  #credit-slot .status { margin-top: 12px; }

  /* Paying with balance: no payment methods, payment note or waiting line, and
     the amount loses its "send this exact amount" — there is nothing to send. */
  #modal.balance-mode .methods,
  #modal.balance-mode #method-body,
  #modal.balance-mode .field,
  #modal.balance-mode #stat,
  #modal.balance-mode .amount small { display: none; }
  .balance-pay {
    margin-top: 14px; padding: 14px; border-radius: 12px;
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.3);
  }
  .balance-pay p { margin: 0 0 12px; font-size: 14px; line-height: 1.45; }

  /* Paying by card: no handle, and no payment note to copy. */
  #modal.card-mode .field:has(.code-row) { display: none; }
  .card-pay { margin-top: 14px; }
  .card-pay p { margin: 0 0 12px; font-size: 14px; line-height: 1.45; color: var(--dim); }

  /* Under the confirmed screen: where to find the order again. */
  .paid-orders-note { text-align: center; margin: 14px 0 0; }

  /* How to use it, under the delivered code on Payment confirmed. */
  .paid-howto {
    margin-top: 14px; padding: 12px 14px 4px; border-radius: 11px;
    background: var(--bg-soft); border: 1px solid var(--line);
  }
  .paid-howto h4 {
    margin: 0 0 8px; font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--dim);
  }
  .paid-howto ol { margin: 0; padding-left: 20px; }
  .paid-howto li { margin: 0 0 10px; font-size: 13.5px; color: var(--muted); line-height: 1.45; }
  .paid-howto li b { display: block; color: var(--text); font-weight: 650; }

  /* The same steps on a Warehouse card, folded until asked for. */
  .card-howto { font-size: 13px; color: var(--muted); }
  .card-howto summary { cursor: pointer; font-weight: 640; color: var(--accent); font-size: 13px; }
  .card-howto ol { margin: 8px 0 0; padding-left: 20px; }
  .card-howto li { margin: 0 0 7px; line-height: 1.45; }
  .card-howto li b { display: block; color: var(--text); font-weight: 640; }

  /* Admin: Edit product, opened on the card itself. */
  .aitem-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex: none; }
  .a-edit { padding: 6px 11px; font-size: 12px; }
  .a-editform {
    margin: 12px 0 4px; padding: 14px; border-radius: 11px;
    background: var(--bg-soft); border: 1px solid var(--line-hi);
  }
  .a-editform a { color: var(--accent); }

  /* status */
  .status {
    margin-top: 16px; padding: 13px 14px; border-radius: 11px; font-size: 13.5px;
    display: flex; align-items: center; gap: 10px;
  }
  .status.wait { background: var(--bg-soft); color: var(--muted); border: 1px solid var(--line); }
  .status.done { background: rgba(61,220,132,.09); color: var(--accent); border: 1px solid rgba(61,220,132,.28); }
  .status.err  { background: rgba(242,85,90,.09); color: var(--danger); border: 1px solid rgba(242,85,90,.26); }
  .spinner {
    width: 15px; height: 15px; border: 2px solid var(--line-hi); border-top-color: var(--accent);
    border-radius: 50%; animation: spin .8s linear infinite; flex: none;
  }
  @keyframes spin { to { transform: rotate(360deg) } }
  .timer { margin-left: auto; font-variant-numeric: tabular-nums; font-size: 12.5px; color: var(--dim); }
  .timer.urgent { color: var(--warn); }

  pre.delivery {
    background: rgba(61,220,132,.06); border: 1px solid rgba(61,220,132,.3); border-radius: 10px;
    padding: 14px; white-space: pre-wrap; word-break: break-word; user-select: all;
    font-family: ui-monospace, monospace; font-size: 14px; margin: 12px 0 0; line-height: 1.5;
  }
  @keyframes pop { from { transform: scale(.97); opacity: 0 } to { transform: scale(1); opacity: 1 } }
  .paid-view { animation: pop .28s ease-out; }

  .resume {
    background: rgba(240,180,41,.08); border: 1px solid rgba(240,180,41,.26); color: var(--warn);
    border-radius: 12px; padding: 13px 15px; margin-bottom: 18px; font-size: 13.5px;
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  }
  .resume button { margin-left: auto; padding: 7px 14px; font-size: 13px; }

  footer { margin-top: 52px; text-align: center; color: var(--dim); font-size: 12.5px; }
  footer a { color: var(--muted); }

  /* A link inside running text — "Message us on Discord", "open a support
     ticket". Highlighted so it reads as something to press, not just words. */
  .text-link {
    color: var(--accent); font-weight: 650; text-decoration: underline;
    text-decoration-thickness: 2px; text-underline-offset: 3px;
    text-decoration-color: rgba(61,220,132,.45);
    background: var(--accent-glow); border-radius: 4px; padding: 0 3px;
    transition: background .15s ease, text-decoration-color .15s ease;
  }
  .text-link:hover { text-decoration-color: currentColor; background: rgba(61,220,132,.2); }
  .display .text-link { text-decoration-color: rgba(11,143,75,.4); }
  .display .text-link:hover { background: rgba(11,143,75,.16); }
  .skeleton {
    height: 132px; border-radius: var(--r); border: 1px solid var(--line);
    background: linear-gradient(100deg, var(--panel) 30%, var(--panel-hi) 50%, var(--panel) 70%);
    background-size: 220% 100%; animation: shimmer 1.3s linear infinite;
  }
  @keyframes shimmer { to { background-position: -220% 0 } }
  .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }


  /* A section's action lives in its header bar, right-aligned opposite the
     title. Smaller than a hero button so it sits inside the bar cleanly. */
  .sec-head .btn {
    flex: none; padding: 9px 17px; font-size: 13.5px; border-radius: 9px;
  }
  @media (max-width: 480px) {
    .sec-head { flex-wrap: wrap; gap: 10px; }
    .sec-head .btn { width: 100%; }
  }

  /* ---------- two-column section body ---------- */
  .split { display: grid; gap: 18px; grid-template-columns: 1fr; align-items: start; }
  @media (min-width: 780px) { .split { grid-template-columns: 1fr 330px; } }

  /* ---------- vending machine ----------
   * Modelled on a modern touchscreen unit: white cabinet, a bezelled display
   * carrying a rotating banner over a product grid, keypad and card reader in
   * a right-hand column, PUSH flap and coin return below.
   *
   * Built in CSS rather than shipped as an image so the screen shows REAL
   * stock — a photo of a vending machine is decoration; this is a readout.
   */
  .vm {
    position: relative;
    background: linear-gradient(180deg, #fcfcfd 0%, #eef0f3 46%, #e1e4e9 100%);
    border: 1px solid #d3d7de;
    border-radius: 18px 18px 7px 7px;
    padding: 13px 12px 0;
    box-shadow: 0 26px 52px rgba(0,0,0,.6), inset 0 1px 0 #fff;
  }

  /* Cabinet top: brand centred, cooling vents parked at the right edge.
     The vents are taken out of flow so they cannot pull the brand off centre. */
  .vm-brand {
    position: relative; display: flex; align-items: center; justify-content: center;
    gap: 7px;
    /* Centred over the SCREEN, not the whole cabinet. The right-hand control
       column is 52px plus a 9px gap, so reserving 61px on this side pulls the
       centre point left to line up with the display below it. */
    padding: 1px 61px 11px 2px;
  }
  .vm-brand span {
    font-size: 9.5px; font-weight: 800; letter-spacing: .15em; color: #2b3039;
  }
  .vm-vents {
    position: absolute; right: 2px; top: 2px;
    display: grid; grid-template-columns: repeat(6, 3px);
    grid-auto-rows: 3px; gap: 3px;
  }
  .vm-vents i { background: #c6cad2; border-radius: 1px; }

  .vm-main { display: flex; gap: 9px; align-items: stretch; }
  .vm-left { flex: 1; min-width: 0; }
  .vm-right { width: 52px; flex: none; display: flex; flex-direction: column; gap: 7px; }

  /* Black bezel, white panel inside. */
  .vm-screen {
    background: #0a0c10; padding: 4px; border-radius: 5px;
    box-shadow: inset 0 0 0 1px #31363f, 0 1px 2px rgba(0,0,0,.5);
  }
  .vm-display { position: relative; background: #eef3f8; border-radius: 2px; overflow: hidden; }
  /* The mark as wallpaper. On a lit panel it is the dark disc of the logo that
     shows through, so this sits lower than the phone's version. */
  .vm-display::before {
    content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: url('/logo.png') no-repeat center 44% / 112px 112px;
    opacity: .25;
  }
  .vm-hero, .vm-cells, .vm-osd { position: relative; z-index: 1; }
  /* Glass reflection across the panel. */
  .vm-display::after {
    content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 4;
    background: linear-gradient(114deg, rgba(255,255,255,.2) 0 26%, transparent 40%);
  }

  /* The rotating banner, the equivalent of the promo video on a real unit. */
  .vm-hero { position: relative; height: 92px; overflow: hidden; }
  .vm-track { display: flex; height: 100%; transition: transform .6s cubic-bezier(.4,0,.2,1); }
  .vm-slide {
    flex: 0 0 100%; display: flex; align-items: center; gap: 11px; padding: 0 14px;
    background: linear-gradient(118deg, #e6eef7 0%, #e3f0e9 100%);
  }
  .vm-slide .e { font-size: 34px; line-height: 1; flex: none; }
  /* Stack them: these are inline spans, so without this the stock line renders
     beside the name instead of under it (and its margin-top does nothing). */
  .vm-slide .t { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
  .vm-slide .n {
    font-size: 12px; font-weight: 780; color: #16202c; line-height: 1.25;
    letter-spacing: -.01em;
  }
  /* Chosen against white, not against the page palette. */
  .vm-slide .s { font-size: 10px; font-weight: 700; }
  .vm-slide .s.ok   { color: #0d7a3f; }
  .vm-slide .s.low  { color: #a86a00; }
  .vm-slide .s.none { color: #b3261e; }

  .vm-dots {
    position: absolute; bottom: 6px; right: 8px; z-index: 3; display: flex; gap: 4px;
  }
  .vm-dots i {
    width: 4px; height: 4px; border-radius: 50%; background: rgba(22,32,44,.24);
    transition: width .3s, background .3s;
  }
  .vm-dots i.on { width: 12px; border-radius: 2px; background: #16202c; }

  /* Product grid. Hairline gaps read as the panel's own cell borders. */
  .vm-cells {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 1px; background: #ccd6e2; border-top: 1px solid #ccd6e2;
  }
  .vm-cell {
    background: #f2f6fa; min-height: 62px; padding: 7px 3px 6px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  }
  .vm-cell .ce { font-size: 17px; line-height: 1; }
  .vm-cell .cn {
    font-size: 7.5px; font-weight: 650; color: #545f6d; line-height: 1.2;
    text-align: center; max-width: 100%;
  }
  .vm-cell .cp { font-size: 10px; font-weight: 800; color: #16202c; }
  .vm-cell.out { opacity: .38; }

  /* Touch-panel footer, as on the real unit. */
  .vm-osd {
    display: flex; justify-content: space-around; align-items: center;
    padding: 5px 2px; background: #e8eff6; border-top: 1px solid #ccd6e2;
  }
  .vm-osd div { text-align: center; font-size: 6.5px; color: #7f8b99; font-weight: 700; }
  .vm-osd b { display: block; font-size: 11px; font-weight: 400; }

  /* The dispenser door is the way into the shop — pushing it opens the
     machine, which is the one affordance on a vending machine everybody
     already understands. */
  .vm-door { display: block; text-decoration: none; }

  .vm-push {
    display: block; text-align: center; font-size: 11.5px; font-weight: 800;
    letter-spacing: .34em; color: #39404a; padding: 13px 0 9px; text-indent: .34em;
    transition: color .16s;
  }
  .vm-door:hover .vm-push { color: var(--accent-deep, #0d7a3f); }

  /* Recessed dispenser flap. */
  .vm-flap {
    display: block; background: #e6e9ee; border-radius: 5px; padding: 6px;
    box-shadow: inset 0 1px 3px rgba(0,0,0,.2);
    transition: box-shadow .16s;
  }
  .vm-flap i {
    display: flex; align-items: center; justify-content: center;
    height: 54px; border-radius: 3px; font-style: normal;
    font-size: 10px; font-weight: 800; letter-spacing: .13em; text-indent: .13em;
    color: rgba(61,220,132,.82);
    background: linear-gradient(180deg, #171b21 0%, #0a0d11 100%);
    box-shadow: inset 0 4px 12px rgba(0,0,0,.95);
    transition: transform .16s, color .16s, box-shadow .16s;
  }
  /* The door dips inward on hover, the way a real flap gives when pushed. */
  .vm-door:hover .vm-flap i {
    color: var(--accent); transform: translateY(1px);
    box-shadow: inset 0 6px 16px rgba(0,0,0,.98), 0 0 14px rgba(61,220,132,.22);
  }
  .vm-door:active .vm-flap i { transform: translateY(2px); }
  .vm-door:focus-visible .vm-flap { outline: 2px solid var(--accent); outline-offset: 3px; }

  /* --- right-hand controls --- */
  .vm-pad {
    background: #0d1016; border-radius: 5px; padding: 6px 5px;
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 3px;
  }
  .vm-pad i {
    height: 8px; border-radius: 2px;
    background: linear-gradient(180deg, #fdfdfe, #d6dae1);
    box-shadow: 0 1px 0 rgba(0,0,0,.6);
  }

  .vm-reader { position: relative; background: #0d1016; border-radius: 5px; height: 58px; }
  .vm-reader::after {
    content: ''; position: absolute; left: 8px; right: 8px; top: 13px; height: 4px;
    border-radius: 2px; background: #000;
    box-shadow: inset 0 1px 1px rgba(255,255,255,.14);
  }

  .vm-coin { display: flex; gap: 4px; }
  .vm-coin div { flex: 1; text-align: center; font-size: 5px; font-weight: 800; color: #6d7684; letter-spacing: .02em; }
  .vm-coin b {
    display: block; width: 13px; height: 13px; margin: 3px auto 0; border-radius: 50%;
    background: radial-gradient(circle at 34% 28%, #454c56, #10131a);
    box-shadow: inset 0 -1px 2px rgba(0,0,0,.8);
  }

  /* Lock strip down the cabinet edge. */
  .vm-lock {
    position: absolute; right: 4px; top: 64px; bottom: 128px; width: 6px;
    border-radius: 3px;
    background: linear-gradient(90deg, #b9bec7, #f1f3f6 45%, #b9bec7);
  }

  .vm-bottom { display: flex; align-items: flex-end; justify-content: flex-end; padding: 11px 4px 14px; }
  .vm-return { text-align: center; font-size: 5.5px; font-weight: 800; color: #6d7684; }
  .vm-return i {
    display: block; width: 25px; height: 15px; margin: 3px auto 0; border-radius: 3px;
    background: #0b0e13; box-shadow: inset 0 2px 5px rgba(0,0,0,.9);
  }

  /* Levelling feet, poking out below the cabinet. */
  .vm-leg {
    position: absolute; bottom: -7px; width: 15px; height: 7px;
    background: #8d949f; border-radius: 0 0 4px 4px;
  }
  .vm-leg.l { left: 13%; }
  .vm-leg.r { right: 13%; }

  /* ---------- plain fact list ----------
     Short fragments, two columns on a desktop. Scanning beats reading on a
     landing page — nobody works through a paragraph to find out what a shop is. */
  .facts { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
  @media (min-width: 640px) { .facts { grid-template-columns: 1fr 1fr; gap: 10px 24px; } }
  .facts li {
    position: relative; padding-left: 27px;
    font-size: 14.5px; color: var(--muted); line-height: 1.45;
  }
  .facts li::before {
    content: '✓'; position: absolute; left: 0; top: -1px;
    color: var(--accent); font-weight: 800; font-size: 15px;
  }
  .facts b { color: var(--text); font-weight: 660; }

  /* ---------- section-1 phone ----------
     A handset running the shop: home screen of product "apps", one gets
     tapped, it opens into the purchase flow, then back to home for the next. */
  .widget-wrap { display: flex; flex-direction: column; }
  .widget {
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
    box-shadow: 0 4px 18px rgba(0,0,0,.45);
    padding: 22px 18px; display: flex; align-items: center; justify-content: center;
    min-height: 470px; overflow: hidden;
  }

  .ph { width: 250px; }
  /* White handset, black screen — the same cabinet finish as the vending
     machine, so the two devices on the page read as one family. */
  .ph-body {
    background: linear-gradient(180deg, #fcfcfd 0%, #eef0f3 50%, #e1e4e9 100%);
    border: 1px solid #d3d7de; border-radius: 32px;
    padding: 11px 11px 0;
    box-shadow: 0 18px 40px rgba(0,0,0,.62), inset 0 1px 0 #fff;
  }
  .ph-speaker { width: 46px; height: 4px; border-radius: 3px; background: #c6cad2; margin: 3px auto 9px; }

  .ph-screen {
    background: linear-gradient(170deg, #0d1420 0%, #05080d 60%);
    border-radius: 18px; overflow: hidden; position: relative;
    box-shadow: inset 0 0 0 1px #262d39;
  }
  /* The mark as wallpaper. Low enough not to fight the content on top of it,
     and it is the white ring and glyph that show through on a black screen. */
  .ph-screen::before {
    content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: url('/logo.png') no-repeat center 46% / 160px 160px;
    opacity: .25;
  }
  .ph-status, .ph-stage { position: relative; z-index: 1; }
  .ph-status {
    display: flex; justify-content: space-between; align-items: center;
    padding: 6px 12px 3px; font-size: 8.5px; font-weight: 700; color: #8f9bad;
  }
  .ph-stage {
    min-height: 316px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 7px;
    text-align: center; padding: 6px 14px 16px;
  }

  /* The chin, with a real home button. */
  .ph-chin { height: 52px; display: grid; place-items: center; }
  .ph-home-btn {
    width: 30px; height: 30px; border-radius: 50%;
    background: linear-gradient(180deg, #fbfbfc, #e6e9ee);
    box-shadow: inset 0 0 0 1.5px #c2c7d0, 0 1px 2px rgba(0,0,0,.18);
  }

  /* --- home screen --- */
  .ph-apps {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px 6px;
    width: 100%; padding: 4px 2px;
  }
  .ph-app { display: flex; flex-direction: column; align-items: center; gap: 5px; }
  .ph-app i {
    width: 47px; height: 47px; border-radius: 13px; display: grid; place-items: center;
    font-size: 24px; font-style: normal;
    background: linear-gradient(160deg, #1e2532, #141a25);
    border: 1px solid #2c3441; box-shadow: 0 3px 7px rgba(0,0,0,.55);
  }
  .ph-app span { font-size: 8px; font-weight: 620; color: #c3ccda; letter-spacing: .01em; }
  /* The tap: press in, overshoot, settle — plus a ring, so it reads as a
     deliberate touch rather than the icon just wobbling. */
  .ph-app.tap i {
    animation: app-tap .6s ease-out;
    border-color: rgba(61,220,132,.6);
  }
  @keyframes app-tap {
    0%   { transform: scale(1);   box-shadow: 0 0 0 0 rgba(61,220,132,.5); }
    35%  { transform: scale(.84); box-shadow: 0 0 0 6px rgba(61,220,132,.22); }
    70%  { transform: scale(1.1); box-shadow: 0 0 0 12px rgba(61,220,132,0); }
    100% { transform: scale(1);   box-shadow: 0 0 0 0 rgba(61,220,132,0); }
  }

  /* --- an opened app --- */
  @keyframes app-open { from { transform: scale(.62); opacity: 0 } to { transform: scale(1); opacity: 1 } }
  .ph-view { width: 100%; animation: app-open .34s cubic-bezier(.2,.8,.3,1) both; }
  .ph-appbar {
    display: flex; align-items: center; gap: 7px; width: 100%;
    padding: 0 0 9px; margin-bottom: 9px; border-bottom: 1px solid #1b2230;
  }
  .ph-appbar .ic { font-size: 14px; }
  .ph-appbar .nm { font-size: 10.5px; font-weight: 720; color: #dce4ef; }
  .ph-inner { display: flex; flex-direction: column; align-items: center; gap: 7px; }

  .ph-emoji { font-size: 52px; line-height: 1; }
  .ph-name { font-size: 13.5px; font-weight: 700; color: var(--text); line-height: 1.3; }
  .ph-retail { font-size: 12px; color: var(--dim); text-decoration: line-through; }
  .ph-price { font-size: 32px; font-weight: 820; letter-spacing: -.03em; color: var(--text); }
  .ph-price.sm { font-size: 25px; }
  .ph-save {
    font-size: 11px; font-weight: 720; color: var(--accent);
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.3);
    border-radius: 999px; padding: 4px 11px;
  }
  .ph-btn {
    margin-top: 8px; width: 100%; background: var(--accent); color: #05230f;
    font-size: 13.5px; font-weight: 720; border-radius: 10px; padding: 10px 0;
    animation: ph-pulse 1.6s ease-out .3s infinite;
  }
  @keyframes ph-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(61,220,132,.42); }
    70%  { box-shadow: 0 0 0 12px rgba(61,220,132,0); }
    100% { box-shadow: 0 0 0 0 rgba(61,220,132,0); }
  }

  .ph-step { font-size: 10.5px; color: var(--dim); font-weight: 620; }
  .ph-code {
    font-family: ui-monospace, Menlo, monospace; font-size: 17px; font-weight: 780;
    letter-spacing: .12em; color: var(--accent);
    background: rgba(61,220,132,.08); border: 1px dashed rgba(61,220,132,.42);
    border-radius: 8px; padding: 9px 12px; margin-top: 3px;
  }
  .ph-msg { font-size: 11.5px; color: var(--muted); display: flex; align-items: center; gap: 7px; margin-top: 3px; }
  .ph-msg.done { color: var(--accent); font-weight: 740; font-size: 13.5px; }
  .ph-check {
    width: 50px; height: 50px; border-radius: 50%; display: grid; place-items: center;
    background: var(--accent-glow); border: 2px solid rgba(61,220,132,.45);
    color: var(--accent); font-size: 24px; font-weight: 800;
  }
  .ph-reveal {
    width: 100%; background: rgba(61,220,132,.07); border: 1px solid rgba(61,220,132,.32);
    border-radius: 8px; padding: 9px; font-family: ui-monospace, Menlo, monospace;
    font-size: 11px; color: var(--text); word-break: break-all;
  }

  /* Inside the split there is not room for two columns of bullets. */
  .facts-1col { grid-template-columns: 1fr !important; }

  /* Brand logos, when public/brands has one for that SKU. Sized to match the
     emoji they replace so no layout shifts when a file is added. */
  .bi { display: block; object-fit: contain; }
  .ph-app .bi { width: 30px; height: 30px; }
  .ph-appbar .bi { width: 15px; height: 15px; }
  .ph-emoji .bi.lg { width: 56px; height: 56px; margin: 0 auto; }
  .vm-slide .bi.md { width: 34px; height: 34px; }
  .vm-cell .bi.sm { width: 19px; height: 19px; }

  /* A SKU with a real logo gets a white tile. Brand marks are drawn for print
     and white backgrounds — black, dark brown and baked-in white all fail on a
     dark screen — and a white tile is what a phone home screen shows anyway. */
  .ph-app i.logo {
    background: #f2f6fa; border-color: #ccd6e2; padding: 7px;
    box-shadow: 0 3px 8px rgba(0,0,0,.45);
  }
  .ph-app i.logo .bi { width: 100%; height: 100%; }

  .ph-appbar .ic.logo {
    background: #f2f6fa; border-radius: 5px; padding: 2px;
    display: inline-grid; place-items: center; width: 20px; height: 20px;
  }
  .ph-appbar .ic.logo .bi { width: 100%; height: 100%; }

  .ph-emoji.logo {
    width: 86px; height: 86px; margin: 0 auto; padding: 13px;
    background: #f2f6fa; border-radius: 20px;
    display: grid; place-items: center;
    box-shadow: 0 5px 16px rgba(0,0,0,.5);
  }
  .ph-emoji.logo .bi.lg { width: 100%; height: 100%; }

  .vm-slide .e.logo {
    width: 46px; height: 46px; padding: 6px; background: #f2f6fa;
    border: 1px solid #ccd6e2; border-radius: 11px;
    display: grid; place-items: center;
  }
  .vm-slide .e.logo .bi.md { width: 100%; height: 100%; }

  /* ================= /vending : inside the machine =================
     The page as the machine's own display. A white cabinet frame with the
     starfield still visible around it, so it reads as zoomed IN rather than
     as a page that merely has a border. */
  .stage { max-width: 940px; margin: 0 auto; padding: 22px 16px 70px; position: relative; z-index: 1; }
  @media (max-width: 560px) { .stage { padding: 12px 8px 50px; } }

  .cabinet {
    background: linear-gradient(180deg, #fcfcfd 0%, #eef0f3 40%, #e1e4e9 100%);
    border: 1px solid #d3d7de;
    border-radius: 26px;
    padding: 16px 16px 0;
    box-shadow: 0 34px 70px rgba(0,0,0,.66), inset 0 1px 0 #fff;
  }
  @media (max-width: 560px) { .cabinet { border-radius: 18px; padding: 10px 10px 0; } }

  .cabinet-top {
    position: relative; display: flex; align-items: center; justify-content: center;
    padding: 2px 2px 13px;
  }
  .cabinet-top span { font-size: 11px; font-weight: 800; letter-spacing: .17em; color: #2b3039; }
  .cabinet-vents {
    position: absolute; right: 2px; top: 2px;
    display: grid; grid-template-columns: repeat(6, 3px); grid-auto-rows: 3px; gap: 3px;
  }
  .cabinet-vents i { background: #c6cad2; border-radius: 1px; }

  /* Black bezel, bright panel inside. */
  .bezel {
    background: #0a0c10; padding: 7px; border-radius: 12px;
    box-shadow: inset 0 0 0 1px #31363f, 0 2px 4px rgba(0,0,0,.5);
  }

  /*
   * The display runs a LIGHT palette by overriding the theme tokens for its
   * subtree only. Almost everything on the page already reads var(--panel),
   * var(--text) and friends, so the whole shop flips to a bright touchscreen
   * without a second set of components.
   */
  .display {
    /* Deliberately NOT pure white. A full-brightness #fff panel this large is
       glare on a dark page at night — the whole viewport goes from near-black
       to maximum luminance. These sit a few steps down: still obviously a lit
       touchscreen, but a surface you can look at for a while. */
    --bg: #e7edf4;
    --bg-soft: #dee6ef;
    --panel: #f2f6fa;
    --panel-hi: #e8eff6;
    --line: #ccd6e2;
    --line-hi: #b0bccb;
    --text: #16202c;
    --muted: #545f6d;
    --dim: #7f8b99;
    /* Darker than the site green: #3ddc84 on white is about 1.7:1, which is
       unreadable. This clears 4.5:1 for text. */
    --accent: #0b8f4b;
    --accent-ink: #ffffff;
    --accent-glow: rgba(11,143,75,.11);
    --warn: #9a6100;
    --danger: #b3261e;
    --shadow: 0 6px 20px rgba(16,24,40,.1);

    background: linear-gradient(180deg, #edf2f8 0%, #e1e9f1 100%);
    color: var(--text);
    border-radius: 6px;
    padding: 26px 22px 30px;
    position: relative; overflow: hidden;
  }
  @media (max-width: 560px) { .display { padding: 18px 13px 22px; } }

  /* Glass sheen over the panel. */
  .display::before {
    content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: url('/logo.png') no-repeat center 34% / 400px 400px;
    opacity: .25;
  }
  .display::after {
    content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 5;
    background: linear-gradient(116deg, rgba(255,255,255,.17) 0 22%, transparent 36%);
  }
  .display > * { position: relative; z-index: 1; }

  /* Hardcoded greens elsewhere in the sheet assume a dark ground; restate the
     few that appear inside the display so they hold up on white. */
  .display .badge.ok { color: var(--accent); background: rgba(11,143,75,.10); border-color: rgba(11,143,75,.26); }
  .display .badge.low { color: var(--warn); background: rgba(154,97,0,.10); border-color: rgba(154,97,0,.26); }
  .display .badge.none { color: var(--danger); background: rgba(179,38,30,.09); border-color: rgba(179,38,30,.24); }
  .display .card { box-shadow: 0 2px 10px rgba(16,24,40,.07); }
  .display .card:not(.out):hover { box-shadow: 0 8px 20px rgba(16,24,40,.13); }
  .display .sec-head { box-shadow: 0 2px 10px rgba(16,24,40,.07); }
  .display .step { background: var(--bg-soft); }
  /* A product on the machine's screen: the same soft surface as the cards around it. */
  .display .prod { box-shadow: 0 2px 10px rgba(16,24,40,.07); }
  .display .prod-media { background: var(--bg-soft); }
  .display .back-link { margin: 0 0 14px; position: relative; z-index: 1; }
  .display .live .pulse, .display .dotg { background: var(--accent); }

  .display-head { text-align: center; margin-bottom: 22px; }
  .display-head h1 {
    margin: 0 0 5px; font-size: 25px; font-weight: 800; letter-spacing: -.025em; color: var(--text);
  }
  .display-head p { margin: 0; color: var(--muted); font-size: 14px; }

  /* Touch-panel footer, as on the real unit. */
  .display-osd {
    display: flex; justify-content: center; gap: 30px;
    margin-top: 26px; padding-top: 14px; border-top: 1px solid var(--line);
  }
  .display-osd div { text-align: center; font-size: 9px; font-weight: 700; color: var(--dim); letter-spacing: .06em; }
  .display-osd b { display: block; font-size: 15px; font-weight: 400; margin-bottom: 2px; }

  /* Cabinet furniture below the screen. */
  .cabinet-push {
    display: block; text-align: center; font-size: 12px; font-weight: 800;
    letter-spacing: .34em; text-indent: .34em; color: #39404a; padding: 15px 0 10px;
  }
  .cabinet-tray {
    background: #e6e9ee; border-radius: 6px; padding: 7px;
    box-shadow: inset 0 1px 3px rgba(0,0,0,.2);
  }
  .cabinet-tray i {
    display: block; height: 46px; border-radius: 4px;
    background: linear-gradient(180deg, #171b21 0%, #0a0d11 100%);
    box-shadow: inset 0 4px 12px rgba(0,0,0,.95);
  }
  .cabinet-foot { display: flex; align-items: flex-end; justify-content: flex-end; padding: 12px 4px 16px; }
  .cabinet-return { text-align: center; font-size: 6px; font-weight: 800; color: #6d7684; }
  .cabinet-return i {
    display: block; width: 27px; height: 16px; margin: 3px auto 0; border-radius: 3px;
    background: #0b0e13; box-shadow: inset 0 2px 5px rgba(0,0,0,.9);
  }

  /* ---------- zoom-into-the-machine transition ----------
     Browse Stock clears the page down to the background, leaves the real
     machine where it stands, then eases it to centre and scales it up before
     handing over to /vending.

     Progressive enhancement: the handler only takes a plain left-click, and
     if anything fails the link is an ordinary link. A transition is never
     allowed to be the reason a link is broken. */
  body.clearing .nav,
  body.clearing .stage,
  body.clearing .wrap {
    opacity: 0; pointer-events: none;
    transition: opacity .38s ease;
  }
  /* The background stays — it is the one thing that carries across. */

  .vm-flying {
    transition: transform .78s cubic-bezier(.35, 0, .2, 1);
    will-change: transform;
    z-index: 200;
  }

  /* Arrival on /vending: the cabinet settles out of the zoom. Kept gentle to
     match the modest scale it arrives at. */
  @keyframes cab-land { from { transform: scale(1.07); opacity: 0 } to { transform: scale(1); opacity: 1 } }
  .cabinet { animation: cab-land .44s cubic-bezier(.2,.8,.3,1) both; }

  @media (prefers-reduced-motion: reduce) {
    .cabinet { animation: none; }
  }

  /* ---------- account ---------- */
  .acct { display: grid; gap: 12px; }
  @media (min-width: 720px) { .acct.two { grid-template-columns: 1fr 1fr; align-items: start; } }
  .panel {
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
    padding: 20px; box-shadow: 0 4px 18px rgba(0,0,0,.45);
  }
  .panel h3 { margin: 0 0 4px; font-size: 16px; font-weight: 700; }
  .panel .sub { margin: 0 0 16px; color: var(--muted); font-size: 13.5px; }

  .field-row { margin-bottom: 12px; }
  .field-row label {
    display: block; font-size: 11.5px; font-weight: 620; color: var(--dim);
    text-transform: uppercase; letter-spacing: .07em; margin-bottom: 5px;
  }
  .field-row input {
    width: 100%; background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; padding: 11px 13px; color: var(--text);
    font-size: 14.5px; font-family: inherit;
  }
  .field-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
  /* Dropdowns match the text boxes, with their own arrow in place of the browser's. */
  .field-row select {
    width: 100%; background-color: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; padding: 11px 38px 11px 13px; color: var(--text);
    font-size: 14.5px; font-family: inherit; cursor: pointer;
    -webkit-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%238b98a8' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 14px center;
  }
  .field-row select:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
  .field-row select option { background: var(--panel); color: var(--text); }
  .field-hint { font-size: 12px; color: var(--dim); margin: 5px 0 0; }

  .form-err {
    background: rgba(242,85,90,.09); border: 1px solid rgba(242,85,90,.28);
    color: var(--danger); border-radius: 9px; padding: 10px 13px;
    font-size: 13px; margin-bottom: 12px;
  }
  .form-ok {
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.28);
    color: var(--accent); border-radius: 9px; padding: 10px 13px;
    font-size: 13px; margin-bottom: 12px;
  }
  .switch-line { margin: 14px 0 0; font-size: 13.5px; color: var(--muted); text-align: center; }
  .switch-line button {
    background: none; color: var(--accent); padding: 0; font-size: 13.5px; font-weight: 660;
  }
  .switch-line button:hover { text-decoration: underline; filter: none; }

  /* points */
  .pts-big {
    font-size: 46px; font-weight: 820; letter-spacing: -.035em; color: var(--accent);
    font-variant-numeric: tabular-nums; line-height: 1;
  }
  .pts-goal { font-size: 13px; color: var(--muted); margin-top: 6px; }
  .pts-bar { height: 8px; border-radius: 5px; background: var(--bg-soft); overflow: hidden; margin-top: 12px; }
  .pts-bar i { display: block; height: 100%; background: var(--accent); border-radius: 5px; transition: width .8s cubic-bezier(.4,0,.2,1); }

  .ledger { display: grid; gap: 7px; margin-top: 16px; }
  .ledger div {
    display: flex; align-items: center; gap: 10px; font-size: 13px;
    padding-top: 7px; border-top: 1px solid var(--line);
  }
  .ledger .d { color: var(--accent); font-weight: 720; flex: none; }
  .ledger .w { margin-left: auto; color: var(--dim); font-size: 11.5px; flex: none; }

  /* discord */
  .dc-row { display: flex; align-items: center; gap: 12px; }
  .dc-av { width: 42px; height: 42px; border-radius: 50%; flex: none; background: var(--bg-soft); }
  .dc-name { font-weight: 680; font-size: 14.5px; }
  .btn.discord { background: #5865f2; color: #fff; }
  .badge-member {
    display: inline-block; margin-top: 4px; font-size: 11px; font-weight: 700;
    color: var(--accent); background: var(--accent-glow);
    border: 1px solid rgba(61,220,132,.28); border-radius: 999px; padding: 3px 9px;
  }
  .badge-guest {
    display: inline-block; margin-top: 4px; font-size: 11px; font-weight: 700;
    color: var(--warn); background: rgba(240,180,41,.1);
    border: 1px solid rgba(240,180,41,.26); border-radius: 999px; padding: 3px 9px;
  }

  /* ---------- member pricing ---------- */
  .price .was {
    color: var(--dim); font-size: 13px; font-weight: 500;
    text-decoration: line-through; margin-right: 3px;
  }
  .member-strip {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    background: var(--panel); border: 1px solid var(--line);
    border-left: 3px solid var(--warn);
    border-radius: 12px; padding: 13px 16px; margin-bottom: 16px;
    font-size: 13.5px; color: var(--muted);
  }
  .member-strip b { color: var(--text); font-weight: 680; }
  .member-strip .btn { margin-left: auto; padding: 8px 15px; font-size: 13px; }
  .member-strip.on { border-left-color: var(--accent); color: var(--accent); }
  .member-strip.on b { color: var(--accent); }

  .credit-toggle {
    margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
    font-size: 13px; font-weight: 620; color: var(--text); cursor: pointer;
  }
  .credit-toggle input { accent-color: var(--accent); width: 15px; height: 15px; }

  /* ---------- rewards prompt ---------- */
  #rewards-prompt {
    background: var(--panel); color: var(--text); border: 1px solid var(--line-hi);
    border-radius: 16px; padding: 0; max-width: 400px; width: calc(100% - 28px);
    box-shadow: var(--shadow);
  }
  #rewards-prompt::backdrop { background: rgba(5,7,10,.78); backdrop-filter: blur(3px); }
  .rp { text-align: center; padding: 26px 24px 24px; }
  .rp-icon {
    width: 54px; height: 54px; margin: 0 auto 14px; border-radius: 15px;
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.3);
    display: grid; place-items: center; font-size: 26px;
  }
  .rp h3 {
    margin: 0 0 9px; font-size: 17px; font-weight: 720;
    line-height: 1.35; letter-spacing: -.01em;
  }
  .rp p { margin: 0 0 20px; color: var(--muted); font-size: 13.5px; line-height: 1.55; }
  .rp-actions { display: grid; gap: 8px; }
  .rp-actions .btn, .rp-actions button { width: 100%; }

  /* The same card as the rewards prompt, for a problem starting an order. */
  #notice { max-width: 400px; }
  .notice-icon { background: rgba(240,180,41,.12); border-color: rgba(240,180,41,.34); }

  /* ---------- checkout on the office computer ----------
     The Warehouse page's twin of the machine checkout: the payment window is a
     small copy of the terminal — dark monitor casing with its badge and power
     light, black bezel, the light screen, and browser chrome across the top.
     All drawn with pseudo-elements, so the dialogs app.js builds are unchanged. */
  body[data-page="warehouse"] dialog,
  body[data-page="warehouse"] #rewards-prompt,
  body[data-page="warehouse"] #ship-form {
    --bg: #e7edf4;
    --bg-soft: #dee6ef;
    --panel: #f2f6fa;
    --panel-hi: #e8eff6;
    --line: #ccd6e2;
    --line-hi: #b0bccb;
    --text: #16202c;
    --muted: #545f6d;
    --dim: #7f8b99;
    --accent: #0b8f4b;
    --accent-ink: #ffffff;
    --accent-glow: rgba(11,143,75,.11);
    --warn: #9a6100;
    --danger: #b3261e;
    --shadow: 0 6px 20px rgba(16,24,40,.1);

    background: linear-gradient(180deg, #26262c 0%, #17171b 46%, #0e0e11 100%);
    color: var(--text);
    border: 1px solid #34343c; border-radius: 16px;
    padding: 0 12px 30px; max-width: 470px;
    box-shadow: 0 34px 70px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,255,255,.06);
  }
  /* The badge along the top of the casing. */
  body[data-page="warehouse"] dialog::before {
    content: 'PROFIT VENDING'; display: block; text-align: center;
    padding: 10px 0 10px; font-size: 10px; font-weight: 820; letter-spacing: .16em; color: #b9b9c4;
  }
  /* The power light under the screen. */
  body[data-page="warehouse"] dialog::after {
    content: ''; position: absolute; left: 50%; bottom: 11px; transform: translateX(-50%);
    width: 7px; height: 7px; border-radius: 50%;
    background: #3ddc84; box-shadow: 0 0 8px rgba(61,220,132,.8);
  }
  /* The screen, its bezel drawn as an outline. */
  body[data-page="warehouse"] dialog .modal {
    position: relative;
    background: linear-gradient(180deg, #edf2f8 0%, #e1e9f1 100%);
    border-radius: 6px;
    box-shadow: 0 0 0 7px #0a0c10, 0 0 0 8px #31363f;
    margin: 8px 8px 0;
    padding-top: 58px;
  }
  /* Browser chrome: the three window dots… */
  body[data-page="warehouse"] dialog .modal::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 38px;
    border-bottom: 1px solid var(--line); border-radius: 6px 6px 0 0;
    background:
      radial-gradient(circle at 16px 19px, #e0685f 4.5px, transparent 5px),
      radial-gradient(circle at 31px 19px, #e2b23f 4.5px, transparent 5px),
      radial-gradient(circle at 46px 19px, #4fb96a 4.5px, transparent 5px),
      #e6edf4;
  }
  /* …and the address pill beside them. */
  body[data-page="warehouse"] dialog .modal::after {
    content: 'https://profitvending.io/warehouse-checkout';
    position: absolute; top: 7px; left: 62px; right: 10px; height: 24px; box-sizing: border-box;
    padding: 0 12px; line-height: 22px; border-radius: 999px;
    background: var(--bg-soft); border: 1px solid var(--line);
    font: 11.5px/22px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--muted);
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  body[data-page="warehouse"] dialog .copyrow button { background: #fff; }
  body[data-page="warehouse"] dialog .copyrow button.done { background: var(--accent); color: #fff; }
  body[data-page="warehouse"] dialog .rp-icon { border-color: rgba(11,143,75,.28); }
  body[data-page="warehouse"] dialog input, body[data-page="warehouse"] dialog textarea { background: #fff; }

  /* ---------- checkout on the machine ----------
     On /vending and the product pages, the payment window is a small copy of
     the machine itself: white cabinet, black bezel, and the screen's light
     palette, so paying feels like part of the same unit rather than a dark
     pop-up laid over it. The bezel is drawn as an outline on .modal, so the
     markup app.js builds does not change. */
  body[data-page="vending"] dialog,
  body[data-page="product"] dialog,
  body[data-page="vending"] #rewards-prompt,
  body[data-page="product"] #rewards-prompt {
    --bg: #e7edf4;
    --bg-soft: #dee6ef;
    --panel: #f2f6fa;
    --panel-hi: #e8eff6;
    --line: #ccd6e2;
    --line-hi: #b0bccb;
    --text: #16202c;
    --muted: #545f6d;
    --dim: #7f8b99;
    --accent: #0b8f4b;
    --accent-ink: #ffffff;
    --accent-glow: rgba(11,143,75,.11);
    --warn: #9a6100;
    --danger: #b3261e;
    --shadow: 0 6px 20px rgba(16,24,40,.1);

    background: linear-gradient(180deg, #fcfcfd 0%, #eef0f3 40%, #e1e4e9 100%);
    color: var(--text);
    border: 1px solid #d3d7de; border-radius: 22px;
    padding: 0 18px 18px; max-width: 460px;
    box-shadow: 0 34px 70px rgba(0,0,0,.66), inset 0 1px 0 #fff;
  }
  body[data-page="vending"] dialog::before,
  body[data-page="product"] dialog::before {
    content: 'PROFIT VENDING'; display: block; text-align: center;
    padding: 11px 0 12px; font-size: 10.5px; font-weight: 800; letter-spacing: .17em; color: #2b3039;
  }
  body[data-page="vending"] dialog .modal,
  body[data-page="product"] dialog .modal {
    background: linear-gradient(180deg, #edf2f8 0%, #e1e9f1 100%);
    border-radius: 6px;
    box-shadow: 0 0 0 7px #0a0c10, 0 0 0 8px #31363f, 0 3px 10px 8px rgba(0,0,0,.35);
    margin: 8px 8px 0;
  }
  body[data-page="vending"] dialog .copyrow button,
  body[data-page="product"] dialog .copyrow button { background: #fff; }
  body[data-page="vending"] dialog .copyrow button.done,
  body[data-page="product"] dialog .copyrow button.done { background: var(--accent); color: #fff; }
  body[data-page="vending"] dialog .rp-icon,
  body[data-page="product"] dialog .rp-icon { border-color: rgba(11,143,75,.28); }

  /* ---------- admin ---------- */
  .stat-row { display: grid; gap: 8px; grid-template-columns: repeat(2, 1fr); margin-bottom: 16px; }
  @media (min-width: 720px) { .stat-row { grid-template-columns: repeat(5, 1fr); } }
  .stat {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
    padding: 14px 15px; text-align: center;
  }
  .stat b { display: block; font-size: 22px; font-weight: 800; letter-spacing: -.02em; }
  .stat span { font-size: 11px; color: var(--dim); font-weight: 620; letter-spacing: .04em; }

  .admin-items { display: grid; gap: 10px; }
  .aitem-card {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 16px 17px;
  }
  .aitem-head { display: flex; align-items: flex-start; gap: 14px; }
  .aitem-head h4 { margin: 0 0 3px; font-size: 15px; font-weight: 680; }
  .asku {
    font-size: 10.5px; font-weight: 700; color: var(--dim);
    background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 5px; padding: 2px 6px; margin-left: 5px;
  }
  .asub { margin: 0; font-size: 12.5px; color: var(--muted); }
  .astock {
    margin-left: auto; font-size: 22px; font-weight: 820; flex: none;
    font-variant-numeric: tabular-nums;
  }
  .astock.ok { color: var(--accent); }
  .astock.none { color: var(--danger); }

  .adrift {
    margin-top: 10px; background: rgba(240,180,41,.09); border: 1px solid rgba(240,180,41,.26);
    color: var(--warn); border-radius: 8px; padding: 9px 11px; font-size: 12.5px;
  }

  .arow-actions { display: flex; gap: 7px; margin-top: 11px; flex-wrap: wrap; }
  .arow-actions input {
    flex: 1; min-width: 80px; background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 8px; padding: 8px 11px; color: var(--text); font-size: 13.5px; font-family: inherit;
  }
  .arow-actions button { padding: 8px 14px; font-size: 13px; }

  /* Item photo, in the edit form. */
  .a-photo-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
  .a-photo-prev {
    width: 54px; height: 54px; object-fit: contain; background: #fff;
    border: 1px solid var(--line); border-radius: 10px; padding: 4px; flex: none;
  }
  .a-photo-none { font-size: 12.5px; color: var(--dim); }
  .a-photo-row input[type="file"] { font-size: 12.5px; max-width: 210px; }

  /* ON / OFF with its own Save, for the password page. */
  .onoff-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
  .onoff {
    display: inline-flex; padding: 3px; gap: 3px;
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 10px;
  }
  .onoff-btn {
    padding: 7px 18px; border: 0; border-radius: 8px; cursor: pointer;
    background: transparent; color: var(--muted);
    font-size: 12.5px; font-weight: 750; letter-spacing: .04em; font-family: inherit;
  }
  .onoff-btn:hover { color: var(--text); filter: none; }
  .onoff-btn[data-gate="on"][aria-pressed="true"] { background: var(--accent); color: #04180d; }
  .onoff-btn[data-gate="off"][aria-pressed="true"] { background: var(--line-hi); color: var(--text); }

  .acodes { margin-top: 12px; }
  .acodes summary {
    cursor: pointer; font-size: 13px; font-weight: 640; color: var(--muted);
    list-style: none; padding: 6px 0;
  }
  .acodes summary::-webkit-details-marker { display: none; }
  .acodes summary::before { content: '+ '; color: var(--accent); font-weight: 800; }
  .acodes[open] summary::before { content: '− '; }
  .acodes textarea {
    width: 100%; background: var(--bg-soft); border: 1px solid var(--line); border-radius: 9px;
    padding: 11px 12px; color: var(--text); font-family: ui-monospace, Menlo, monospace;
    font-size: 13px; resize: vertical;
  }

  .admin-orders { display: grid; gap: 4px; }
  /* Fixed track widths, not `auto`: every row is its own grid, so `auto`
     columns size to their own content and the columns never line up with
     each other — or with the header. */
  .arow {
    display: grid; grid-template-columns: 104px 1fr 118px 74px 96px;
    gap: 10px; align-items: center;
    background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
    padding: 9px 12px; font-size: 12.5px;
  }
  .arow.ahead {
    background: transparent; border-color: transparent; padding-bottom: 2px;
    font-size: 10.5px; font-weight: 720; letter-spacing: .06em;
    color: var(--dim); text-transform: uppercase;
  }
  .arow.ahead span:nth-child(4), .arow.ahead span:nth-child(5) { text-align: right; }

  @media (max-width: 640px) {
    .arow { grid-template-columns: 96px 1fr 84px; }
    .awho, .aamt,
    .arow.ahead span:nth-child(3), .arow.ahead span:nth-child(4) { display: none; }
  }
  .acode { font-family: ui-monospace, Menlo, monospace; font-weight: 700; color: var(--accent); }
  .aitem { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .awho { color: var(--muted); }
  .aamt { font-weight: 700; font-variant-numeric: tabular-nums; }
  .ast { font-size: 10.5px; font-weight: 700; text-align: right; color: var(--dim); }
  .apay { color: var(--muted); font-size: 12px; }
  .aord-view { padding: 5px 9px; font-size: 11px; white-space: nowrap; }

  /* The row is dense: tighter gaps, and every cell may shrink, so the View
     button stays on screen instead of being pushed off the right edge. */
  .admin-orders .arow { gap: 6px; padding: 9px 10px; }
  .admin-orders .arow > * { min-width: 0; }
  .admin-orders .acode { font-size: 11.5px; }
  .admin-orders .aitem { font-size: 12px; }
  .admin-orders .awho { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* One order in full. */
  .aord-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px 18px; }
  .aord-fact { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .aord-fact span {
    font-size: 10.5px; font-weight: 720; letter-spacing: .06em;
    text-transform: uppercase; color: var(--dim);
  }
  .aord-fact b { font-size: 13.5px; font-weight: 620; word-break: break-word; }
  .aord-mono { font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; }
  .aord-codes {
    margin: 10px 0; padding: 11px 13px; background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; font-family: ui-monospace, Menlo, monospace; font-size: 12.5px;
    white-space: pre-wrap; word-break: break-word;
  }
  .aord-events { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
  .aord-events li { display: flex; flex-wrap: wrap; gap: 8px; font-size: 12.5px; align-items: baseline; }
  .aord-events li span { color: var(--dim); min-width: 74px; }
  .aord-events li i { color: var(--muted); font-style: normal; word-break: break-all; }
  .ast.delivered, .ast.paid { color: var(--accent); }
  .ast.expired, .ast.cancelled { color: var(--danger); }

  /* ---------- admin: sidebar layout ---------- */
  .adm { display: grid; gap: 16px; grid-template-columns: 1fr; align-items: start; }
  @media (min-width: 800px) { .adm { grid-template-columns: 190px 1fr; } }

  .adm-side {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
    padding: 8px; display: flex; flex-direction: column; gap: 4px;
    position: sticky; top: 62px;
  }
  .adm-side nav { display: flex; flex-direction: column; gap: 3px; }
  .adm-side button {
    background: transparent; color: var(--muted); text-align: left;
    padding: 10px 13px; border-radius: 8px; font-size: 13.5px; font-weight: 640;
    justify-content: flex-start;
  }
  .adm-side button:hover { background: var(--panel-hi); color: var(--text); filter: none; }
  .adm-side button[aria-current="page"] {
    background: var(--accent-glow); color: var(--accent);
  }
  .adm-lock { margin-top: 6px; border-top: 1px solid var(--line); border-radius: 0 0 8px 8px; }
  @media (max-width: 799px) {
    .adm-side { position: static; flex-direction: row; flex-wrap: wrap; }
    .adm-side nav { flex-direction: row; flex: 1; }
    .adm-lock { margin-top: 0; border-top: 0; }
  }

  .adm-range { display: flex; gap: 4px; flex: none; }
  .adm-range button {
    background: var(--bg-soft); color: var(--muted); border: 1px solid var(--line);
    padding: 6px 11px; font-size: 11.5px; font-weight: 640; border-radius: 7px;
  }
  .adm-range button[aria-pressed="true"] {
    background: var(--accent-glow); color: var(--accent); border-color: rgba(61,220,132,.34);
  }
  @media (max-width: 560px) { .adm-range { width: 100%; } .adm-range button { flex: 1; } }

  /* ---------- best sellers ----------
     One series of magnitudes, so one hue: colour carries size here, not
     identity, and no legend is needed for a single series. Values are direct-
     labelled and all text stays in text tokens, so nothing depends on colour. */
  .rank { display: grid; gap: 3px; }
  .rank-row {
    display: grid; grid-template-columns: 22px minmax(90px, 1.1fr) 2fr 34px 58px;
    gap: 10px; align-items: center;
    padding: 8px 12px; border-radius: 9px;
    background: var(--panel); border: 1px solid var(--line);
    font-size: 12.5px;
  }
  .rank-row:hover { border-color: var(--line-hi); }
  .rank-n { color: var(--dim); font-weight: 700; font-variant-numeric: tabular-nums; }
  .rank-name { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* A track behind the bar so short bars still read as "small", not "missing". */
  .rank-track { background: var(--bg-soft); border-radius: 4px; height: 9px; overflow: hidden; }
  .rank-track i {
    display: block; height: 100%; background: var(--accent);
    border-radius: 0 4px 4px 0;   /* rounded data-end, square against the baseline */
    transition: width .5s cubic-bezier(.4,0,.2,1);
  }
  .rank-val { font-weight: 800; font-variant-numeric: tabular-nums; text-align: right; }
  .rank-rev { color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; }
  @media (max-width: 640px) {
    .rank-row { grid-template-columns: 20px 1fr 34px; }
    .rank-track, .rank-rev { display: none; }
  }

  /* key/value list in settings */
  .kv { display: grid; gap: 0; margin-top: 6px; }
  .kv div {
    display: flex; align-items: center; gap: 12px;
    padding: 9px 0; border-top: 1px solid var(--line); font-size: 13px;
  }
  .kv span { color: var(--muted); }
  .kv b { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
  .acct-row { grid-template-columns: 1fr 1.4fr 74px 80px 96px; }
  @media (max-width: 640px) { .acct-row { grid-template-columns: 1fr 80px; } }

  /* Stacked figures on an inventory card: label left, value right, so the
     numbers line up down the column and can be compared at a glance. */
  dl.asub { margin: 4px 0 0; display: grid; gap: 3px; }
  dl.asub div { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; }
  dl.asub dt { margin: 0; color: var(--muted); min-width: 96px; }
  dl.asub dd { margin: 0; color: var(--text); font-weight: 640; font-variant-numeric: tabular-nums; }

  /* ---------- add / remove product ---------- */
  .field-row textarea {
    width: 100%; background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; padding: 11px 13px; color: var(--text);
    font-size: 14.5px; font-family: inherit; resize: vertical; line-height: 1.5;
  }
  .field-row textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

  .rm-list { display: grid; gap: 6px; margin-top: 6px; }
  .rm-row {
    display: flex; align-items: center; gap: 12px;
    background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; padding: 10px 13px; font-size: 13.5px;
  }
  .rm-name { color: var(--text); font-weight: 620; }
  .rm-meta { margin-left: auto; color: var(--dim); font-size: 12px; }
  .rm-btn { padding: 7px 14px; font-size: 12.5px; flex: none; }
  .rm-btn:hover { border-color: var(--danger); color: var(--danger); }

  .ping-toggle {
    display: flex; align-items: center; gap: 8px; margin-top: 10px;
    font-size: 13px; font-weight: 620; color: var(--text); cursor: pointer;
  }
  .ping-toggle input { accent-color: var(--accent); width: 15px; height: 15px; }
  .ping-toggle input:disabled { cursor: not-allowed; }
  .ping-toggle:has(input:disabled) { color: var(--dim); cursor: not-allowed; }

  /* ---------- editable settings ---------- */
  .set-list { display: grid; gap: 8px; margin-top: 4px; }
  .set-row {
    display: grid; grid-template-columns: 1fr 120px auto auto; gap: 8px; align-items: center;
    padding-top: 8px; border-top: 1px solid var(--line);
  }
  .set-row label { font-size: 13px; color: var(--muted); }
  .set-input { position: relative; display: flex; align-items: center; }
  .set-pre {
    position: absolute; left: 11px; color: var(--dim); font-size: 13.5px; pointer-events: none;
  }
  .set-row input {
    width: 100%; background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 8px; padding: 8px 11px; color: var(--text);
    font-size: 13.5px; font-family: inherit; font-variant-numeric: tabular-nums;
  }
  .set-input:has(.set-pre) input { padding-left: 22px; }
  .set-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
  .set-row button { padding: 8px 13px; font-size: 12.5px; }
  @media (max-width: 640px) {
    .set-row { grid-template-columns: 1fr 1fr; }
    .set-row label { grid-column: 1 / -1; }
  }

  /* ---------- error log ---------- */
  .err-list { display: grid; gap: 5px; }
  .err-row {
    display: grid; grid-template-columns: 78px 1fr 110px 74px; gap: 10px; align-items: start;
    background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
    padding: 10px 12px; font-size: 12.5px;
  }
  .err-kind {
    font-size: 10px; font-weight: 760; letter-spacing: .05em; text-transform: uppercase;
    padding: 3px 7px; border-radius: 5px; text-align: center;
    background: var(--bg-soft); color: var(--dim); border: 1px solid var(--line);
  }
  /* Kind carries a label as well as a colour, so it never depends on hue alone. */
  .err-kind.k-payment, .err-kind.k-order { color: var(--danger); border-color: rgba(242,85,90,.3); }
  .err-kind.k-webhook, .err-kind.k-discord { color: var(--warn); border-color: rgba(240,180,41,.3); }
  .err-kind.k-stock { color: var(--warn); border-color: rgba(240,180,41,.3); }
  .err-msg { color: var(--text); }
  .err-detail {
    margin-top: 3px; color: var(--dim); font-family: ui-monospace, Menlo, monospace;
    font-size: 11px; white-space: pre-wrap; word-break: break-word;
  }
  .err-ref { color: var(--muted); font-family: ui-monospace, Menlo, monospace; font-size: 11.5px; }
  .err-when { color: var(--dim); text-align: right; font-size: 11.5px; }
  @media (max-width: 640px) {
    .err-row { grid-template-columns: 70px 1fr; }
    .err-ref, .err-when { display: none; }
  }

  .set-switches { display: flex; gap: 18px; flex-wrap: wrap; margin: 4px 0 16px; }
  .set-switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13.5px; }
  .set-switch input { accent-color: var(--accent); width: 16px; height: 16px; }
  .set-state {
    margin-left: 7px; font-size: 10px; font-weight: 720; letter-spacing: .04em;
    padding: 2px 7px; border-radius: 999px; text-transform: uppercase;
  }
  .set-state.on  { color: var(--accent); background: var(--accent-glow); border: 1px solid rgba(61,220,132,.3); }
  .set-state.off { color: var(--dim); background: var(--bg-soft); border: 1px solid var(--line); }
  .set-hr { border: 0; border-top: 1px solid var(--line); margin: 18px 0 16px; }
  .field-hint code {
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 4px;
    padding: 1px 5px; font-size: 11.5px;
  }

  /* The dispenser door on /vending is the way back to the home page. */
  .cabinet-door { display: block; text-decoration: none; }
  .cabinet-door .cabinet-tray {
    display: block; transition: box-shadow .16s;
  }
  .cabinet-tray i {
    display: flex; align-items: center; justify-content: center;
    height: 46px; border-radius: 4px; font-style: normal;
    font-size: 10.5px; font-weight: 800; letter-spacing: .14em; text-indent: .14em;
    color: rgba(61,220,132,.8);
    background: linear-gradient(180deg, #171b21 0%, #0a0d11 100%);
    box-shadow: inset 0 4px 12px rgba(0,0,0,.95);
    transition: transform .16s, color .16s, box-shadow .16s;
  }
  .cabinet-door:hover .cabinet-tray i {
    color: var(--accent); transform: translateY(1px);
    box-shadow: inset 0 6px 16px rgba(0,0,0,.98), 0 0 14px rgba(61,220,132,.22);
  }
  .cabinet-door:active .cabinet-tray i { transform: translateY(2px); }
  .cabinet-door:focus-visible .cabinet-tray { outline: 2px solid var(--accent); outline-offset: 3px; }
  .cabinet-door:hover ~ .cabinet-push,
  .cabinet-push { transition: color .16s; }

  /* ---------- webhook lists ---------- */
  .hook-block { margin-bottom: 18px; }
  .hook-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
  .hook-head b { font-size: 13.5px; }
  .hook-count { font-size: 11.5px; color: var(--dim); }
  .hook-rows { display: grid; gap: 5px; }
  .hook-row {
    display: grid; grid-template-columns: 8px 1fr auto auto; gap: 10px; align-items: center;
    background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 8px; padding: 9px 12px; font-size: 12.5px;
  }
  .hook-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
  .hook-label { color: var(--text); font-weight: 620; }
  .hook-id { color: var(--dim); font-family: ui-monospace, Menlo, monospace; font-size: 11.5px; }
  .hook-x { padding: 5px 11px; font-size: 11.5px; }
  .hook-x:hover { border-color: var(--danger); color: var(--danger); }

  .hook-add { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
  .hook-add input {
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 8px;
    padding: 9px 11px; color: var(--text); font-size: 13px; font-family: inherit;
  }
  .hook-add .hook-url { flex: 3; min-width: 180px; }
  .hook-add .hook-name { flex: 1; min-width: 110px; }
  .hook-add button { flex: none; padding: 9px 14px; font-size: 12.5px; }
  @media (max-width: 640px) {
    .hook-row { grid-template-columns: 8px 1fr auto; }
    .hook-id { display: none; }
    .hook-add input, .hook-add button { flex: 1 1 100%; }
  }

  /* Every save button says so, briefly. */
  button.saved,
  .copyrow button.saved { background: var(--accent) !important; color: #05230f !important; }
  .set-switches #save-pings { margin-left: auto; padding: 8px 16px; font-size: 12.5px; }

  /* ---------- customer accounts ---------- */
  .acct-table { display: grid; gap: 4px; }
  .acct-row {
    display: grid; grid-template-columns: 44px 1.1fr 1.5fr 1.2fr 108px;
    gap: 10px; align-items: center; width: 100%; text-align: left;
    background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
    padding: 11px 13px; font-size: 12.5px; color: var(--text);
    font-family: inherit; font-weight: 400; cursor: pointer;
  }
  button.acct-row:hover { background: var(--panel-hi); border-color: var(--line-hi); filter: none; }
  button.acct-row[aria-expanded="true"] { border-color: var(--accent); }
  .acct-head {
    background: transparent; border-color: transparent; cursor: default;
    padding-bottom: 2px; font-size: 10.5px; font-weight: 720;
    letter-spacing: .06em; text-transform: uppercase; color: var(--dim);
  }
  .acct-n { color: var(--dim); font-variant-numeric: tabular-nums; }
  .acct-name { font-weight: 640; }
  .acct-email, .acct-date { color: var(--muted); }
  .acct-email { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dc-yes { color: var(--text); }
  .dc-no { color: var(--dim); }
  .dc-badge {
    margin-left: 6px; font-size: 9.5px; font-weight: 720; color: var(--accent);
    background: var(--accent-glow); border-radius: 999px; padding: 2px 6px;
  }
  @media (max-width: 720px) {
    .acct-row { grid-template-columns: 36px 1fr 1fr; }
    .acct-email, .acct-date { display: none; }
    .acct-head span:nth-child(3), .acct-head span:nth-child(5) { display: none; }
  }

  .acct-panel { margin-bottom: 14px; border-color: var(--line-hi); }
  .acct-top { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
  .acct-top h3 { margin: 0 0 3px; }
  .acct-top .x { margin-left: auto; }
  .acct-h {
    margin: 20px 0 6px; font-size: 11px; font-weight: 720; letter-spacing: .07em;
    text-transform: uppercase; color: var(--dim);
  }
  .acct-del { border-color: rgba(242,85,90,.35); color: var(--danger); }
  .acct-del:hover { background: rgba(242,85,90,.09); border-color: var(--danger); }

  /* ---------- shipping ---------- */
  .ad-grid { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 8px; }
  @media (max-width: 480px) { .ad-grid { grid-template-columns: 1fr 1fr; } }
  #ship-form {
    background: var(--panel); color: var(--text); border: 1px solid var(--line-hi);
    border-radius: 16px; padding: 0; max-width: 440px; width: calc(100% - 28px);
    box-shadow: var(--shadow);
  }
  #ship-form::backdrop { background: rgba(5,7,10,.76); backdrop-filter: blur(3px); }

  /* ---------- One Time Code (support page) ---------- */
  .otp-card {
    display: flex; align-items: center; gap: 18px; padding: 20px 22px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
  }
  .otp-card h4 { margin: 0 0 6px; font-size: 16px; }
  .otp-card p { margin: 0; color: var(--dim); font-size: 14px; line-height: 1.5; }
  .otp-card #otp-open { flex: none; white-space: nowrap; }
  @media (max-width: 640px) {
    .otp-card { flex-direction: column; align-items: stretch; }
  }
  #otp-form {
    background: var(--panel); color: var(--text); border: 1px solid var(--line-hi);
    border-radius: 16px; padding: 0; max-width: 440px; width: calc(100% - 28px);
    box-shadow: var(--shadow);
  }
  #otp-form::backdrop { background: rgba(5,7,10,.76); backdrop-filter: blur(3px); }
  .otp-code {
    font: 750 34px/1.1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: .14em; text-align: center; padding: 18px 12px; margin: 4px 0 10px;
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.3); border-radius: 12px;
    user-select: all;
  }

  /* Progress, not a receipt — a parcel is not finished when it is paid. */
  .ship-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
  .ship-steps li {
    position: relative; padding: 0 0 18px 26px; font-size: 13.5px; color: var(--dim);
  }
  .ship-steps li:last-child { padding-bottom: 0; }
  .ship-steps .dot {
    position: absolute; left: 0; top: 3px; width: 11px; height: 11px; border-radius: 50%;
    background: var(--bg-soft); border: 2px solid var(--line-hi);
  }
  /* The connecting line stops at the last step so it does not dangle. */
  .ship-steps li:not(:last-child)::before {
    content: ''; position: absolute; left: 5px; top: 16px; bottom: 2px;
    width: 2px; background: var(--line);
  }
  .ship-steps li.done { color: var(--text); font-weight: 620; }
  .ship-steps li.done .dot { background: var(--accent); border-color: var(--accent); }
  .ship-steps li.done:not(:last-child)::before { background: var(--accent); }

  /* ---------- shipping queue ---------- */
  .ship-list { display: grid; gap: 10px; }
  .ship-card {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 16px 17px;
  }
  .ship-top { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
  .ship-top h4 { margin: 0 0 3px; font-size: 15px; font-weight: 680; }
  .ship-state {
    margin-left: auto; flex: none; font-size: 10.5px; font-weight: 720;
    letter-spacing: .05em; text-transform: uppercase; padding: 4px 9px; border-radius: 999px;
    background: var(--bg-soft); border: 1px solid var(--line); color: var(--dim);
  }
  .ship-state.s-paid { color: var(--warn); border-color: rgba(240,180,41,.3); }
  .ship-state.s-packed { color: var(--text); }
  .ship-state.s-shipped, .ship-state.s-delivered { color: var(--accent); border-color: rgba(61,220,132,.3); }

  .ship-addr {
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 9px;
    padding: 12px 14px; margin-bottom: 11px;
  }
  .ship-to { font-weight: 680; font-size: 13.5px; margin-bottom: 3px; }
  .ship-addr pre {
    margin: 0; font-family: ui-monospace, Menlo, monospace; font-size: 12.5px;
    color: var(--muted); white-space: pre-wrap; line-height: 1.5;
  }
  .ship-meta { font-size: 12px; color: var(--dim); margin-top: 5px; }
  .ship-note { font-size: 12.5px; color: var(--warn); margin-top: 6px; font-style: italic; }
  .ship-copy { margin-top: 9px; padding: 6px 12px; font-size: 11.5px; }

  .ship-track {
    display: flex; align-items: center; gap: 10px; margin-bottom: 11px;
    font-size: 12.5px; color: var(--muted);
  }
  .ship-track b { color: var(--accent); font-family: ui-monospace, Menlo, monospace; }

  /* ---------- warehouse ----------
     A ground-level view of the yard: two gable units with open loading bays,
     a box truck, a forklift and pallets of stock, in the site's own palette.
     Generated by tools/warehouse.mjs, which authors the scene in world
     coordinates and projects it — edit that and re-run it rather than nudging
     numbers in the markup. */
  /* The yard sits in the right-hand column. It carries more detail than a
     phone or a machine, so this section runs a wider column than the others. */
  .whx { display: block; width: 100%; height: auto; border-radius: 14px; }
  /* The picture and its button, centred against the text beside it, which runs
     much taller than the picture. */
  .split.wide > .wh-col { align-self: center; display: grid; gap: 12px; }
  .wh-browse { width: 100%; }
  @media (min-width: 900px) { .split.wide { grid-template-columns: 1fr 430px; } }

  /* ---------- account tabs ---------- */
  .tabs { display: flex; gap: 4px; margin-bottom: 10px; }
  .tabs button {
    flex: 1; background: var(--panel); color: var(--muted);
    border: 1px solid var(--line); border-bottom: 0;
    border-radius: 10px 10px 0 0; padding: 11px 8px;
    font-size: 13px; font-weight: 640;
  }
  .tabs button:hover { color: var(--text); filter: none; }
  .tabs button[aria-selected="true"] {
    background: var(--panel); color: var(--accent);
    border-color: var(--line-hi); box-shadow: inset 0 2px 0 var(--accent);
  }
  .tab-panel { margin-top: -10px; border-top-left-radius: 0; border-top-right-radius: 0; }
  @media (max-width: 480px) { .tabs button { font-size: 12px; padding: 10px 4px; } }

  /* orders */
  .ord-list { display: grid; gap: 6px; margin-top: 14px; }
  .ord-row {
    display: grid; grid-template-columns: 1fr auto 86px 56px; gap: 10px; align-items: center;
    background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; padding: 11px 13px; font-size: 13px;
  }
  .ord-item { font-weight: 620; }
  .ord-meta { font-size: 11.5px; color: var(--dim); margin-top: 2px; }
  .ord-amt { font-weight: 700; font-variant-numeric: tabular-nums; }
  .ord-view {
    text-align: center; text-decoration: none; font-size: 12px; font-weight: 640;
    color: var(--muted); border: 1px solid var(--line-hi); border-radius: 7px; padding: 6px 0;
  }
  .ord-view:hover { color: var(--text); background: var(--panel-hi); }
  @media (max-width: 560px) {
    .ord-row { grid-template-columns: 1fr auto; }
    .ord-amt, .ord-view { display: none; }
  }

  /* tickets */
  .tk-list { display: grid; gap: 5px; margin: 14px 0 0; }
  .tk-row {
    display: grid; grid-template-columns: 78px 1fr auto; gap: 10px; align-items: center;
    width: 100%; text-align: left; background: var(--bg-soft);
    border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px;
    font-size: 13px; color: var(--text); font-family: inherit; font-weight: 400; cursor: pointer;
  }
  .tk-row:hover { border-color: var(--line-hi); background: var(--panel-hi); filter: none; }
  .tk-status {
    font-size: 10px; font-weight: 760; letter-spacing: .05em; text-transform: uppercase;
    padding: 3px 7px; border-radius: 999px; text-align: center;
    background: var(--bg-soft); border: 1px solid var(--line); color: var(--dim);
  }
  .tk-status.s-open { color: var(--warn); border-color: rgba(240,180,41,.3); }
  .tk-status.s-answered { color: var(--accent); border-color: rgba(61,220,132,.3); }
  .tk-subject { font-weight: 620; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tk-when { color: var(--dim); font-size: 11.5px; }

  .tk-thread { display: grid; gap: 9px; margin: 16px 0; }
  .tk-msg { border-radius: 10px; padding: 11px 13px; font-size: 13.5px; line-height: 1.5; }
  /* Two sides, so a thread reads as a conversation rather than a log. */
  .tk-msg.you { background: var(--bg-soft); border: 1px solid var(--line); }
  .tk-msg.them {
    background: var(--accent-glow); border: 1px solid rgba(61,220,132,.26);
  }
  .tk-who { font-size: 11px; font-weight: 700; color: var(--dim); margin-bottom: 4px; }
  .tk-msg.them .tk-who { color: var(--accent); }
  .tk-body { white-space: pre-wrap; word-break: break-word; }
  .ast.shipped, .ast.packed, .ast.packing { color: var(--warn); }
  .ast.unpaid, .ast.pending { color: var(--muted); }
  .tk-who-l { display: block; font-weight: 400; font-size: 11.5px; color: var(--dim); margin-top: 2px; }
  .adm-tk { grid-template-columns: 88px 1fr auto; align-items: start; }
  .adm-tk .tk-status, .adm-tk .tk-when { margin-top: 1px; }

  /* ---------- /warehouse as the office terminal ----------
     A black monitor, stand and keyboard around the same .display panel the
     vending machine uses, so the shop inside is one set of components either
     way. Only the stock list lives on the front screen; shipping and help are
     panes behind the buttons along the bottom, which is what keeps the whole
     terminal about a screen tall instead of a long scroll. */
  .desktop { position: relative; }

  .monitor {
    position: relative;          /* the power LED hangs off this, not .desktop */
    background: linear-gradient(180deg, #26262c 0%, #17171b 46%, #0e0e11 100%);
    border: 1px solid #34343c;
    border-radius: 16px;
    padding: 10px 10px 26px;
    box-shadow: 0 22px 50px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.06);
  }
  .mon-brand {
    display: flex; align-items: center; justify-content: center; gap: 7px;
    padding: 5px 0 9px;
  }
  .mon-brand span {
    font-size: 10px; font-weight: 820; letter-spacing: .16em; color: #b9b9c4;
  }
  .mon-led {
    position: absolute; left: 50%; bottom: 9px; transform: translateX(-50%);
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--accent); box-shadow: 0 0 8px rgba(61,220,132,.8);
  }

  /* Window chrome is what makes the panel read as a computer rather than the
     machine's touchscreen — same surface, different device. */
  .win-bar {
    display: flex; align-items: center; gap: 6px;
    margin: -8px -6px 16px; padding: 7px 10px;
    border-bottom: 1px solid var(--line);
  }
  .win-bar > i { width: 9px; height: 9px; border-radius: 50%; background: var(--line-hi); }
  .win-bar > i.d1 { background: #e0685f; }
  .win-bar > i.d2 { background: #e2b23f; }
  .win-bar > i.d3 { background: #4fb96a; }
  /* The panes are real addresses, so the chrome shows the real address. */
  .win-url {
    flex: 1; min-width: 0; margin-left: 6px; padding: 7px 12px;
    background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px;
    font-size: 12px; color: var(--muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* The buttons along the bottom are real controls, not decoration. */
  .display-osd button {
    background: none; border: 0; padding: 4px 6px; border-radius: 8px;
    font-family: inherit; text-align: center; cursor: pointer;
    font-size: 9px; font-weight: 700; color: var(--dim); letter-spacing: .06em;
  }
  .display-osd button:hover { background: var(--panel-hi); color: var(--text); filter: none; }
  .display-osd button[aria-current="true"] { color: var(--accent); background: var(--accent-glow); }
  .display-osd button b { display: block; font-size: 15px; font-weight: 400; margin-bottom: 2px; }

  .mon-neck {
    width: 92px; height: 38px; margin: 0 auto;
    background: linear-gradient(180deg, #26262c, #131317);
    border-left: 1px solid #34343c; border-right: 1px solid #0a0a0d;
  }
  .mon-base {
    width: 260px; height: 14px; margin: 0 auto 24px;
    border-radius: 0 0 10px 10px;
    background: linear-gradient(180deg, #26262c, #0e0e11);
    box-shadow: 0 14px 26px rgba(0,0,0,.55);
  }

  .kbd {
    display: block; max-width: 660px; margin: 0 auto; padding: 16px 18px 18px;
    background: linear-gradient(180deg, #24242a, #131317);
    border: 1px solid #34343c; border-radius: 14px; text-decoration: none;
    box-shadow: 0 14px 30px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.05);
  }
  .kbd:hover { filter: brightness(1.15); }
  .kbd-row { display: flex; gap: 6px; margin-bottom: 6px; }
  .kbd-row i, .kbd-bottom i {
    flex: 1; height: 22px; border-radius: 4px;
    background: linear-gradient(180deg, #3a3a43, #24242b);
    box-shadow: 0 1px 0 #0c0c0f, inset 0 1px 0 rgba(255,255,255,.06);
  }
  .kbd-row i.w { flex: 1.6; }
  .kbd-row i.w2 { flex: 2.2; }
  .kbd-bottom { display: flex; gap: 6px; align-items: center; }
  .kbd-bottom i.w { flex: 1.4; }
  .kbd-space {
    flex: 6; display: block; padding: 6px 0; text-align: center; border-radius: 4px;
    background: linear-gradient(180deg, #3a3a43, #24242b);
    box-shadow: 0 1px 0 #0c0c0f, inset 0 1px 0 rgba(255,255,255,.06);
  }
  .kbd-space i {
    font-style: normal; font-size: 9.5px; font-weight: 800;
    letter-spacing: .14em; color: #cfcfd8;
  }
  @media (max-width: 560px) {
    .mon-neck { height: 26px; } .mon-base { width: 190px; margin-bottom: 16px; }
    .kbd { padding: 10px 11px 12px; }
    .kbd-row i, .kbd-bottom i, .kbd-space { height: 14px; }
    .kbd-space { padding: 3px 0; }
    .kbd-space i { font-size: 7.5px; letter-spacing: .08em; }
  }

  /* Arrival: the terminal settles out of the flight through the door. */
  @keyframes desk-land { from { transform: scale(1.09); opacity: 0 } to { transform: scale(1); opacity: 1 } }
  .desktop { animation: desk-land .46s cubic-bezier(.2,.8,.3,1) both; }

  /* ---------- flying into the office ----------
     Browse Products rolls the office bay's shutter up, then scales the yard with
     the terminal inside as the origin, so you go through the opening rather
     than at it. Deliberately unhurried: the shutter has to visibly travel
     before the camera starts moving, or the reveal is lost. */
  /* The shutter is clipped to its own opening in the SVG, so translating it
     up rolls it away into the housing — slats travelling, not squashing. */
  #wh-shutter, #wh-drum { transform-box: fill-box; transform-origin: top center; }
  #wh-drum { transform: scaleY(0); }

  /* A roller door: a small jolt down as the motor takes the weight, then the
     slats climb into the housing while the coil above them thickens. */
  .wh-open #wh-shutter { animation: wh-roll 1.1s cubic-bezier(.5, 0, .25, 1) forwards; }
  .wh-open #wh-drum    { animation: wh-coil 1.1s cubic-bezier(.5, 0, .25, 1) forwards; }
  @keyframes wh-roll {
    0%   { transform: translateY(0); }
    9%   { transform: translateY(1.2%); }
    100% { transform: translateY(-100%); }
  }
  @keyframes wh-coil {
    0%, 9% { transform: scaleY(0); }
    100%   { transform: scaleY(1); }
  }

  /* No CSS transform here on purpose. Scaling the element would scale a
     bitmap of it, which is what made the flight blurry; app.js moves the
     SVG's viewBox instead, so every frame is drawn fresh at full sharpness. */
  .wh-flying { z-index: 200; border-radius: 0; }

  @media (prefers-reduced-motion: reduce) {
    .desktop { animation: none; }
    .wh-open #wh-shutter, .wh-open #wh-drum { animation-duration: 1ms; }
  }

  /* ---------- the success box ----------
     Each success is a packing slip standing in an opened carton: flaps folded
     back, front panel laid over the slip's foot so the paper reads as being IN
     the box. The deck swipes sideways on the machine's own five-second beat. */
  .collage { margin: 4px 0 28px; }
  .vbox {
    --card: #b98f5e; --card-lit: #d0a878; --card-dark: #8d6a41;
    position: relative; max-width: 560px; margin: 0 auto;
    padding-top: 8px;
  }

  /* The window the slips stand in. */
  .vbox-stage { position: relative; z-index: 1; overflow: hidden; border-radius: 8px 8px 0 0; }
  .vbox-track { display: flex; transition: transform .55s cubic-bezier(.35,0,.2,1); }

  @keyframes slip-up { from { transform: translateY(26px); opacity: .4 } to { transform: none; opacity: 1 } }
  .slip {
    flex: 0 0 100%; min-width: 100%;
    background: linear-gradient(180deg, #f7f5ef, #e9e6dd);
    color: #1e2530; border-radius: 4px 4px 0 0;
    padding: 13px 16px 44px; box-shadow: 0 -6px 18px rgba(0,0,0,.35);
  }
  .slip.up { animation: slip-up .5s cubic-bezier(.2,.8,.3,1) both; }

  .slip-head { display: flex; align-items: center; gap: 8px; }
  .slip-mark { border-radius: 50%; background: #fff; }
  .slip-title { font-size: 11px; font-weight: 820; letter-spacing: .13em; text-transform: uppercase; }
  .slip-no { margin-left: auto; font-size: 10.5px; font-weight: 700; color: #7a8494;
             font-family: ui-monospace, Menlo, Consolas, monospace; }
  .slip-tear {
    height: 2px; margin: 9px -16px 11px;
    background: repeating-linear-gradient(90deg, #b9c0cb 0 6px, transparent 6px 12px);
  }

  /* The photo is the proof, so it leads: full width across the slip, big, with
     the name, stars and words underneath it. */
  .slip-body { display: flex; flex-direction: column; gap: 12px; min-height: 96px; }
  .slip-photo {
    display: block; width: 100%; height: 320px; object-fit: contain; box-sizing: border-box;
    border-radius: 4px; background: #dcd9d1;
    border: 1px solid #cfccc4; padding: 4px;
  }
  .slip-nophoto {
    display: grid; place-items: center;
    background: radial-gradient(circle at 50% 45%, #efece4, #dcd9d1);
  }
  .slip-nophoto img { width: 132px; height: 132px; border-radius: 50%; background: #fff; opacity: .55; }
  .slip-text { flex: 1; min-width: 0; }
  .slip-who { display: flex; align-items: center; gap: 7px; margin-bottom: 3px; }
  .slip-av {
    width: 22px; height: 22px; border-radius: 50%; flex: 0 0 auto;
    background: #dfdcd4; border: 1px solid #c9c6be;
  }
  .slip-initial { display: grid; place-items: center; font-size: 11px; font-weight: 800; color: #6a7382; }
  .slip-name { font-size: 13.5px; font-weight: 760; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .slip-chip {
    margin-left: auto; flex: 0 0 auto; font-size: 9.5px; font-weight: 800;
    letter-spacing: .04em; padding: 3px 8px; border-radius: 999px;
  }
  .slip-chip { color: #0b6c3c; background: rgba(11,143,75,.13); }
  .slip-msg { margin: 5px 0 0; font-size: 13.5px; line-height: 1.5; color: #47505f; }

  .slip-foot { display: flex; align-items: flex-end; gap: 10px; margin-top: 12px; }
  .slip-bars {
    flex: 0 0 auto; width: 132px; height: 22px;
    background: repeating-linear-gradient(90deg,
      #2a3140 0 2px, transparent 2px 4px, #2a3140 4px 5px, transparent 5px 9px,
      #2a3140 9px 12px, transparent 12px 14px);
    opacity: .8;
  }
  .slip-when { margin-left: auto; font-size: 11px; color: #7a8494; white-space: nowrap; }

  /* The carton front, laid over the foot of the slip. */
  .vbox-carton { position: relative; z-index: 2; }

  /* Flaps at the carton's mouth, splayed outward with the slip rising between
     them. Behind the slip they were simply invisible — an opaque sheet of
     paper covers anything sharing its box. */
  .vbox-flap {
    position: absolute; top: -26px; width: 43%; height: 34px; z-index: 3;
    background: linear-gradient(180deg, var(--card-lit), var(--card));
    border: 1px solid var(--card-dark);
    box-shadow: 0 -5px 12px rgba(0,0,0,.3);
  }
  .vbox-flap.l {
    left: -3%; transform-origin: bottom right;
    transform: rotate(-6deg) skewX(-11deg); border-radius: 7px 2px 0 0;
  }
  .vbox-flap.r {
    right: -3%; transform-origin: bottom left;
    transform: rotate(6deg) skewX(11deg); border-radius: 2px 7px 0 0;
  }
  .vbox-inner {
    display: block; height: 9px;
    background: linear-gradient(180deg, #3a2c1b, var(--card-dark));
  }
  .vbox-face {
    display: flex; align-items: center; gap: 11px;
    padding: 15px 18px 17px;
    background: linear-gradient(180deg, var(--card), var(--card-dark));
    border-radius: 0 0 10px 10px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 14px 28px rgba(0,0,0,.5);
  }
  .vbox-face img { border-radius: 50%; background: #fff; flex: 0 0 auto; }
  .vbox-face b { font-size: 12.5px; font-weight: 820; letter-spacing: .12em; color: #3b2b19; }
  .vbox-face i {
    margin-left: auto; font-style: normal; font-size: 9.5px; font-weight: 700;
    letter-spacing: .1em; color: rgba(59,43,25,.62);
  }

  .vbox-dots { display: flex; justify-content: center; gap: 6px; margin-top: 14px; }
  .vbox-dots i {
    width: 7px; height: 7px; border-radius: 50%; background: var(--line-hi);
    cursor: pointer; transition: background .2s, transform .2s;
  }
  .vbox-dots i.on { background: var(--accent); transform: scale(1.25); }

  @media (max-width: 520px) {
    .slip-photo { height: 230px; }
    .vbox-face i { display: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .vbox-track { transition: none; }
    .slip.up { animation: none; }
  }

  /* ---------- post a success ---------- */
  .rate { display: flex; gap: 4px; }
  .rate button {
    background: none; border: 0; padding: 2px 4px; font-size: 26px; line-height: 1;
    color: var(--line-hi); cursor: pointer;
  }
  .rate button[aria-pressed="true"] { color: var(--warn); }
  .rate button:hover { filter: none; color: var(--warn); }

  .field-row input[type="file"] {
    width: 100%; background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 9px; padding: 9px 11px; color: var(--muted); font-size: 13px;
  }
  .sx-thumb {
    display: block; margin-top: 9px; max-height: 140px; border-radius: 9px;
    border: 1px solid var(--line);
  }
  .sx-list { display: grid; gap: 8px; margin-top: 12px; }
  .sx-row {
    display: grid; grid-template-columns: 62px 1fr; gap: 11px; align-items: start;
    background: var(--bg-soft); border: 1px solid var(--line);
    border-radius: 10px; padding: 10px;
  }
  .sx-row img, .sx-nophoto {
    width: 62px; height: 62px; border-radius: 7px; object-fit: cover;
    background: var(--panel-hi); display: block;
  }
  .sx-row p { margin: 4px 0 5px; font-size: 13px; color: var(--muted); line-height: 1.45; }

/* ================= phones =================
   Everything here is for small screens. A desktop is unaffected: the only
   rules outside a media query just stop grid columns growing wider than the
   screen, which a desktop-width layout never reaches. */

/* A grid column can otherwise grow to fit its widest content — the vending
   machine's sliding banner on the home page, the tables in the admin panel —
   and push the whole page wider than the phone, which then zooms out. */
.split > *, .split.wide > *, .adm > * { min-width: 0; }
.vm { max-width: 100%; }
/* The vending cabinet and the office computer land with a slight zoom (they start
   about 9% larger). On a phone the browser sizes the page while that is still
   oversized and keeps the wider size, zooming everything out a touch. clip, not
   hidden: it trims the overflow without making a scroll box, so nothing sticky
   or scrolling inside is affected. */
@media (max-width: 640px) { .stage { overflow-x: clip; } }

@media (max-width: 640px) {
  /* Top bar: logo and "Profit Vending" on the left; account (plus the bell,
     signed in) and a menu button on the right. The page links open as a
     column underneath when the menu button is tapped. */
  .nav-in {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "brand right menu" "items items items";
    row-gap: 0; column-gap: 4px; padding-top: 6px; padding-bottom: 6px;
  }
  .nav-brand { grid-area: brand; }
  .nav-brand span { display: inline; font-size: 15px; }
  .nav-right { grid-area: right; }
  .nav-menu-btn { display: grid; grid-area: menu; }
  .nav-items {
    grid-area: items; display: none; flex-direction: column; flex-wrap: nowrap;
    gap: 2px; padding: 8px 0 4px; margin-top: 6px; border-top: 1px solid var(--line);
  }
  .nav.menu-open .nav-items { display: flex; }
  .nav-items a { white-space: nowrap; font-size: 15px; padding: 12px 14px; border-radius: 10px; }
  .nav-welcome { display: none; }

  /* Things a thumb has to hit: at least 40px. */
  .nav-brand { min-height: 40px; min-width: 40px; }
  .x { min-width: 40px; min-height: 40px; display: grid; place-items: center; margin: -9px -9px -9px 0; }
  .switch-line button { padding: 10px 8px; }

  /* Admin tables with fixed columns scroll sideways inside their own box
     instead of stretching the page. */
  .admin-orders { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .admin-orders .arow[style] { min-width: 560px; }
  .adm-range { flex-wrap: wrap; }
}

@media (max-width: 799px) {
  /* Admin sections as one row you swipe along, rather than wrapped buttons. */
  .adm-side { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .adm-side::-webkit-scrollbar { display: none; }
  .adm-side nav { flex-wrap: nowrap; flex: none; }
  .adm-side button { white-space: nowrap; flex: none; }
  .adm-lock { flex: none; }
}

@media (max-width: 560px) {
  /* The Warehouse keyboard's space bar is a real link: keep its label readable. */
  .kbd-space { height: auto; min-height: 20px; }
  .kbd-space i { font-size: 10px; letter-spacing: .06em; }
}
