/* Site-wide mobile safety net: never let the body scroll sideways. overflow-x:clip
   contains any stray-wide element (off-canvas drawers, decorative glows, a rogue
   nowrap line) without creating a scroll container, so position:sticky still works.
   The real fix for each page is still to make content fit; this stops one stray
   element from breaking the whole layout on a phone (#mobile-overflow). */
html, body { overflow-x: clip; }

/* Site-wide mobile safety net #2: a tap with the smallest downward drag, at the
   top of a page, is read by Chrome/WebView as a pull-to-refresh gesture and
   reloads the whole page — indistinguishable from "any button reloads the app"
   to someone tapping normally on a touchscreen (#pull-to-refresh). Internal
   scrolling still works; only the browser's own refresh-on-overscroll is off. */
html, body { overscroll-behavior-y: contain; }

/* Mobile header fit: every page defines its own .nav-inner, and on a narrow
   phone the identity chip / Sign-in was pushed off the right edge. Shrink the
   gap, brand and chip site-wide so the chip always stays on-screen. The
   `nav .nav-inner` selector out-specifies each page's base rule regardless of
   stylesheet order (#mobile-header). */
@media (max-width: 560px) {
  nav .nav-inner { gap: 8px; }
  nav .nav-inner .brand { font-size: 15px; }
  nav .nav-inner .brand svg { width: 24px; height: 24px; }
  #ozIdChip { max-width: 148px; }
  #ozIdChip .oz-pts { display: none; }
}
/* OCCUPY ARENA IS A LETTER LONGER (10 Oct 2026): at 360px the home header's «احجز» pill ended 10px off the
   screen. The pages' own 12-13px rules for these widths never applied (this sheet's 15px out-specifies them). */
@media (max-width: 380px) {
  nav .nav-inner .brand { font-size: 13px; }
  nav .nav-inner .brand svg { width: 22px; height: 22px; }
}

/**
 * oz-motion.css — the shared motion + polish layer for OCCUPY ARENA.
 *
 * WHY THIS EXISTS
 * Every page had its own ad-hoc transitions, so the product felt like several
 * sites stitched together. This is one vocabulary, included with one line, so
 * the website, the kiosk, the big screen and the player app all move the same.
 *
 * THE VOCABULARY COMES FROM THE ARENA, NOT FROM A TEMPLATE
 *   · reveal    — a short, low-travel rise. Content arrives; it does not float.
 *   · lock      — numerals settle like a reticle acquiring a target.
 *   · pulse     — anything genuinely live breathes. Nothing else does.
 *   · scan      — a single sweep across a loading surface (radio sweep).
 *   · acquire   — a scope settling onto what it found. Once, on arrival.
 *   · press     — physical, immediate feedback. This is a venue tool; staff
 *                 need to know the tap registered.
 *
 * RULES
 *   · Motion is opt-in per element (a class), never a blanket * transition.
 *   · Only transform and opacity animate — they do not trigger layout.
 *   · prefers-reduced-motion gets a QUIETER version, never an absence. This
 *     line used to read "disables all of it. Non-negotiable", and that is
 *     exactly what the owner reported twice: on iOS it is set by Low Power
 *     Mode, and on Windows by one accessibility toggle, so "disabled" reached
 *     most of the people looking at the site. See the floor at the bottom.
 *   · Nothing in the floor ever runs `infinite`. A repeating animation is the
 *     one thing that preference most clearly asks not to happen — and two of
 *     them made the site heavy («الموقع بقا تقيل», 16 Sep).
 */

/* ---------- tokens ---------- */
:root{
  --oz-fast:.16s;
  --oz-base:.34s;
  --oz-slow:.6s;
  --oz-ease:cubic-bezier(.22,.68,.24,1);      /* decisive, slight settle */
  --oz-ease-out:cubic-bezier(.16,1,.3,1);     /* long tail, for reveals   */
}

/* ---------- reveal on scroll ----------
   12px of travel, not 40. Content should look like it arrived, not flew in. */
/* IT ARRIVES BY BEING LIT, AND IT DOES NOT TRAVEL.
   Owner, 20 Sep 2026: of the forty he was shown, the two that used to be here
   — content rising from below (#3) and a grid staggering up (#4) — are among
   the six he did not pick, and «معجبونيش اللي انا مش مختارهم». What he DID
   pick for a grid is #30: «نور بيعدّي عليهم بالترتيب وبيسيبهم» — a light
   passes over them in order and leaves them behind. A single block is the
   same sentence with one item in it, so both use it: nothing moves, the light
   arrives, and what it passes stays lit. */
/* HIDDEN ONLY ONCE THE SCRIPT THAT REVEALS IT IS RUNNING (5 Oct 2026, the finish-gate review).
   `.oz-rise{opacity:0}` on its own left every revealed band invisible wherever oz-motion.js did
   not run: no JavaScript, a blocked script, a page photographed whole. DESIGN.md: content is
   visible without JavaScript; a reveal only adds movement to something already there. The
   script arms the page (html.oz-armed) after lighting what is already in view. */
html.oz-armed .oz-rise{opacity:0}
.oz-rise.oz-in{animation:ozLit .52s cubic-bezier(.25,.75,.3,1) both}

/* the same light, passing along a grid one item at a time */
html.oz-armed .oz-stagger>*{opacity:0}
.oz-stagger.oz-in>*{animation:ozLit .52s cubic-bezier(.25,.75,.3,1) both}

/* THE SPIKE IN THE MIDDLE IS THE LIGHT ITSELF. Without it this is a fade, and
   a fade is not what he picked: the surface has to be BRIGHTER as the light
   crosses it than it is afterwards, or nothing passed over anything. */
@keyframes ozLit{
  0%{opacity:.05;filter:brightness(.5) saturate(.7)}
  40%{opacity:1;filter:brightness(1.55) saturate(1.15)}
  100%{opacity:1;filter:brightness(1) saturate(1)}
}
.oz-stagger.oz-in>*:nth-child(1){animation-delay:0s}
.oz-stagger.oz-in>*:nth-child(2){animation-delay:.06s}
.oz-stagger.oz-in>*:nth-child(3){animation-delay:.12s}
.oz-stagger.oz-in>*:nth-child(4){animation-delay:.18s}
.oz-stagger.oz-in>*:nth-child(5){animation-delay:.24s}
.oz-stagger.oz-in>*:nth-child(6){animation-delay:.30s}
.oz-stagger.oz-in>*:nth-child(n+7){transition-delay:.30s}

/* ---------- lock-on ----------
   A number that just changed gets one crisp beat. Used by countUp(). */
@keyframes ozLock{
  0%{transform:scale(1.11);filter:brightness(1.5)}
  60%{transform:scale(.985)}
  100%{transform:scale(1);filter:brightness(1)}
}
.oz-lock{animation:ozLock .3s var(--oz-ease) both}

/* ---------- live pulse ----------
   Reserved for things that are genuinely live. Never decorative. */
@keyframes ozPulse{
  0%,100%{opacity:1;box-shadow:0 0 0 0 currentColor}
  55%{opacity:.62;box-shadow:0 0 0 7px transparent}
}
.oz-live{animation:ozPulse 1.5s ease-in-out infinite}

/* ---------- scan (loading) ----------
   A radio sweep across the surface while real data is on its way. Replaces
   the blank panels that used to sit there with no explanation. */
