/* ═══════════════════════════════════════════════════════════════════════
   RYVO DESIGN SYSTEM
   The single source for the site and the Control Centre. Both surfaces run
   off this file so they cannot drift apart — a slick site bolted to a
   different-looking admin reads as two companies.

   The language, settled 19 Aug 2026 after three cuts:

   1. SOFT GEOMETRY. Capsules for anything interactive, 22–28px on panels.
      Committed to rather than sprinkled — half-rounded is worse than either.
   2. DEPTH FROM LIGHT. Panels lift with an inner top highlight and a long
      soft shadow; the page carries ambient violet and teal blooms. Borders
      are barely there and never do the structural work.
   3. GRAPHICS THAT MEAN SOMETHING. Gradient areas with real bezier
      smoothing, donut gauges, capped bars. No chart is decoration.
   4. MOTION IS PART OF IT. Everything that changes state eases rather than
      snaps, on one curve and two durations.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── ground ──────────────────────────────────────────────────────── */
  --bg:      #070911;
  --bg-2:    #0B0E1A;
  --panel:   rgba(255,255,255,.055);
  --panel-2: rgba(255,255,255,.018);

  /* ── ink ─────────────────────────────────────────────────────────── */
  --ink:  #F4F6FD;
  --ink2: #A9B2CC;
  --ink3: #6C7695;
  --ink4: #4A5470;

  /* ── the mark ─────────────────────────────────────────────────────
     Violet leads, teal is the second note. Straight from favicon.svg —
     never Sky blue, and never gold. */
  --violet:  #8B7CFF;
  --violet2: #A996FF;
  --teal:    #37E5C9;
  --teal2:   #2BC9B0;
  --amber:   #FFC14D;
  --rose:    #FF6B87;

  --line:  rgba(255,255,255,.06);
  --line2: rgba(255,255,255,.11);

  /* ── radii: capsule or generous, nothing between ─────────────────── */
  --r-pill: 999px;
  --r-lg:   28px;
  --r-md:   22px;
  --r-sm:   14px;

  /* ── elevation: one recipe ───────────────────────────────────────── */
  --lift:   0 24px 60px -34px rgba(0,0,0,.9), inset 0 1px 0 rgba(255,255,255,.07);
  --lift-2: 0 50px 110px -50px rgba(0,0,0,.95), inset 0 1px 0 rgba(255,255,255,.09);
  --glow-v: 0 18px 40px -18px rgba(139,124,255,.95);

  /* ── motion: one curve, two speeds ───────────────────────────────── */
  --ease: cubic-bezier(.22,.7,.24,1);
  --fast: .2s;
  --slow: .42s;

  --edge: clamp(20px, 5vw, 72px);
  --maxw: 1360px;
  --maxw-wide: min(2200px, 95vw);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body { overflow-x: clip; }  /* a decorative glow wider than the viewport
                                     let the whole page be dragged sideways on a
                                     phone; clip, not hidden, so the sticky
                                     header still sticks */

[hidden] { display: none !important; }  /* .gate/.shell set display: on a class,
                                           which outranks the UA [hidden] rule */

img, svg, video { max-width: 100%; }
img { height: auto; }  /* a width:100% image with a height="900" attribute and no height:auto
                          keeps 900px as its used height — every screenshot on the site was
                          squashed into a portrait box until this line existed */

body {
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, -apple-system, system-ui, sans-serif;
  font-size: 15px; line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  background-image:
    radial-gradient(1200px 700px at 82% -10%, rgba(139,124,255,.17), transparent 60%),
    radial-gradient(900px 600px at -5% 42%, rgba(55,229,201,.075), transparent 60%);
  background-attachment: fixed;
}

/* Outfit is display only. A display face set as body copy is the fastest
   way to look amateur. */