.oz-skel{
  position:relative;overflow:hidden;
  background:rgba(255,255,255,.05);
  border-radius:10px;min-height:14px;
}
.oz-skel::after{
  content:'';position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(52,224,240,.16),transparent);
  animation:ozScan 1.15s ease-in-out infinite;
}
@keyframes ozScan{100%{transform:translateX(100%)}}
.oz-skel.t{height:13px;margin:7px 0;border-radius:6px}
.oz-skel.t.w60{width:60%}.oz-skel.t.w40{width:40%}.oz-skel.t.w80{width:80%}

/* ---------- acquire ----------
   A scope settling onto what it found: the rings arrive a touch large and
   turned, then lock. Once, on arrival. It never loops; a reticle that keeps
   turning is decoration, and only live things keep moving (see pulse). */
@keyframes ozAcquire{
  0%{opacity:0;transform:scale(1.12) rotate(-9deg)}
  70%{opacity:1}
  100%{opacity:1;transform:none}
}
.oz-acquire{animation:ozAcquire 1.1s var(--oz-ease-out) both;transform-origin:50% 50%}

/* ---------- press feedback ---------- */
.oz-press{transition:transform var(--oz-fast) var(--oz-ease),
                     filter var(--oz-fast) var(--oz-ease)}
.oz-press:active{transform:scale(.972)}
.oz-press:hover{filter:brightness(1.07)}

/* lift for cards that are actually clickable */
.oz-lift{transition:transform var(--oz-base) var(--oz-ease),
                    border-color var(--oz-base) var(--oz-ease),
                    box-shadow var(--oz-base) var(--oz-ease)}
.oz-lift:hover{transform:translateY(-3px)}

/* ---------- value flash ----------
   A score that went up glows green for a beat; one that dropped, red. */
@keyframes ozUp{0%{color:var(--green,#3BE0A0)}100%{color:inherit}}
@keyframes ozDown{0%{color:var(--red,#FF5A76)}100%{color:inherit}}
.oz-up{animation:ozUp .9s var(--oz-ease) both}
.oz-down{animation:ozDown .9s var(--oz-ease) both}

/* ---------- page entrance ----------
   One quiet settle on load so a page never snaps into place. */
@keyframes ozEnter{from{opacity:0;transform:translate3d(0,6px,0)}to{opacity:1;transform:none}}
.oz-enter{animation:ozEnter var(--oz-base) var(--oz-ease-out) both}

/* ---------- focus, always visible ---------- */
.oz-press:focus-visible,.oz-lift:focus-visible{
  outline:2px solid var(--cyan,#34E0F0);outline-offset:3px;
}

/* ---------- THE BREACH ----------
 *
 * Owner, 15 Sep 2026: «إن تسجيل الدخول لما حد يسجل ... يروح ضارب الباب طلقه
 * ورازعه بالرجل وداخل ويعمل انيميشن لدخول الموقع».
 *
 * The way in is a door, so the button that opens it is one. A hairline seam
 * and two jamb ticks, always there and almost unnoticed — until the password
 * is right, and it is kicked off its hinges.
 *
 * ONE moment, in ONE place. Everything else on this page stays quiet: a site
 * that flashes at every press has no way to say "this one mattered". The panels
 * are drawn by oz-motion.js over the button's own rectangle, so no page has to
 * change its markup to get it, and nothing is left behind afterwards.
 *
 * The wrong password uses the SAME mechanism in the other direction: the door
 * holds. It is the honest opposite of being let in, and it needs no new idea.
 */
 * REBUILT 15 Sep 2026, THE SAME EVENING, ON THE OWNER'S VERDICT:
 * «الباب مكانه غلط انت حاطه في النص وكمان مفيش انيميشن وشكله وحش».
 *
 * He was right three times, and the third one is the one that matters:
 *
 *   · THE PLACE WAS WRONG. The first version put a hairline seam down the
 *     middle of the sign-in BUTTON. A thin line through the middle of a label
 *     does not read as a door; it reads as a rendering fault. What actually
 *     stands between somebody and the site is the sign-in CARD and the dark
 *     sheet behind it — so THAT is the door, and it is the whole screen.
 *   · NOTHING IS DRAWN AT REST any more. The door only exists during the kick.
 *   · AND HE SAW NO ANIMATION AT ALL, because the seam was not in the
 *     reduced-motion block below while the animation was. A phone with battery
 *     saver on — or anybody who has ever turned "reduce motion" on — got the
 *     ugly line and none of the payoff. Reduced motion means DO NOT THROW THE
 *     ROOM ABOUT. It does not mean "give this person nothing": that is how a
 *     feature ends up invisible to the one person who reported it. The doors
 *     still open for them; they just fade instead of swinging.
 */

/* the door holds: a shove that does not open it (a wrong password) */
@keyframes ozHold{
  0%,100%{transform:translateX(0)}
  14%{transform:translateX(-9px)}32%{transform:translateX(8px)}
  52%{transform:translateX(-5px)}72%{transform:translateX(4px)}88%{transform:translateX(-2px)}
}
.oz-held{animation:ozHold .44s var(--oz-ease) both}
.oz-held{border-color:var(--red,#FF5A76)!important;box-shadow:0 0 0 1px rgba(255,90,118,.5),0 0 26px rgba(255,90,118,.35)}

/* ---------- THE DOOR, AND IT IS IN THE BUTTON ---------------------------
 *
 * Owner, 16 Sep 2026: «انا كنت عايز باب حرفياً باب في تسجيل الدخول يبقا
 * فالزرار وكدا» — and, about the full-screen version that used to stand here:
 * «فتح الباب وقفله مش بالطريقة ديه حاسه اوفر اوي ومش حلو اصلاً».
 *
 * WHAT WAS HERE BEFORE AND WHY IT IS GONE. A boot flying in from off-screen,
 * the card struck off its hinges, two leaves the size of the screen, a seam, a
 * shock ring and a flash — six things for one moment. He read it as a
 * production, and what he had asked for on day one was smaller than any of it:
 * a door, in the button, that opens when the password is right. Everything he
 * KEPT out of the forty candidates was one object doing one thing in under
 * .7s; everything he threw out was either five things at once or an effect
 * with no object behind it. This is that rule applied to the way in.
 *
 * AT REST IT HAS TO READ AS A DOOR. The first attempt (15 Sep) drew a hairline
 * down the middle of the button and he called it what it was: «شكله وحش». A
 * line is not a door. A frame, a leaf with a panel in it, a handle and a
 * person standing at it are — and all four are there before anything is
 * pressed, which is the point: you can see what is about to happen.
 *
 * THREE WAYS IT OPENS, one of which is on the site at any time:
 *   k41  he winds up and kicks it off its hinge   (his original sentence)
 *   k42  it is pushed open and he walks through
 *   k43  the leaf goes and the light comes out, nobody in it
 * Switch with ?door=41|42|43 on any page; the choice sticks in the browser.
 */

/* BIGGER THAN THE FIRST CUT, BECAUSE HE COULD NOT SEE IT WORK. Owner, 20 Sep:
   «الباب عايزه يبقا احسن شوية وباين الفتح والقفل». At 22×30 the leaf turned
   through 9px of screen and the whole moment was a flicker; at 26×36 the swing
   is 13px, the doorway behind it is a room rather than a slot, and the light
   that comes out is wide enough to spill onto the button (see ozDoorGlow). */
.ozdoor{position:relative;display:inline-block;width:26px;height:36px;flex:0 0 26px;
  border-radius:4px 4px 0 0;border:2px solid rgba(7,16,30,.82);background:#080e18;
  overflow:hidden;perspective:80px;perspective-origin:76% 50%;vertical-align:middle;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12)}
/* the room on the other side, dark until the door opens */
.ozdoor .ozdoor-lite{position:absolute;inset:0;opacity:0;
  background:linear-gradient(180deg,#f2feff,var(--cyan,#34E0F0) 58%,#0f7b8a)}
/* the leaf, hinged on its leading edge. The inner panel and the line down the
   closing edge are what make it read as a LEAF rather than a filled rectangle,
   and they are the parts the eye tracks while it turns. */
.ozdoor .ozdoor-leaf{position:absolute;inset:0;transform-origin:left center;
  background:linear-gradient(112deg,#243346,#0f1826 62%);
  border-right:1px solid rgba(52,224,240,.45)}
.ozdoor .ozdoor-leaf::after{content:'';position:absolute;left:4px;top:4px;right:4px;bottom:4px;
  border:1px solid rgba(52,224,240,.34);border-radius:2px}
.ozdoor .ozdoor-knob{position:absolute;right:4px;top:50%;width:4px;height:4px;margin-top:-2px;
  border-radius:50%;background:var(--cyan,#34E0F0);box-shadow:0 0 5px rgba(52,224,240,.95);z-index:2}
/* the person waiting at it — a drawn mark, never a character (§3.7) */
.ozdoor .ozdoor-man{position:absolute;left:50%;bottom:2px;width:11px;height:22px;margin-left:-5.5px;
  color:#e6f9ff;z-index:3;transform-origin:50% 90%}
.ozdoor .ozdoor-man svg{width:100%;height:100%;display:block}

/* THE LIGHT GETS OUT OF THE DOORWAY. A door opening is not only a leaf moving:
   it is the room behind it reaching the room you are in. The frame itself
   throws light onto the button for the length of the swing, which is what
   makes the opening legible at 26px without making anything travel. */
@keyframes ozDoorGlow{
  0%{box-shadow:inset 0 1px 0 rgba(255,255,255,.12)}
  45%{box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 0 16px 3px rgba(226,253,255,.75)}
  100%{box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 0 10px 1px rgba(226,253,255,.42)}
}
@keyframes ozDoorGlowOut{
  0%{box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 0 12px 2px rgba(226,253,255,.6)}
  100%{box-shadow:inset 0 1px 0 rgba(255,255,255,.12)}
}

/* 41 · KICKED. The leaf is pushed IN for one frame — the wind-up is the whole
   difference between "struck" and "opened" — and then thrown off its hinge. */
.ozdoor.k41.oz-run .ozdoor-leaf{animation:ozDoorKick .62s cubic-bezier(.2,.9,.2,1) both}
.ozdoor.k41.oz-run .ozdoor-lite{animation:ozDoorLite .62s ease-out both .2s}
.ozdoor.k41.oz-run .ozdoor-man{animation:ozDoorMan .62s cubic-bezier(.3,.8,.3,1) both}
.ozdoor.k41.oz-run .ozdoor-knob{animation:ozDoorKnob .62s linear both}
.ozdoor.k41.oz-run{animation:ozDoorGlow .62s ease-out both}
@keyframes ozDoorKick{
  0%{transform:rotateY(0);filter:brightness(1)}
  26%{transform:rotateY(5deg);filter:brightness(1.15)}   /* wound up against it */
  38%{transform:rotateY(-78deg);filter:brightness(.8)}   /* the boot lands */
  72%{transform:rotateY(-102deg);filter:brightness(.5)}
  100%{transform:rotateY(-112deg);filter:brightness(.38)}
}
@keyframes ozDoorMan{
  0%{opacity:1;transform:translateX(0) rotate(0)}
  24%{opacity:1;transform:translateX(-3px) rotate(-7deg)}   /* leans back */
  36%{opacity:1;transform:translateX(2px) rotate(9deg)}     /* strikes */
  60%{opacity:1;transform:translateX(4px) rotate(0)}
  100%{opacity:0;transform:translateX(11px) rotate(0)}      /* through it */
}
@keyframes ozDoorLite{0%{opacity:0}45%{opacity:1}100%{opacity:.8}}
@keyframes ozDoorKnob{0%{opacity:1}30%{opacity:1}42%{opacity:0}100%{opacity:0}}

/* 42 · OPENED. The same door with no violence in it: pushed, and walked
   through. */
.ozdoor.k42.oz-run .ozdoor-leaf{animation:ozDoorOpen .66s cubic-bezier(.3,.7,.2,1) both}
.ozdoor.k42.oz-run .ozdoor-lite{animation:ozDoorLite .66s ease-out both .12s}
.ozdoor.k42.oz-run .ozdoor-man{animation:ozDoorWalk .66s ease-in-out both .1s}
.ozdoor.k42.oz-run .ozdoor-knob{animation:ozDoorKnob .66s linear both}
.ozdoor.k42.oz-run{animation:ozDoorGlow .66s ease-out both}
@keyframes ozDoorOpen{0%{transform:rotateY(0);filter:brightness(1)}
  100%{transform:rotateY(-108deg);filter:brightness(.4)}}
@keyframes ozDoorWalk{0%{opacity:1;transform:translateX(0)}
  55%{opacity:1;transform:translateX(5px)}100%{opacity:0;transform:translateX(11px)}}

/* 43 · JUST THE DOOR. No figure at all — the leaf goes and the light is out. */
.ozdoor.k43 .ozdoor-man{display:none}
.ozdoor.k43.oz-run .ozdoor-leaf{animation:ozDoorOpen .58s cubic-bezier(.25,.85,.2,1) both}
.ozdoor.k43.oz-run .ozdoor-lite{animation:ozDoorLite .58s ease-out both .1s}
.ozdoor.k43.oz-run .ozdoor-knob{animation:ozDoorKnob .58s linear both}
.ozdoor.k43.oz-run{animation:ozDoorGlow .58s ease-out both}

/* ---------- 17 · THE RADAR ---------------------------------------------
 *
 * «الخريطة الحيّة والريكون — ذراع بتلفّ وبتنوّر اللي بتعدّي عليه. بتفضل
 * شغّالة طول ما الخريطة مفتوحة».
 *
 * IT REPEATS, and it is the third and last thing on the site allowed to: a
 * radar that stops is a radar that is not looking. It exists only while the
 * floor plan is open on the big screen, so it cannot become the site's
 * weight — the page it lives on is a television on a wall.
 */
.ozradar{position:absolute;inset:0;pointer-events:none;overflow:hidden;z-index:0}
.ozradar i{position:absolute;left:50%;top:50%;width:150%;height:150%;margin:-75% 0 0 -75%;
  background:conic-gradient(from 0deg,rgba(52,224,240,.26) 0deg,
             rgba(52,224,240,.05) 34deg,rgba(52,224,240,0) 62deg,rgba(52,224,240,0) 360deg);
  animation:ozRadarArm 4.4s linear infinite}
.ozradar::after{content:'';position:absolute;inset:10%;border-radius:50%;
  border:1px solid rgba(52,224,240,.14)}
@keyframes ozRadarArm{to{transform:rotate(360deg)}}

/* ---------- 18 · A RANK GOES UP ----------------------------------------
 *
 * «ترقية رتبة: الشعار بينزل من فوق ويتختم وتطلع منه موجة». It happens once,
 * the first time the player opens their profile after crossing a tier — not
 * on every visit, or it is wallpaper.
 */
.ozrank{position:relative;animation:ozRank .62s cubic-bezier(.2,.9,.25,1) both}
@keyframes ozRank{
  0%{opacity:0;transform:translate3d(0,-22px,0) scale(1.3)}
  38%{opacity:1;transform:translate3d(0,0,0) scale(1)}     /* the stamp */
  48%{transform:scale(1.09)}
  62%{transform:scale(1)}
  100%{transform:none}
}
/* and the wave off the stamp */
.ozrank::after{content:'';position:absolute;inset:-7px;border-radius:999px;
  border:2px solid currentColor;opacity:0;pointer-events:none;
  animation:ozRankWave .72s cubic-bezier(.1,.8,.2,1) both .3s}
@keyframes ozRankWave{0%{opacity:.85;transform:scale(.6)}100%{opacity:0;transform:scale(2.2)}}

/* ---------- 20 · SOMETHING IS REFUSED -----------------------------------
 *
 * «تشويش: لما حاجة تترفض أو النت يفصل — الكلام بيتهزّ ويتفكّ لونه لثانية».
 * It rides on the shared toast, so every refusal on the site gets it and no
 * page has to remember to ask: oz-ui adds this class whenever the toast is
 * the bad kind.
 */
.oz-glitch{animation:ozGlitch .46s steps(3,end) 2 both}
@keyframes ozGlitch{
  0%{transform:translate3d(0,0,0);text-shadow:none}
  22%{transform:translate3d(-2px,1px,0);
      text-shadow:2px 0 var(--red,#FF5A76),-2px 0 var(--cyan,#34E0F0)}
  44%{transform:translate3d(2px,-1px,0);
      text-shadow:-2px 0 var(--red,#FF5A76),2px 0 var(--cyan,#34E0F0)}
  66%{transform:translate3d(-1px,0,0);
      text-shadow:1px 0 var(--red,#FF5A76),-1px 0 var(--cyan,#34E0F0)}
  100%{transform:none;text-shadow:none}
}

/* ---------- 22 · SOMEBODY LANDS IN HIS SLOT -----------------------------
 *
 * «تكوين السكواد — كل لاعب بينزل في خانته من فوق ويستقر فيها».
 *
 * This one TRAVELS, and that is not a contradiction of everything above: a
 * name arriving in a squad slot is an object doing something you can point
 * at, which is the rule he actually picked by. What he threw out was travel
 * with no object behind it — a card sliding up because it is new.
 */
.ozdrop{animation:ozDrop .44s cubic-bezier(.22,.9,.3,1) both}
@keyframes ozDrop{
  0%{opacity:0;transform:translate3d(0,-16px,0)}
  62%{opacity:1;transform:translate3d(0,2px,0)}    /* it lands, and settles */
  100%{opacity:1;transform:none}
}

/* ---------- 23 · THE PRIZE IS UNLOCKED ----------------------------------
 *
 * «فتح جايزة: القفل بيرتفع ويلفّ، والجسم بينوّر». Drawn over the order the
 * moment the venue's server says it is his — the lock is a mark we drew, and
 * the row it opens on lights once underneath it.
 */
.ozlock{position:fixed;z-index:2147481700;pointer-events:none;
  display:flex;align-items:center;justify-content:center}
.ozlock svg{width:40px;height:40px;color:var(--gold,#F5C451);
  filter:drop-shadow(0 0 12px rgba(245,196,81,.85));
  animation:ozLockPop .66s cubic-bezier(.25,.85,.3,1) both}
.ozlock .ozlock-shk{transform-origin:50% 64%;
  animation:ozLockLift .66s cubic-bezier(.3,.8,.25,1) both}
@keyframes ozLockLift{0%{transform:none}30%{transform:translateY(-3px)}
  100%{transform:translateY(-7px) rotate(-28deg)}}
@keyframes ozLockPop{0%{opacity:0;transform:scale(.7)}
  16%{opacity:1;transform:scale(1)}70%{opacity:1;transform:scale(1)}
  100%{opacity:0;transform:scale(1.22)}}
/* and the thing itself, lighting up under it */
.oz-got{animation:ozGot .8s ease-out both}
@keyframes ozGot{0%{filter:brightness(1)}20%{filter:brightness(1.5) saturate(1.2)}
  100%{filter:brightness(1)}}

/* ---------- 16 · THE COUNT IN -------------------------------------------
 *
 * «٣ ٢ ١ — بداية الجولة: كل رقم بيتضرب في الشاشة وبيختفي». On the big screen
 * before a round, on the same clock as the countdown tones the room already
 * hears (600ms apart, then the long one at 1.85s).
 *
 * STRUCK, NOT FADED IN. The numeral arrives at 2.6x and lands in a seventh of
 * a second — force on a screen is size and speed (the same rule the first
 * sign-in boot got wrong). It is gone before the next one starts, so there is
 * never more than one thing on the screen.
 *
 * AT "off" THE COUNT STILL HAPPENS. Three, two, one is information — the
 * round is about to start — and the person who asked for no motion still
 * needs it. The numbers swap; nothing scales.
 */
.ozcount{position:fixed;inset:0;z-index:2147481500;pointer-events:none;
  display:flex;align-items:center;justify-content:center;
  background:rgba(6,10,18,.42);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.ozcount b{font:900 clamp(96px,26vw,340px)/1 Orbitron,system-ui,sans-serif;color:#eafdff;
  text-shadow:0 0 40px rgba(52,224,240,.75),0 0 100px rgba(52,224,240,.38);
  animation:ozCountHit .58s cubic-bezier(.2,.9,.2,1) both}
.ozcount b.go{color:var(--cyan,#34E0F0);font-size:clamp(64px,15vw,200px)}
@keyframes ozCountHit{
  0%{opacity:0;transform:scale(2.6)}
  14%{opacity:1;transform:scale(1)}        /* it lands */
  18%{transform:scale(1.07)}               /* and rings */
  28%{transform:scale(1)}
  74%{opacity:1;transform:scale(1)}
  100%{opacity:0;transform:scale(.93)}
}

/* ---------- 24 · THE BAND LEAVES THE WORD BEHIND ------------------------
 *
 * «الفوز: شريط بيعدّي على الكلمة ويسيبها وراه». The end of a round on the big
 * screen. The band crosses in the team's own colour and the word is simply
 * there afterwards — nothing arrives, nothing bounces.
 */
.ozband{position:fixed;inset:0;z-index:2147481500;pointer-events:none;
  display:flex;align-items:center;justify-content:center}
.ozband b{position:relative;padding:10px 34px;color:var(--green,#3BE0A0);opacity:0;
  font:900 clamp(40px,9vw,130px)/1.1 Orbitron,system-ui,sans-serif;
  animation:ozBandWord .5s cubic-bezier(.2,.9,.25,1) both .24s}
.ozband b::before{content:'';position:absolute;inset:0;background:currentColor;
  transform:scaleX(0);transform-origin:right center;
  animation:ozBandSweep .6s cubic-bezier(.4,0,.2,1) both}
.ozband.ozband-out{animation:ozDoorFade .4s linear both}
@keyframes ozBandSweep{
  0%{transform:scaleX(0);transform-origin:right center}
  45%{transform:scaleX(1);transform-origin:right center}
  46%{transform:scaleX(1);transform-origin:left center}
  100%{transform:scaleX(0);transform-origin:left center}
}
@keyframes ozBandWord{0%{opacity:0;transform:translateY(8px)}100%{opacity:1;transform:none}}

/* ---------- WAITING: THE RADIO FINDING THE SIGNAL ----------------------
 *
 * He ticked the loading sweep (#7) and all three of its alternatives — the
 * radar (#32), the five signal bars (#33) and the needle hunting along a dial
 * (#34) — and said: «في حاجات مختار منها اكتر من شكل بس عايزك تدمجهم مع
 * بعض». They are not four ideas. They are one: a receiver looking for a
 * signal it has not found yet.
 *
 * So the rows keep the sweep of light they already had (#7 — that is what a
 * placeholder ROW is for), and anywhere the page is waiting on the server
 * with a word rather than a row, this mark sits beside the word: five bars
 * hunting for level, with the needle crossing them. One object, and it says
 * exactly what is happening — we are listening, nothing has arrived yet.
 *
 * IT REPEATS ON PURPOSE, and it is the only thing on the site besides the
 * live dot that may: a wait with a finite animation is a wait that ends on
 * screen while the page is still waiting, which is the "spinner that lies"
 * this venue has already been bitten by (agents.html, 7 Sep). It is removed
 * the moment the data lands, so it can never become the site's weight.
 */
.oztune{display:inline-flex;align-items:flex-end;gap:2px;height:16px;width:34px;
  position:relative;vertical-align:-3px;margin-inline-end:8px}
.oztune span{display:block;width:4px;height:4px;border-radius:1px;
  background:var(--cyan,#34E0F0);opacity:.5;animation:ozTuneBar 1.15s ease-in-out infinite}
.oztune span:nth-child(2){animation-delay:.09s}
.oztune span:nth-child(3){animation-delay:.18s}
.oztune span:nth-child(4){animation-delay:.27s}
.oztune span:nth-child(5){animation-delay:.36s}
.oztune span:nth-child(6){animation-delay:.45s}
/* the needle crossing the dial, looking for it */
.oztune i{position:absolute;left:0;top:-1px;bottom:-1px;width:2px;border-radius:1px;
  background:#eafdff;box-shadow:0 0 9px 1px rgba(226,253,255,.85);
  animation:ozTuneHunt 1.9s cubic-bezier(.45,0,.55,1) infinite}
@keyframes ozTuneBar{0%,100%{height:4px;opacity:.45}50%{height:15px;opacity:1}}
@keyframes ozTuneHunt{0%{transform:translateX(0)}50%{transform:translateX(32px)}
  100%{transform:translateX(0)}}

/* 21 · WHILE IT IS BEING TYPED, there is something doing the typing. A solid
   bar, not a blinking one: a caret that blinks is a repeating animation for
   the sake of decoration, and it would be the only thing on the site running
   forever for no reason. It goes with the attribute, the moment the code is
   complete. */
[data-oz-typing]::after{content:'';display:inline-block;width:.08em;height:1em;
  margin-inline-start:.06em;vertical-align:-.12em;background:var(--cyan,#34E0F0);
  box-shadow:0 0 8px rgba(52,224,240,.8)}

/* ---------- 26 · THE IDENTITY IS READ ----------------------------------
 *
 * He picked this one as well as the door (#26 «مسح الهوية»: one line goes down
 * the card, reads it, and that is all), and asked for the ones he picked twice
 * over to be MERGED rather than chosen between. They are one sentence when
 * they run in order: the card is read, and then the door opens for the person
 * it belongs to. Nothing is thrown, and there is still only one object moving
 * at a time.
 *
 * It is drawn OVER the sign-in card, on its own rectangle, so no markup in the
 * card changes and nothing reflows.
 */
.ozscan{position:fixed;z-index:2147481900;pointer-events:none;overflow:hidden;
  border-radius:16px}
.ozscan i{position:absolute;left:0;right:0;top:0;height:2px;
  background:linear-gradient(90deg,transparent,var(--cyan,#34E0F0) 18%,#eafdff 50%,
                             var(--cyan,#34E0F0) 82%,transparent);
  box-shadow:0 0 14px 2px rgba(52,224,240,.75);
  animation:ozScanDown .34s cubic-bezier(.4,0,.3,1) both}
/* and the card lights up very slightly as the line passes — the surface being
   read, rather than a line sitting on top of a picture of one */
.ozscan{animation:ozScanGlow .34s linear both}
@keyframes ozScanDown{0%{transform:translateY(0);opacity:0}
  12%{opacity:1}88%{opacity:1}
  100%{transform:translateY(var(--ozs-h,300px));opacity:0}}
@keyframes ozScanGlow{0%,100%{background:transparent}
  50%{background:rgba(52,224,240,.05)}}

/* ---------- THE WAY OUT: the same door, closing -------------------------
 *
 * Owner, 16 Sep 2026: «وكمان اعمل حاجه للـ Logout او كدا».
 *
 * The counterpart, and the only honest one: the door you came through,
 * shutting. It is drawn AT THE FINGER — the point that was actually pressed —
 * because a thing that happens where you touched happened because of you, and
 * the same door appearing in the middle of the screen would be the production
 * all over again. Nobody walks out of it: leaving is an acknowledgement, and a
 * place that makes a performance out of somebody going has misread the room.
 */
/* A LITTLE BIGGER THAN THE ONE IN THE BUTTON. There it sits beside a label
   and borrows its scale; here it stands alone on the page at the point of a
   finger, and 22x30 at arm's length is a speck. */
.ozdoor-fly{position:fixed;z-index:2147482000;pointer-events:none;margin:-15px 0 0 -11px;
  transform:scale(1.8);transform-origin:center}
.ozdoor.oz-shut .ozdoor-man{display:none}
.ozdoor.oz-shut .ozdoor-leaf{animation:ozDoorShut .46s cubic-bezier(.3,.72,.2,1) both}
.ozdoor.oz-shut .ozdoor-lite{animation:ozDoorDim .46s ease-out both}
/* the handle comes back the instant the leaf meets the frame — the small
   click at the end that says SHUT rather than "stopped moving" */
.ozdoor.oz-shut .ozdoor-knob{animation:ozDoorClick .2s ease-out both .4s}
.ozdoor.oz-shut{animation:ozDoorGlowOut .46s ease-out both,ozDoorFade .3s linear both .5s}
@keyframes ozDoorShut{0%{transform:rotateY(-108deg);filter:brightness(.4)}
  82%{transform:rotateY(-3deg);filter:brightness(1.05)}
  100%{transform:rotateY(0);filter:brightness(1)}}
@keyframes ozDoorDim{0%{opacity:.85}70%{opacity:.25}100%{opacity:0}}
@keyframes ozDoorClick{0%{opacity:0;transform:scale(.4)}60%{opacity:1;transform:scale(1.5)}
  100%{opacity:1;transform:scale(1)}}
@keyframes ozDoorFade{to{opacity:0}}

/* ---------- sheen ----------
 * A single band of light crossing a card when you put a finger or a cursor on
 * it. Owner, 15 Sep: «عايز الناس تحس انها داخله حاجه بريميوم».
 *
 * It is a SWEEP, not a glow: the card is lit from one side and the light
 * leaves, which is what a real surface does and what a gradient sitting there
 * permanently does not. One pass, then nothing — a card that keeps shimmering
 * is a cheap card.
 */
.oz-sheen{position:relative;overflow:hidden}
.oz-sheen>*{position:relative;z-index:1}
.oz-sheen::before{
  content:'';position:absolute;top:-40%;bottom:-40%;left:-60%;width:45%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.13) 42%,
                             rgba(52,224,240,.20) 52%,transparent);
  transform:translate3d(0,0,0) skewX(-14deg);opacity:0;pointer-events:none;z-index:0;
}
.oz-sheen:hover::before,.oz-sheen:focus-visible::before{animation:ozSheen .72s var(--oz-ease-out) both}
@keyframes ozSheen{
  0%{opacity:0;transform:translate3d(0,0,0) skewX(-14deg)}
  12%{opacity:1}
  100%{opacity:0;transform:translate3d(420%,0,0) skewX(-14deg)}
}

/* ---------- lock-on ----------
 * A reticle closing on something that has just become real — the booking code
 * at the moment an hour is held. Two corner brackets snap in from outside and
 * settle, once.
 *
 * It deliberately reuses the scope language the homepage hero already speaks
 * rather than inventing a new effect, so somebody who has seen the front page
 * recognises it. And it is used in exactly ONE place: that panel already has a
 * QR drawing itself and a coin toss of its own, and a third effect competing
 * with them would read as noise, not polish.
 *
 * THE BRACKETS ARE NOT MOTION — they are a frame around the thing you are
 * meant to screenshot. So under reduced motion they still appear; they simply
 * do not fly in. Hiding them there would take the marker away from the reader
 * who asked for less movement, which is the mistake the sign-in door already
 * taught once tonight.
 */
.oz-lockon{position:relative}
/* EACH HALF SPANS THE WHOLE THING, so the two of them ARE the frame. They
   used to be two 18px corner brackets, which is what «الهدف بيتقفل» was; a
   frame that draws itself has to end up as a frame. */
.oz-lockon::before,.oz-lockon::after{
  content:'';position:absolute;pointer-events:none;inset:-6px;
  border:2px solid var(--cyan,#34E0F0);
}
/* 37 · IT IS DRAWN, NOT FLOWN IN. He did not pick the two brackets arriving
   from off-screen (#13); he picked «إطار بيترسم حواليه ضلع ورا ضلع» — the
   frame drawing itself around the code, so it is clear WHICH thing to
   photograph. Two Ls, each growing out of its own corner along both of its
   edges, a beat apart: four strokes, one frame, nothing travelling. */
.oz-lockon::before{
  border-inline-end-width:0;border-bottom-width:0;
  transform-origin:top left;
  animation:ozFrameA .34s cubic-bezier(.2,.8,.25,1) both;
}
.oz-lockon::after{
  border-inline-start-width:0;border-top-width:0;
  transform-origin:bottom right;
  animation:ozFrameB .34s cubic-bezier(.2,.8,.25,1) both .16s;
}
@keyframes ozFrameA{
  0%{opacity:0;transform:scale(.04)}
  25%{opacity:1}
  100%{opacity:1;transform:scale(1)}
}
@keyframes ozFrameB{
  0%{opacity:0;transform:scale(.04)}
  25%{opacity:1}
  100%{opacity:1;transform:scale(1)}
}

/* ---------- moving between pages ----------
 * A single band of light crossing the screen as one page hands over to the
 * next, so the site reads as one place you are moving through rather than a
 * stack of documents that blink. It is drawn OVER everything and blocks
 * nothing; the navigation itself never waits on it (see oz-motion.js).
 */
/* IT COMES FROM THE FINGER.
   A band travelling left to right is the single most generic transition there
   is, and it has no relationship to anything the person did — «الأنيميشنز ديه
   مش حلوه». This blooms out of the exact point that was tapped, so the page
   leaves because of them rather than on a timer, and the dark edge it carries
   is what hands the screen over to whatever loads next.
   It is short on purpose: the navigation fires at 150ms and takes the old page
   with it, so nearly all of this has to have happened by then. */
/* 39 · ONE LINE CROSSES, AND THE PAGE HAS CHANGED BEHIND IT.
   The bloom that used to be here is #14, which he did not pick; this is #39,
   «خط نور واحد بيعدّي على الشاشة والصفحة اتغيّرت وراه». It still comes from
   the finger — the line starts on the side he actually tapped — because a
   hand-over that begins where he pressed happened because of him. The page
   navigates at 150ms, while the line is mid-screen, so what he sees is the
   light passing and the new page already behind it. */
.oz-wipe{
  position:fixed;inset:0;z-index:2147481000;pointer-events:none;overflow:hidden;
  animation:ozWipe .42s linear both;
}
.oz-wipe::before{
  content:'';position:absolute;top:-2%;bottom:-2%;left:0;width:3px;
  background:linear-gradient(180deg,transparent,#eafdff 14%,var(--cyan,#34E0F0) 50%,
                             #eafdff 86%,transparent);
  box-shadow:0 0 30px 7px rgba(52,224,240,.72);
  animation:ozWipeLine .42s cubic-bezier(.36,0,.26,1) both;
}
/* tapped on the right half: it crosses the other way */
.oz-wipe.ozw-r::before{animation-name:ozWipeLineR}
@keyframes ozWipe{
  0%{background:rgba(9,14,26,0)}
  60%{background:rgba(9,14,26,.34)}
  100%{background:rgba(9,14,26,.5)}
}
@keyframes ozWipeLine{0%{transform:translateX(-6vw)}100%{transform:translateX(106vw)}}
@keyframes ozWipeLineR{0%{transform:translateX(106vw)}100%{transform:translateX(-6vw)}}

/* ---------- THE THREE LEVELS -----------------------------------------------
 *
 * Owner, 16 Sep 2026: «عايزه ديماً يكون الانيميشن شغال بس الشخص يقدر يخليه
 * اقل شوية او يطفيه خالص وهكذا».
 *
 *   full   everything. THE DEFAULT, for everybody, on every device.
 *   less   quieter: nothing travels, spins, zooms or strobes, but every
 *          moment still happens — see the block below.
 *   off    nothing moves at all.
 *
 * WHAT CHANGED, AND WHY IT IS HIS CALL. This used to key off the system's
 * `prefers-reduced-motion`, which sounds right and is not: iOS sets it for
 * LOW POWER MODE and Windows for one "Animation effects" toggle, so it was
 * answering for players who had never been asked — the owner included, on two
 * separate devices, which is how the whole layer came to be invisible to him
 * twice in one day. A guess made by the machine is now the thing we ignore,
 * and a choice made by the person is the thing we keep.
 *
 * THE COST, STATED PLAINLY: somebody whose vestibular system genuinely cannot
 * take motion now meets it once before they can turn it down. That is why the
 * control is in the account menu on every page rather than buried, why it is
 * three named steps and not a checkbox, and why "off" is a real level that
 * stops everything rather than a quieter one.
 *
 * ONE TRAP, and it is why the reveals below are not !important: an
 * !important declaration outranks a CSS animation. `opacity:1!important`
 * here would silently beat every fade this block adds, which is the same
 * shape of bug as the one it is fixing.
 */

/* ---------- LEVEL "less" --------------------------------------------------
 * Every moment still happens; only the movement in it goes. The rule that
 * earned this block: what is left has to MEAN something without motion. A
 * seam is the light between two parting doors, so with nothing parting it is
 * a stripe down the middle of the screen — «هو خط في نص الصفحة بس». Leftovers
 * are not a quieter version.
 */

/* The real triggers — and ONLY these come off. */
html[data-oz-motion="less"] .oz-sheen::before{display:none!important}                /* a band crossing a card   */
html[data-oz-motion="less"] .oz-sheen:hover::before,
html[data-oz-motion="less"] .oz-sheen:focus-visible::before{animation:none!important}

/* Reveals still arrive; they just no longer rise. The base stays visible, so
   a block whose class never lands is still readable — the blank-hero rule. */
html[data-oz-motion="less"] .oz-rise,
html[data-oz-motion="less"] .oz-stagger>*{opacity:1;transform:none!important;transition:none!important}
html[data-oz-motion="less"] .oz-rise.oz-in,
html[data-oz-motion="less"] .oz-stagger.oz-in>*{animation:ozFadeIn .45s linear both}
html[data-oz-motion="less"] .oz-stagger.oz-in>*:nth-child(2){animation-delay:.06s}
html[data-oz-motion="less"] .oz-stagger.oz-in>*:nth-child(3){animation-delay:.12s}
html[data-oz-motion="less"] .oz-stagger.oz-in>*:nth-child(4){animation-delay:.18s}
html[data-oz-motion="less"] .oz-stagger.oz-in>*:nth-child(5){animation-delay:.24s}
html[data-oz-motion="less"] .oz-stagger.oz-in>*:nth-child(n+6){animation-delay:.30s}

/* The page still hands over: a veil that comes up, not a band that crosses. */
html[data-oz-motion="less"] .oz-wipe::before{display:none!important}   /* a line crossing the screen IS travel */
html[data-oz-motion="less"] .oz-wipe{
  background:linear-gradient(180deg,rgba(9,14,26,.42),rgba(9,14,26,.66))!important;
  animation:ozVeil .3s linear both!important;
}

/* THE VEIL LIFTS. That is the whole quiet version, and it is deliberately
   less than the first attempt at this block.

   Owner, 16 Sep, looking at that first attempt: «الأنيميشن بتاع اللوجين مش
   كامل هو خط في نص الصفحة بس ومبيلحقش يعمل اي انيميشن وبيخش». He was right,
   and it is the SAME fault he named on 15 Sep («الباب مكانه غلط انت حاطه في
   النص»): a bright line down the middle of the screen.

   The seam is the light BETWEEN TWO PARTING DOORS. With nothing parting
   there is no gap for it to be in, so it stops being an effect and becomes a
   stripe drawn across the page for no reason — and the same is true of a
   boot striking nothing and a flash with no cause. Bringing all three back
   for a reader who gets no movement was showing them the leftovers of an
   animation instead of a quieter animation.

   So what is left is the one thing that still means something without
   movement: the card recedes, and the two leaves fade a beat apart so the
   sheet reads as two panels rather than one. Nothing is drawn in the middle
   of the screen at any point. */
/* A WAIT IS NOT A MOMENT, so there is nothing here to play quietly: the mark
   is drawn at rest and the word beside it says what is happening. Repeating
   animations are the one thing this level most plainly forbids. */
html[data-oz-motion="less"] .oztune span{animation:none!important;height:9px;opacity:.7}
html[data-oz-motion="less"] .oztune i{animation:none!important;opacity:.55}

/* The count still counts and the word still lands; nothing is thrown at
   anybody. The numerals swap on the same clock and the band simply is. */
/* A name still ARRIVES in its slot; it just does not fall into it. And the
   lock still opens — the shackle lifting is the whole information — while
   the pop around it goes. */
/* The rank still lands and the refusal still reads as one — the badge
   arrives without falling, and the message is answered by light rather than
   by being shaken about. */
/* Nothing spins for somebody who asked for less. The sweep holds still and
   the ring stays, so the map still reads as a live one. */
html[data-oz-motion="less"] .ozradar i{animation:none!important;opacity:.5}

html[data-oz-motion="less"] .ozrank{animation:ozFadeIn .4s linear both!important}
html[data-oz-motion="less"] .ozrank::after{display:none!important}
html[data-oz-motion="less"] .oz-glitch{animation:ozHeldCalm .5s linear both!important}

html[data-oz-motion="less"] .ozdrop{animation:ozFadeIn .34s linear both!important}
html[data-oz-motion="less"] .ozlock svg{animation:ozFadeIn .3s linear both!important}
html[data-oz-motion="less"] .oz-got{animation:ozGot .8s ease-out both!important}

html[data-oz-motion="less"] .ozcount b{animation:ozFadeIn .2s linear both!important}
html[data-oz-motion="less"] .ozband b{animation:ozFadeIn .34s linear both!important}
html[data-oz-motion="less"] .ozband b::before{animation:none!important;transform:scaleX(0)!important}

html[data-oz-motion="less"] .oz-held{animation:ozHeldCalm .5s linear both!important}
/* THE DOOR STILL OPENS. Nothing swings and nobody travels: the leaf goes by
   going, the light behind it comes up on the same clock, and the person is
   simply no longer standing there. The RESULT is identical, which is the whole
   rule for this level — and the reason the caller waits exactly as long. */
html[data-oz-motion="less"] .ozdoor.oz-run .ozdoor-leaf{animation:ozDoorFade .38s linear both!important}
html[data-oz-motion="less"] .ozdoor.oz-run .ozdoor-man{animation:ozDoorFade .38s linear both!important}
html[data-oz-motion="less"] .ozdoor.oz-run .ozdoor-lite{animation:ozFadeIn .38s linear both!important}
html[data-oz-motion="less"] .ozdoor.oz-run .ozdoor-knob{animation:ozDoorFade .2s linear both!important}
/* ...and the way out, the same way round: the leaf arrives instead of
   swinging back, and the light goes. */
html[data-oz-motion="less"] .ozdoor.oz-shut .ozdoor-leaf{animation:ozFadeIn .34s linear both!important}
html[data-oz-motion="less"] .ozdoor.oz-shut .ozdoor-lite{animation:ozDoorFade .34s linear both!important}
/* the glow and the click are light, not movement, so they stay as they are.
   The scan line TRAVELS, so at this level the card is simply lit once. */
html[data-oz-motion="less"] .ozscan i{animation:ozFadeIn .3s linear both!important;
  top:0;bottom:0;height:auto!important;opacity:.14}

/* Numerals, live marks and the settle: colour and light, never scale.
   .oz-up/.oz-down are pure colour keyframes and were being switched off for
   no reason at all — a score going green is information, not decoration. */
html[data-oz-motion="less"] .oz-lock{animation:ozLockCalm .34s linear both!important}
/* NOTHING HERE RUNS FOREVER. Owner, 16 Sep: «الموقع بقا تقيل» — and the
   cause was two rules in this very block, which had been given `infinite`
   pulses on the argument that a live mark should still say it is live. On a
   wall or a roster that is dozens of elements repainting for as long as the
   page is open, on the machines LEAST able to afford it, and it is the one
   thing this preference most clearly asks not to happen: a repeating
   animation nobody can stop. A live dot is already a coloured dot. */
html[data-oz-motion="less"] .oz-live{animation:none!important}
html[data-oz-motion="less"] .oz-acquire{animation:ozFadeIn .5s linear both!important}
html[data-oz-motion="less"] .oz-enter{animation:ozEnterCalm .4s linear both!important}
html[data-oz-motion="less"] .oz-lockon::before,
html[data-oz-motion="less"] .oz-lockon::after{animation:ozFadeIn .4s linear both!important}
html[data-oz-motion="less"] .oz-skel::after{animation:none!important}

/* A press still answers — with light, rather than a squeeze. */
html[data-oz-motion="less"] .oz-press,
html[data-oz-motion="less"] .oz-lift{transition:filter var(--oz-fast) linear!important}
html[data-oz-motion="less"] .oz-press:active,
html[data-oz-motion="less"] .oz-lift:hover{transform:none!important;filter:brightness(1.22)}

/* ---------- LEVEL "off" ---------------------------------------------------
 * Nothing moves. Not a quieter version — the absence, on purpose, because
 * somebody asked for it in as many words.
 *
 * It is written against OUR OWN class names rather than as a blanket
 * `*{animation:none}` for two reasons: a universal rule would also stop
 * things that are not decoration (a spinner saying the network is working, a
 * video), and it would fight every page's own transitions instead of turning
 * off this layer. The layer switches itself off; it does not switch the site
 * off.
 *
 * The RESULT of each moment is kept, which is the difference between "off"
 * and "broken": revealed content is visible, a number shows its new value, a
 * door that has opened is gone. Only the travel between states is removed.
 */
html[data-oz-motion="off"] .oz-rise,
html[data-oz-motion="off"] .oz-stagger>*{opacity:1!important;transform:none!important;
  transition:none!important;animation:none!important}
html[data-oz-motion="off"] .oz-lock,
html[data-oz-motion="off"] .oz-live,
html[data-oz-motion="off"] .oz-up,
html[data-oz-motion="off"] .oz-down,
html[data-oz-motion="off"] .oz-enter,
html[data-oz-motion="off"] .oz-acquire,
html[data-oz-motion="off"] .oz-held,
html[data-oz-motion="off"] .oz-skel::after,
html[data-oz-motion="off"] .oz-lockon::before,
html[data-oz-motion="off"] .oz-lockon::after{animation:none!important;transform:none!important}
/* THE DOOR IS A DRAWING, NOT A MOVEMENT, so it stays on the button at "off"
   exactly as it is — shut, with its handle and the person at it. What goes is
   the opening: nothing runs, nothing is drawn at the finger on the way out,
   and the card closes at once. */
html[data-oz-motion="off"] .ozdoor .ozdoor-leaf,
html[data-oz-motion="off"] .ozdoor .ozdoor-lite,
html[data-oz-motion="off"] .ozdoor .ozdoor-man,
html[data-oz-motion="off"] .ozdoor .ozdoor-knob,
html[data-oz-motion="off"] .ozdoor{animation:none!important}
/* "off" keeps the information and drops every animation: the numbers appear
   and go on their own clock, and the winning word is simply written. */
html[data-oz-motion="off"] .ozradar{display:none!important}
html[data-oz-motion="off"] .ozrank{animation:none!important}
html[data-oz-motion="off"] .ozrank::after{display:none!important}
html[data-oz-motion="off"] .oz-glitch{animation:none!important}
html[data-oz-motion="off"] .ozdrop{animation:none!important}
html[data-oz-motion="off"] .oz-got{animation:none!important}
html[data-oz-motion="off"] .ozcount b{animation:none!important;opacity:1}
html[data-oz-motion="off"] .ozband b{animation:none!important;opacity:1}
html[data-oz-motion="off"] .ozband b::before{display:none!important}
html[data-oz-motion="off"] .oztune span{animation:none!important;height:9px;opacity:.7}
html[data-oz-motion="off"] .oztune i{animation:none!important;opacity:.55}
html[data-oz-motion="off"] .oz-sheen::before,
html[data-oz-motion="off"] .oz-wipe,
html[data-oz-motion="off"] .ozdoor-fly{display:none!important}
html[data-oz-motion="off"] .oz-press,
html[data-oz-motion="off"] .oz-lift{transition:none!important}
html[data-oz-motion="off"] .oz-press:active,
html[data-oz-motion="off"] .oz-lift:hover{transform:none!important}


/* The quiet forms. Defined once, used only by the floor above (§3.10). */
@keyframes ozFadeIn{from{opacity:0}to{opacity:1}}
@keyframes ozVeil{from{opacity:0}to{opacity:1}}
@keyframes ozCardOut{from{opacity:1}to{opacity:0}}
@keyframes ozHeldCalm{0%,100%{filter:none}30%{filter:brightness(1.35) saturate(1.5)}}
@keyframes ozLockCalm{0%{filter:brightness(1.9)}100%{filter:brightness(1)}}
@keyframes ozEnterCalm{from{opacity:.6}to{opacity:1}}

/* ---- oz-blip: one person on a map, drawn the same way everywhere -----------
 *
 * Owner, 9 Aug: the profile picture and the name, on every surface — the radio
 * map, the stream overlay, /where and the app — not a coloured dot.
 *
 * The markup comes from OZUI.mapBlip so there is one renderer; these are its
 * styles, here because this is the stylesheet every page already loads. The
 * caller positions the .oz-blip; everything inside it is fixed so a person
 * looks identical on a phone, a wall and a stream.
 */
.oz-blip{position:absolute;transform:translate(-50%,-50%);
  display:flex;flex-direction:column;align-items:center;gap:3px;pointer-events:none}
.oz-blip-face{width:30px;height:30px;border-radius:50%;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  font:800 13px/1 Orbitron,system-ui,sans-serif;color:#04121a;
  background:#E8EEF6;border:2px solid #E8EEF6;
  box-shadow:0 2px 8px rgba(0,0,0,.55)}
.oz-blip-face img{width:100%;height:100%;object-fit:cover;display:block}
.oz-blip.red  .oz-blip-face{border-color:#FF5A76;box-shadow:0 0 0 2px #ff5a7644,0 2px 8px rgba(0,0,0,.55)}
.oz-blip.blue .oz-blip-face{border-color:#4F8CFF;box-shadow:0 0 0 2px #4f8cff44,0 2px 8px rgba(0,0,0,.55)}
.oz-blip.me   .oz-blip-face{border-color:#34E0F0;box-shadow:0 0 0 3px #34e0f055,0 2px 10px rgba(0,0,0,.6)}
.oz-blip-name{font:700 10px/1 Rajdhani,system-ui,sans-serif;color:#E8EEF6;
  text-shadow:0 1px 3px #000;white-space:nowrap;max-width:96px;
  overflow:hidden;text-overflow:ellipsis}
/* A name is a person's, so it never letter-spaces in Arabic (§3.8). */
:lang(ar) .oz-blip-name,[dir="rtl"] .oz-blip-name{letter-spacing:normal}