/* 1.2, and the number is measured rather than guessed.

   Was 1.03, which cut roughly 2px off the bottom of every display heading —
   invisible on a heading in open space, obvious the moment one sits in a panel
   that hides its overflow. A first pass at 1.12 was still not enough: reading
   scrollHeight against font-size on the live pages, Outfit's ink box runs to
   **1.168 at 63px and 1.185 at 27px** — it needs proportionally MORE at small
   sizes, which is why the big marketing headings looked fine while a 27px
   panel heading ("Ryvo free trial" on pricing) still lost its descender.

   1.2 clears the worst measured case with a little headroom. A heading has to
   fit its own letters whatever it is sitting in. */
.dsp { font-family: Outfit, sans-serif; font-weight: 700; letter-spacing: -.04em; line-height: 1.2; }
.d1 { font-size: clamp(40px, 4.4vw, 66px); }
.d2 { font-size: clamp(30px, 3.4vw, 50px); }
.d3 { font-size: clamp(21px, 1.9vw, 27px); letter-spacing: -.03em; }
.grad { background: linear-gradient(120deg, var(--violet2), var(--teal));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.num { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }
.muted { color: var(--ink2); }
.dim   { color: var(--ink3); }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--edge); }
/* Imagery and grids get the screen; paragraphs keep their reading width. */
.wrap.wide { max-width: var(--maxw-wide); }

/* ── pills ─────────────────────────────────────────────────────────── */
/* min-height, NOT height.

   A fixed 32px is a toolbar chip size, and it clipped its own text the moment
   a label wrapped: "1 opened the account page" on the Visitors tile spilled
   straight out of the bottom of its own rounded box. It only showed between
   about 700px and 1100px — narrow enough for the tile to be tight, wide enough
   that the phone rules (which already set height:auto) had not taken over. A
   shrunk desktop window lands exactly in that gap.

   box-sizing is border-box globally, so a single-line pill is still exactly
   32px and nothing anywhere else moves. max-width and overflow-wrap are the
   belt and braces: a long unbroken string now wraps inside the pill rather
   than running out through the side of it. */
.pill {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 32px; padding: 5px 16px; border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 500; line-height: 1.35;
  /* break-word, NOT anywhere. `anywhere` splits a word at any character AND
     lowers the element's intrinsic minimum width, so a squeezed table column
     could shrink below the width of the word inside it: the Status pill in the
     licences table came out as "Activ / e" on two lines at around 900px.
     `break-word` breaks only a word that genuinely cannot fit on its own line,
     so "Active" stays whole and holds its column open, while a long label like
     "1 opened the account page" still wraps at its spaces. */
  max-width: 100%; overflow-wrap: break-word;
  background: rgba(255,255,255,.06); border: 1px solid var(--line); color: var(--ink2);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.pill > i { width: 6px; height: 6px; border-radius: var(--r-pill); background: currentColor; flex: none; }
.pill.ok    { background: rgba(55,229,201,.13);  color: var(--teal);   border-color: rgba(55,229,201,.22); }
.pill.warn  { background: rgba(255,193,77,.13);  color: var(--amber);  border-color: rgba(255,193,77,.22); }
.pill.bad   { background: rgba(255,107,135,.13); color: var(--rose);   border-color: rgba(255,107,135,.22); }
.pill.off   { background: rgba(255,255,255,.045); color: var(--ink3); }
.pill.solid { background: linear-gradient(120deg, var(--violet), var(--violet2)); color: #0B0720; border-color: transparent; font-weight: 600; }

/* ── buttons ───────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  height: 52px; padding: 0 30px; border-radius: var(--r-pill); border: 0;
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; text-decoration: none;
  background: linear-gradient(120deg, var(--violet), var(--violet2)); color: #0B0720;
  box-shadow: var(--glow-v);
  transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease), background var(--fast) var(--ease);
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 22px 48px -18px rgba(139,124,255,1); }
.btn:active { transform: translateY(0); }
.btn.g { background: rgba(255,255,255,.07); color: var(--ink); border: 1px solid var(--line); box-shadow: none; }
.btn.g:hover { background: rgba(255,255,255,.11); box-shadow: none; }
.btn.sm { height: 42px; padding: 0 22px; font-size: 14px; }
/* "Get Ryvo" broke onto two lines in a tight phone header and read as a fault */
.btn { white-space: nowrap; }
@media (max-width: 460px) { .btn.sm { padding: 0 15px; font-size: 13.5px; } }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }

/* ── panels ────────────────────────────────────────────────────────── */
.panel {
  position: relative; overflow: hidden;
  background: linear-gradient(168deg, var(--panel), var(--panel-2));
  border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 26px; box-shadow: var(--lift);
}
.panel::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(120% 90% at 50% -20%, rgba(255,255,255,.05), transparent 55%);
}
.panel > * { position: relative; z-index: 1; }
.panel-h { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.panel-h h3 { font-size: 15px; font-weight: 600; }
.panel-h .sub { margin-left: auto; font-size: 12.5px; color: var(--ink3); }

/* ── bento ─────────────────────────────────────────────────────────── */
.bento { display: grid; grid-template-columns: repeat(12, 1fr); gap: 18px; }
.c3{grid-column:span 3}.c4{grid-column:span 4}.c5{grid-column:span 5}
.c6{grid-column:span 6}.c7{grid-column:span 7}.c8{grid-column:span 8}.c12{grid-column:span 12}

/* ── stat ──────────────────────────────────────────────────────────── */
.stat .k { font-size: 12.5px; color: var(--ink3); }
.stat .v {
  font-family: Outfit, sans-serif; font-weight: 600; font-size: 44px;
  /* 1.15, not 1.05. Outfit's digits need about 1.14 of their own size, so a
     1.05 line box cut 4px off a 44px figure — and because the number is a
     gradient CLIPPED TO THE TEXT, the slice takes the fill with it and reads
     as a badly rendered number rather than a tight line-height. `.stat` hides
     its overflow for the bloom, so there was nowhere for it to go. The mobile
     rule overrides only font-size, so it inherited the same ratio and clipped
     there too; fixing the base fixes both. Margins come down by the 4px the
     line box gained, so no tile changes height. */
  /* 1.2, matching .dsp — Outfit needs proportionally more at small sizes
     (1.168 at 63px, 1.185 at 27px), and this rule is also what the 23px
     figures on the phone layout inherit, where 1.15 would have been about a
     pixel short. One number for the whole typeface is easier to keep true
     than three that each drift. */
  letter-spacing: -.045em; line-height: 1.2; margin: 7px 0 5px;
  background: linear-gradient(180deg, #fff, #B9BFDA);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.stat .v small { font-size: 22px; color: var(--ink3); -webkit-text-fill-color: var(--ink3); }
/* The bloom behind a figure, which is what stops a number looking flat. */
.stat .bloom { position: absolute; width: 120px; height: 120px; border-radius: var(--r-pill);
  filter: blur(46px); opacity: .5; top: -14px; right: -14px; background: var(--violet); pointer-events: none; z-index: 0; }
.stat .bloom.t { background: var(--teal); }
.stat .bloom.a { background: var(--amber); }

/* ── capped bars ───────────────────────────────────────────────────── */
/* "Capped" was the name, not the behaviour — one row per licence with no
   limit, so as the customer count grew this dragged its grid row (Device
   mix sits beside it) up with it: two boxes that should read as roughly
   matched pairs instead ballooning together. Same hidden-scrollbar shape as
   .sup-thread elsewhere in this file, so a long list scrolls in place
   instead of resizing the panel — or its neighbour — around it. */
.cbars { display: grid; gap: 16px; max-height: 260px; overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none; }
.cbars::-webkit-scrollbar { width: 0; height: 0; display: none; }
.cb .l { display: flex; justify-content: space-between; font-size: 13px; color: var(--ink2); margin-bottom: 8px; }
.cb .l b { color: var(--ink); font-family: Outfit, sans-serif; font-weight: 600; }
.cb .t { height: 9px; border-radius: var(--r-pill); background: rgba(255,255,255,.06); overflow: hidden; }
.cb .t i { display: block; height: 100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--violet), var(--violet2));
  transition: width var(--slow) var(--ease); }
.cb .t i.teal  { background: linear-gradient(90deg, var(--teal2), var(--teal)); }
.cb .t i.amber { background: linear-gradient(90deg, #E0A63C, var(--amber)); }

/* ── capsule rows ──────────────────────────────────────────────────── */
.rows { display: grid; gap: 10px; }
.row {
  display: grid; grid-template-columns: 1fr auto auto; gap: 16px; align-items: center;
  background: rgba(255,255,255,.035); border: 1px solid var(--line);
  border-radius: var(--r-pill); padding: 12px 18px;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.row:hover { background: rgba(255,255,255,.06); border-color: var(--line2); }
.row .who { display: flex; align-items: center; gap: 13px; min-width: 0; }
.row .ic { width: 36px; height: 36px; border-radius: var(--r-pill); flex: none; display: grid; place-items: center;
  background: rgba(139,124,255,.16); color: var(--violet2); }
.row .ic svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.row .nm { font-size: 13.5px; font-weight: 500; }
.row .sb { font-size: 11.5px; color: var(--ink3); }
.row .mt { font-size: 12.5px; color: var(--ink3); }

/* ── fields ────────────────────────────────────────────────────────── */
.field { display: block; }
.field > span { display: block; font-size: 12.5px; color: var(--ink3); margin-bottom: 8px; }
.field input, .field select {
  width: 100%; height: 48px; padding: 0 20px; border-radius: var(--r-pill);
  background: rgba(255,255,255,.05); border: 1px solid var(--line);
  color: var(--ink); font: inherit; font-size: 14.5px; outline: 0;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.field input:focus { border-color: var(--violet); background: rgba(139,124,255,.07); }
.field input::placeholder { color: var(--ink4); }
.field .hint { font-size: 12px; color: var(--ink4); margin-top: 7px; display: block; }
.err { color: var(--rose); font-size: 13px; min-height: 19px; }
.err.ok { color: var(--teal); }

/* ── motion ────────────────────────────────────────────────────────────
   One entrance, used on first paint. Anything that eases in twice looks
   nervous, so this runs once and is never re-triggered on interaction. */
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.rise { animation: rise var(--slow) var(--ease) both; }
.rise-1 { animation-delay: .04s; } .rise-2 { animation-delay: .10s; }
.rise-3 { animation-delay: .16s; } .rise-4 { animation-delay: .22s; }

/* A stroke that draws itself in — used on the area charts so the page
   arrives rather than appearing. */
@keyframes draw { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }
.draw { stroke-dasharray: var(--len); animation: draw 1.4s var(--ease) both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ── responsive ────────────────────────────────────────────────────── */
@media (max-width: 1180px) { .bento > * { grid-column: span 6; } }
@media (max-width: 760px)  { .bento > * { grid-column: span 12; } .btn { width: 100%; }
  /* 34px is a mouse target. These are not decorative on a phone — "Add a
     television", "Copy" the licence key and "Forgotten your password" are all
     .mini, and all of them are things a customer taps with a thumb. */
  .mini { min-height: 40px; padding-left: 14px; padding-right: 14px; } }

/* ── Support thread ────────────────────────────────────────────────────
   Shared by the customer's account page and the admin inbox so the two
   cannot drift apart. */
.chips{display:flex;flex-wrap:nowrap;gap:7px;margin-bottom:14px}
/* One row on a desktop: the six labels come to roughly 540px of text
   against about 600px of panel, which fits only with the padding held
   down — these are deliberately tighter than the usual chip numbers.
   Below 860px the row genuinely is too narrow, so it wraps rather than
   squashing the labels. */
.chip{flex:0 0 auto;padding:6px 11px;border-radius:999px;background:rgba(255,255,255,.05);
      border:1px solid var(--line);font-size:12px;line-height:1.2;white-space:nowrap;
      cursor:pointer;transition:background var(--fast) var(--ease),border-color var(--fast) var(--ease)}
.chip:hover,.chip.on{background:rgba(139,124,255,.16);border-color:rgba(139,124,255,.42)}
@media (max-width:860px){ .chips{flex-wrap:wrap;gap:8px} }

.sup-thread{max-height:420px;overflow-y:auto;scrollbar-width:none;-ms-overflow-style:none}
.sup-thread::-webkit-scrollbar{width:0;height:0;display:none}
.msg{max-width:78%;padding:11px 14px;border-radius:16px;font-size:14px;line-height:1.5;
     margin-bottom:6px;white-space:pre-wrap;word-wrap:break-word}
.from-me{background:linear-gradient(180deg,#8B7CFF,#6f5fe8);color:#fff;margin-left:auto;
         border-bottom-right-radius:5px}
.from-them{background:rgba(255,255,255,.06);border:1px solid var(--line);border-bottom-left-radius:5px}
.msg-meta{font-size:11.5px;color:#7d86a1;margin:0 0 12px}
.msg-meta.r{text-align:right}

.composer{display:flex;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
/* A fixed height with resize:none forces a scrollbar the moment the text
   reaches one line, which looks broken. It grows instead, and the bar is
   suppressed on all three engines — miss one and it reappears there. */
.composer textarea{flex:1;min-width:0;background:rgba(255,255,255,.04);border:1px solid var(--line);
  color:var(--ink);border-radius:14px;padding:11px 13px;font:inherit;font-size:14px;resize:none;
  line-height:1.45;height:44px;max-height:132px;overflow-y:auto;
  scrollbar-width:none;-ms-overflow-style:none}
.composer textarea::-webkit-scrollbar{width:0;height:0;display:none}
.composer textarea::placeholder{color:#7d86a1}

/* 🔴 A composer button must NOT go full width.
   The mobile block below turns every .btn into width:100%, which is right for
   a page CTA and wrong for a button sitting beside a text field. Measured in
   the admin support chat at 375px: Send took 257px of a 295px row and left the
   reply box 28px wide — unusable, and it reads as the app being broken rather
   than as a stylesheet collision. Content-sized here, on both sides of the
   conversation, since customers answer from phones more than staff do. */
.composer .btn{width:auto;flex:0 0 auto;padding:0 20px}

.diagbox{margin-top:14px;padding:12px;border-radius:12px;background:rgba(255,255,255,.03);
         border:1px dashed var(--line);font-size:12.5px;color:#9aa3bd;line-height:1.7}

/* Admin support inbox rows.
   🔴 These existed only in the throwaway mockup and were never carried into
   the real stylesheet, so #sup-list rendered as unstyled divs — no padding,
   no border, no flex — which is what "scrambled" looked like. Scoped to
   #sup-list because `.thread` is far too generic a name to own globally. */
/* 🔴 No visible scrollbars anywhere on the support screen. It still scrolls —
   overflow stays auto — the bars are just not drawn.

   .sup-thread already did this; the two panes actually on screen did not, so
   the console showed bars down the thread column and the message pane and
   looked unfinished. All three now agree.

   Three declarations because three engines disagree: scrollbar-width is the
   standard one (Firefox), -ms-overflow-style is old Edge, and the
   ::-webkit-scrollbar pseudo-element is Chrome, Safari and current Edge —
   which is what a Fire TV browser and Danny's desktop both use, so the
   pseudo-element is the one doing the work here. */
.supcol-list, #sup-msgs { scrollbar-width: none; -ms-overflow-style: none; }
.supcol-list::-webkit-scrollbar, #sup-msgs::-webkit-scrollbar { width: 0; height: 0; display: none; }

#sup-list { padding: 8px; }
#sup-list .thread { display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: 14px; margin-bottom: 8px;
  background: rgba(255,255,255,.03); cursor: pointer;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease); }
#sup-list .thread:hover { background: rgba(139,124,255,.10); border-color: rgba(139,124,255,.35); }
#sup-list .thread:last-child { margin-bottom: 0; }

/* 🔴 The thread row was a plain flex: a long email pushed the status tag into
   the "1d" and the whole thing read as one cramped smear. Danny reported it.

   A GRID instead — name/preview take one column that is allowed to shrink,
   the age gets its own and never moves. minmax(0,1fr) is the part that makes
   ellipsis work; a bare 1fr refuses to shrink below its content and the
   overlap comes straight back. */
#sup-list .thread { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: start; column-gap: 14px; }
#sup-list .thread .who { display: flex; align-items: center; gap: 8px; min-width: 0; }
#sup-list .thread .who b { font-weight: 600; font-size: 13.5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The tag must never be the thing that gets squeezed — it is one or two words
   and it carries the state. */
#sup-list .thread .who .tag { flex: 0 0 auto; }
#sup-list .thread .prev { font-size: 12.5px; margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#sup-list .thread .age { font-size: 11.5px; white-space: nowrap; padding-top: 2px; }

/* 🔴 UNREAD. There WAS a marker — a 7px dot, placed after the tag inside the
   row that was already overflowing, so in practice it was invisible and Danny
   reported the inbox as giving no alert at all. The flag itself was fine:
   support.js sets unreadForAdmin when a customer writes.

   So the whole row changes instead of one dot: a teal edge, a teal wash, and
   the name at full white. Teal is the brand's own accent — never gold. */
#sup-list .thread.unread { border-color: rgba(55,229,201,.55);
  background: rgba(55,229,201,.10); box-shadow: inset 3px 0 0 0 var(--teal); }
#sup-list .thread.unread:hover { background: rgba(55,229,201,.16); }
#sup-list .thread.unread .who b { color: #fff; }
#sup-list .thread.unread .age { color: var(--teal); font-weight: 600; }
#sup-list .thread .newdot { width: 8px; height: 8px; border-radius: 50%;
  background: var(--teal); flex: 0 0 auto; box-shadow: 0 0 0 3px rgba(55,229,201,.22); }
#sup-msgs .msg { max-width: 82%; }

/* 🔴 NO VISIBLE SCROLLBARS, ANYWHERE. ONE RULE, NOT PER ELEMENT.

   Danny, repeatedly, and again on 10 Sept: "get rid of the scroller bars,
   how many times". The reason it keeps coming back is that it had been done
   one container at a time — .cbars, .sup-thread, .composer textarea,
   .supcol-list, #sup-msgs, #cmdk .res, .nav each carried their own copy of
   the same three declarations. Every new scrolling thing therefore starts
   life with a bar on it, and the fix is remembered only after he sees one.
   The admin drawer, the mobile action sheet and the horizontal table
   wrappers were all still showing them.

   So it is stated once, for everything, and no future element can miss it.

   Three declarations because three engines disagree: scrollbar-width is the
   standard and is Firefox today, -ms-overflow-style is old Edge and IE, and
   ::-webkit-scrollbar is Chrome, Safari and current Edge. Miss one and the
   bar survives on that browser only, which is the hardest kind to be told
   about.

   Nothing stops scrolling — wheel, trackpad, touch, arrow keys, Page Up and
   Down and a d-pad all still work. Only the bar is gone. */
*, *::before, *::after { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { width: 0; height: 0; display: none; }
html, body { scrollbar-width: none; -ms-overflow-style: none; }
html::-webkit-scrollbar, body::-webkit-scrollbar { width: 0; height: 0; display: none; }
