/* ════════════════════════════════════════════
   ZEENTECH SHARED THEME
   Color schemes (html[data-theme]), ambient glow,
   theme switcher chrome, desert scene + clouds.
   Page-specific layout/content styles stay inline in each page.
   ════════════════════════════════════════════ */

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

/* ── ORIGINAL — Desert Monastery (default) ── */
html[data-theme="original"]{
  /* Tells native controls (date/time pickers, their icons/popovers) to use dark-mode
     chrome instead of assuming a light page — without this, e.g. a datetime-local
     input's calendar icon and time segments render for a light background and become
     hard to see/use against this theme's dark surfaces. */
  color-scheme:dark;
  --bg:#080604; --bg2:#0F0A04;
  --surface:rgba(14,10,4,.92); --card:rgba(26,18,6,.80); --card-solid:rgba(26,18,6,.96);
  --border:#3A2810; --border2:#5A3E18;
  --glow:#E07B00; --glow2:#F5A020; --glow-dim:#8B4A00;
  --gold:#C9A84C; --sand:#C4B48C; --sand-dim:#7A6A4C;
  --glow-shadow:0 0 18px #E07B00, 0 0 40px rgba(224,123,0,.3);
  --node-shadow:0 0 14px rgba(201,168,76,.6); --node-shadow2:0 0 28px rgba(201,168,76,.9);
  --ok:#8BB836; --warn:#E0A020; --err:#C0392B;
  --sky:transparent;
  --cloud:rgba(196,180,140,.18); --cloud-edge:rgba(196,180,140,.30);
  --palm-trunk:#5A3E18; --palm-frond:#3A7A4A;
  --cactus:#3A7A4A; --cactus-dim:#2A5A36;
  --camel:#C9A84C; --camel-dim:#8B6A2C;
  --ground:#1A1206; --ground2:#241808; --ground-edge:#3A2810;
  --swatch:#E07B00;
}

/* ── ORIGINAL GREEN — lightened earth-green ── */
html[data-theme="original-green"]{
  color-scheme:dark;
  --bg:#141A0E; --bg2:#1C240F;
  --surface:rgba(28,36,15,.92); --card:rgba(36,46,18,.80); --card-solid:rgba(36,46,18,.96);
  --border:#2A3818; --border2:#4A5E28;
  --glow:#8BB836; --glow2:#A8D44E; --glow-dim:#4A6A1C;
  --gold:#D8B85C; --sand:#CAC8A2; --sand-dim:#8A8A5C;
  --glow-shadow:0 0 18px #8BB836, 0 0 40px rgba(139,184,54,.3);
  --node-shadow:0 0 14px rgba(216,184,92,.6); --node-shadow2:0 0 28px rgba(216,184,92,.9);
  --ok:#8BB836; --warn:#D8B85C; --err:#C0392B;
  --sky:transparent;
  --cloud:rgba(202,200,162,.18); --cloud-edge:rgba(202,200,162,.32);
  --palm-trunk:#5A4E28; --palm-frond:#8BB836;
  --cactus:#7AA82C; --cactus-dim:#5A7E1C;
  --camel:#D8B85C; --camel-dim:#9A8240;
  --ground:#1A2410; --ground2:#243012; --ground-edge:#3A4A1C;
  --swatch:#8BB836;
}

/* ── DESERT WARMTH — chocolate + sand gold (light) ── */
html[data-theme="desert-warmth"]{
  color-scheme:light;
  --bg:#FDF8F2; --bg2:#F5EBDD;
  --surface:rgba(255,255,255,.75); --card:rgba(255,255,255,.65); --card-solid:rgba(253,248,242,.96);
  --border:#D8C4A8; --border2:#B89668;
  --glow:#A8651F; --glow2:#C9802E; --glow-dim:#8B5E3C;
  --gold:#A87A1E; --sand:#4E342E; --sand-dim:#8B6B4C;
  --glow-shadow:none;
  --node-shadow:0 0 10px rgba(168,122,30,.4); --node-shadow2:0 0 18px rgba(168,122,30,.6);
  --ok:#5E7E3C; --warn:#A8651F; --err:#A83226;
  --sky:transparent;
  --cloud:rgba(255,255,255,.9); --cloud-edge:rgba(184,150,104,.55);
  --palm-trunk:#8B5E3C; --palm-frond:#6B8E4E;
  --cactus:#7A9B54; --cactus-dim:#5E7E3C;
  --camel:#A87545; --camel-dim:#7A4F2C;
  --ground:#EADAC0; --ground2:#DBC8A4; --ground-edge:#C4A878;
  --swatch:#8B5E3C;
}

/* ── CLOUD NEUTRAL — Pantone 2026 warm off-white (light) ── */
html[data-theme="cloud-neutral"]{
  --bg:#F0EEE9; --bg2:#E7E4DD;
  --surface:rgba(255,255,255,.78); --card:rgba(255,255,255,.68); --card-solid:rgba(240,238,233,.97);
  --border:#D5D2CA; --border2:#B8B4AA;
  --glow:#3D3D3D; --glow2:#5A5A5A; --glow-dim:#8A8A8A;
  --gold:#1E4CA1; --sand:#1A1A1A; --sand-dim:#6B6B6B;
  --glow-shadow:none;
  --node-shadow:0 0 10px rgba(30,76,161,.35); --node-shadow2:0 0 18px rgba(30,76,161,.5);
  --ok:#3D6E3D; --warn:#1E4CA1; --err:#A83226;
  --sky:transparent;
  --cloud:rgba(255,255,255,.95); --cloud-edge:rgba(184,180,170,.6);
  --palm-trunk:#9A8E7A; --palm-frond:#7A8B6E;
  --cactus:#8A9B7E; --cactus-dim:#6E7E62;
  --camel:#A8A296; --camel-dim:#7E786C;
  --ground:#E4E1D9; --ground2:#D6D2C8; --ground-edge:#C2BEB2;
  --swatch:#1E4CA1;
}

/* ── QATAR — GCO maroon + gold (light) ── */
html[data-theme="qatar"]{
  --bg:#F4F1EC; --bg2:#EAE5DD;
  --surface:rgba(255,255,255,.78); --card:rgba(255,255,255,.68); --card-solid:rgba(244,241,236,.97);
  --border:#E2CDD4; --border2:#C9A0AC;
  --glow:#8A1538; --glow2:#A8244A; --glow-dim:#6E1029;
  --gold:#A87A1E; --sand:#2A0A12; --sand-dim:#8A5560;
  --glow-shadow:none;
  --node-shadow:0 0 10px rgba(138,21,56,.35); --node-shadow2:0 0 18px rgba(138,21,56,.5);
  --ok:#5E7E3C; --warn:#A8651F; --err:#A83226;
  --sky:transparent;
  --cloud:rgba(255,255,255,.95); --cloud-edge:rgba(201,160,172,.55);
  --palm-trunk:#8B5E3C; --palm-frond:#6B8E4E;
  --cactus:#7A9B54; --cactus-dim:#5E7E3C;
  --camel:#B58A3A; --camel-dim:#8A6420;
  --ground:#EADAC0; --ground2:#DBC8A4; --ground-edge:#C9A8B0;
  --swatch:#8A1538;
}

/* ════════════════════════════════════════════ */

:root{
  /* Display font: headers/labels/buttons — short, blocky, on-brand.
     Body font: anything read at length (form fields, paragraphs, notes) — adopted from
     the session wizard (local/features/04_session_wizard), which splits the two instead
     of setting monospace everywhere. Not yet applied to every page — see each page's
     inline <style> for what opts in via var(--font-body). */
  --font-display:'Press Start 2P',monospace;
  --font-body:'Inter',sans-serif;
}

html,body{height:100%;}
body{
  background:var(--bg);
  color:var(--sand);
  font-family:'Share Tech Mono',monospace;
  transition:background .4s ease, color .4s ease;
}

/* ambient glow behind content */
.ambient{
  position:fixed; top:46%; left:50%; transform:translate(-50%,-50%);
  width:600px; height:600px;
  background:radial-gradient(ellipse at center, var(--glow) 0%, transparent 70%);
  opacity:.08; pointer-events:none; z-index:0;
  animation:breathe 4s ease-in-out infinite;
}
@keyframes breathe{0%,100%{opacity:.06;}50%{opacity:.12;}}

/* ── THEME SWITCHER (top-right) ── */
.switcher{
  position:fixed; top:16px; right:16px; z-index:200;
  background:var(--surface); border:2px solid var(--border2);
  padding:10px 12px;
}
.switcher-label{
  font-family:'Press Start 2P',monospace; font-size:6px;
  color:var(--sand-dim); letter-spacing:.12em; margin-bottom:9px;
}
.swatches{display:flex; gap:7px;}
.swatch{
  width:18px; height:18px; cursor:pointer; padding:0;
  border:2px solid var(--border2); background:var(--sw);
  transition:transform .12s, box-shadow .12s;
}
.swatch:hover{transform:translateY(-2px);}
.swatch.active{
  border-color:var(--glow);
  box-shadow:0 0 0 2px var(--bg), 0 0 10px var(--glow);
}
.switcher-name{
  font-family:'Press Start 2P',monospace; font-size:6px;
  color:var(--glow); letter-spacing:.08em; margin-top:9px; min-height:8px;
}

/* ── NAV LINK — shared chrome, reused as: plain nav-bar buttons on public pages, and
   both the menu toggle button + each entry in the dropdown list on internal pages ── */
.nav-link{
  font-family:'Press Start 2P',monospace; font-size:7px;
  color:var(--sand-dim); letter-spacing:.1em;
  background:var(--surface); border:2px solid var(--border2);
  padding:10px 14px; text-decoration:none;
  transition:color .2s, border-color .2s;
}
.nav-link:hover{color:var(--glow); border-color:var(--glow);}

/* ── NAV BAR (top-left) — plain row of buttons, public pages only ── */
.nav-bar{
  position:fixed; top:16px; left:16px; z-index:200;
  display:flex; gap:8px;
}

/* ── TOP-LEFT BAR — wraps the nav menu + (on pages that have one) the notification
   bell, so they lay out as a row instead of two independently-guessed fixed-position
   elements that can end up overlapping (see the top-right switcher/bell collision this
   replaced the pattern for). ── */
.top-left-bar{position:fixed; top:16px; left:16px; z-index:200; display:flex; align-items:flex-start; gap:8px;}

/* ── NAV MENU — a dropdown of every page reachable from here, internal pages only, so
   no admin tool is a dead end; see www/js/nav-menu.js for the open/close behavior.
   Positioned by its `.top-left-bar` wrapper now, not itself — `position:relative` is
   just so its dropdown list (`position:absolute`) anchors correctly. ── */
.nav-menu{position:relative;}
.nav-menu-btn{cursor:pointer;}
.nav-menu.open .nav-menu-btn{color:var(--glow); border-color:var(--glow);}
.nav-menu-list{
  display:none; flex-direction:column; gap:6px;
  position:absolute; top:calc(100% + 8px); left:0; min-width:190px;
}
.nav-menu.open .nav-menu-list{display:flex;}
/* The menu is identical on every page in its group (public vs internal) — this just
   marks which entry is the page you're already on, rather than omitting it. */
.nav-menu-current{color:var(--gold); border-color:var(--gold); cursor:default;}
.nav-menu-current:hover{color:var(--gold); border-color:var(--gold);}

/* ── NOTIFICATION CENTER (bell + dropdown) — a `.top-left-bar` flex item, next to the
   nav menu. Shared by booking-admin.html, admin.html, brainstorm.html (was
   booking-admin.html-only, duplicated-then-diverged risk if it stayed that way). Each
   page's own script decides when to un-hide `#notifBell` (after login) and drives
   ZeenBooking.getNotifications()/renderNotifications(). ── */
.notif-bell{
  background:var(--surface); border:2px solid var(--border2); color:var(--sand-dim);
  font-family:'Press Start 2P',monospace; font-size:12px; cursor:pointer;
  padding:9px 12px; line-height:1;
}
.notif-bell:hover{border-color:var(--glow); color:var(--glow);}
.notif-bell.has-items{border-color:var(--warn); color:var(--warn);}
.notif-count{
  display:inline-block; margin-left:6px;
  font-family:'Press Start 2P',monospace; font-size:8px; color:var(--bg);
  background:var(--warn); min-width:14px; height:14px; line-height:14px; text-align:center;
  border-radius:50%; vertical-align:middle;
}
/* Anchored to `.top-left-bar` (its nearest positioned ancestor), left-aligned to it —
   the bar sits near the viewport's left edge, so right-aligning a 300px panel to a
   ~150px-wide bar would push most of it off-screen (as happened here once already).
   Left-aligning means it always extends rightward into the page instead. */
.notif-panel{
  position:absolute; top:calc(100% + 8px); left:0; width:300px; max-height:340px; overflow-y:auto;
  background:var(--surface); border:2px solid var(--border2); padding:10px;
}
.notif-empty{font-family:var(--font-body); font-size:12px; color:var(--sand-dim); padding:8px 4px;}
.notif-row{
  border:1px solid var(--border); padding:10px; margin-bottom:8px; display:flex;
  flex-direction:column; gap:8px;
}
.notif-row:last-child{margin-bottom:0;}
.notif-main{display:flex; flex-direction:column; gap:4px; font-family:var(--font-body); font-size:12px; color:var(--sand);}
.notif-when{font-size:11px; color:var(--glow-dim); letter-spacing:.03em;}
.notif-who{font-size:13px;}
.notif-tag{
  align-self:flex-start; font-size:9px; letter-spacing:.05em; padding:2px 6px; margin-top:2px;
}
.notif-tag-assigned{color:var(--glow); border:1px solid var(--glow);}
.notif-tag-open{color:var(--warn); border:1px solid var(--warn);}
.notif-confirm-btn{
  align-self:flex-start; background:none; border:2px solid var(--border2); color:var(--sand-dim);
  font-family:var(--font-body); font-size:12px; cursor:pointer; padding:5px 10px;
  transition:border-color .15s, color .15s;
}
.notif-confirm-btn:hover{border-color:var(--glow); color:var(--glow);}
@media(max-width:600px){
  .notif-panel{width:calc(100vw - 96px);}
}

/* ── TOAST — themed replacement for alert()/confirm(), so a "your action worked" message
   reads like the rest of the site instead of a bare browser dialog. See www/js/toast.js
   for the show()/confirm() API; markup is created on demand, not hardcoded per page. ── */
.zt-toast-stack{
  position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); z-index:500;
  display:flex; flex-direction:column; gap:10px; align-items:center;
  pointer-events:none;
}
.zt-toast{
  pointer-events:auto; display:flex; align-items:center; gap:12px;
  max-width:360px; background:var(--surface); border:2px solid var(--border2);
  padding:16px 20px; font-family:var(--font-body); font-size:14px; color:var(--sand);
  box-shadow:0 10px 32px rgba(0,0,0,.45);
  opacity:0; transform:scale(.94); transition:opacity .2s, transform .2s;
}
.zt-toast.in{opacity:1; transform:scale(1);}
.zt-toast-icon{
  flex:none; width:22px; height:22px; display:flex; align-items:center; justify-content:center;
  font-family:'Press Start 2P',monospace; font-size:11px; border:2px solid currentColor;
}
.zt-toast-ok{border-color:var(--ok); color:var(--ok);}
.zt-toast-error{border-color:var(--err); color:var(--err);}
.zt-toast-msg{flex:1; line-height:1.5;}
.zt-toast-close{
  flex:none; background:none; border:none; color:var(--sand-dim); cursor:pointer;
  font-family:var(--font-body); font-size:16px; line-height:1; padding:2px;
}
.zt-toast-close:hover{color:var(--sand);}
@media(max-width:520px){
  .zt-toast-stack{width:calc(100vw - 32px);}
  .zt-toast{max-width:none;}
}

/* ── CONFIRM DIALOG — themed replacement for window.confirm(). See ZeenToast.confirm() in
   www/js/toast.js; returns a Promise<boolean>, so this is used from async handlers. ── */
.zt-confirm-backdrop{
  position:fixed; inset:0; z-index:600; background:rgba(0,0,0,.55);
  display:flex; align-items:center; justify-content:center;
  opacity:0; transition:opacity .2s;
}
.zt-confirm-backdrop.in{opacity:1;}
.zt-confirm{
  max-width:380px; width:calc(100vw - 48px); background:var(--surface); border:2px solid var(--border2);
  padding:24px; box-shadow:0 10px 32px rgba(0,0,0,.45);
  transform:scale(.94); transition:transform .2s;
}
.zt-confirm-backdrop.in .zt-confirm{transform:scale(1);}
.zt-confirm-msg{font-family:var(--font-body); font-size:14px; color:var(--sand); line-height:1.5; margin-bottom:20px;}
.zt-confirm-actions{display:flex; justify-content:flex-end; gap:10px;}
.zt-confirm-btn{
  background:var(--surface); border:2px solid var(--border2); color:var(--sand-dim);
  font-family:var(--font-body); font-size:13px; padding:8px 16px; cursor:pointer;
  transition:border-color .15s,color .15s;
}
.zt-confirm-cancel:hover{border-color:var(--glow); color:var(--glow);}
.zt-confirm-ok{border-color:var(--err); color:var(--err);}
.zt-confirm-ok:hover{background:var(--err); color:var(--bg);}

/* ── blinking status dot, reused across pages ── */
@keyframes blink{0%,100%{opacity:1;}50%{opacity:0;}}

/* ── SOLID CARD — opt-in modifier for a `.step` that's dense/large (the month calendar is
   the main case): the default `--card` is deliberately translucent so the desert scene
   shows through, which reads as clutter on the biggest, busiest card on the page. Add this
   class alongside `.step` just on that one to make it read solid without touching `--card`
   everywhere else. ── */
.step-solid{background:var(--card-solid);}

/* ── MONTH CALENDAR — shared by www/booking.html (public) and www/booking-admin.html
   (admin); was duplicated verbatim in both pages' inline <style>, now defined once here.
   Page-specific bits (admin's per-day booking-count badge) stay inline in that page. ── */
.cal-header{display:flex; justify-content:space-between; align-items:center; margin-bottom:14px;}
.cal-month-label{
  font-family:'Press Start 2P',monospace; font-size:9px;
  color:var(--sand); letter-spacing:.1em;
}
.cal-nav-btn{
  background:var(--surface); border:2px solid var(--border2); color:var(--sand-dim);
  font-family:var(--font-body); font-size:11px; letter-spacing:.02em;
  padding:8px 12px; cursor:pointer; transition:border-color .15s, color .15s;
}
.cal-nav-btn:hover{border-color:var(--glow); color:var(--glow);}
.cal-weekdays{display:grid; grid-template-columns:repeat(7,1fr); gap:6px; margin-bottom:6px;}
.cal-weekday{
  font-family:'Press Start 2P',monospace; font-size:6px;
  color:var(--sand-dim); text-align:center; letter-spacing:.05em; padding:4px 0;
}
.cal-weekday.off{color:var(--border2);}
.cal-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:6px;}
.cal-cell{
  position:relative; aspect-ratio:4/3; display:flex; flex-direction:column; align-items:center; justify-content:center;
  background:var(--surface); border:2px solid var(--border2); color:var(--sand);
  font-family:var(--font-body); cursor:pointer; padding:4px;
  transition:border-color .15s, transform .12s;
}
.cal-cell:hover:not(.blank):not(:disabled){transform:translateY(-2px); border-color:var(--glow);}
.cal-cell.blank{visibility:hidden; cursor:default; border:none; background:none;}
.cal-cell.active{border-color:var(--glow); box-shadow:0 0 0 1px var(--glow);}
/* Past/non-working cells get a distinct muted fill (not just dimmed opacity on the same
   background) so a mostly-empty month reads as "many quiet cells", not "a wall of
   identical boxes" — see local/features/02_booking (calendar overflow discussion). */
.cal-cell.off,.cal-cell.past{background:var(--ground2); border-color:var(--border); opacity:.6;}
.cal-cell.today .cal-daynum{color:var(--gold);}
.cal-daynum{font-size:13px;}
/* Status is color AND shape, not color alone: open = green circle, fully booked = amber square. */
.cal-dot{width:7px; height:7px; margin-top:3px;}
.cal-dot.open{background:var(--ok); box-shadow:0 0 6px var(--ok); border-radius:50%;}
.cal-dot.full{background:var(--warn); border-radius:1px;}
@media(max-width:520px){
  .cal-daynum{font-size:10px;}
  .cal-weekday{font-size:5px;}
}

/* ── DESERT SCENE (pixel decorations, bottom) ── */
.scene{position:fixed; left:0; right:0; bottom:0; height:230px; z-index:1; pointer-events:none; overflow:hidden;}
.scene svg{image-rendering:pixelated; position:absolute;}
/* Dunes sit behind the sprites regardless of DOM order (the markup lists dunes last, after
   the camels, so it needs an explicit lower z-index or it paints over them and buries
   whichever camel happens to be walking through the near dune's silhouette). */
.dunes{left:0; bottom:0; width:100%; height:130px; z-index:1;}
.dunes .d-back{fill:var(--ground2);}
.dunes .d-front{fill:var(--ground);}
.dunes .d-edge{fill:var(--ground-edge);}

.sprite{position:absolute; z-index:2;}
/* Invisible full-viewBox rect on each clickable sprite (see the palm/camel markup) so the
   whole bounding box is a hit target — SVG only hit-tests painted pixels by default, and a
   handful of thin trunk/leg/neck rects on a mostly-transparent canvas made triple/double
   clicks miss depending on exactly where on the tree/camel you clicked. fill:transparent
   (not `none`) keeps it counted as "painted" for hit-testing while staying invisible. */
.hit-target{fill:transparent;}
.s-trunk{fill:var(--palm-trunk);}
.s-frond{fill:var(--palm-frond);}
.s-cactus{fill:var(--cactus);}
.s-cactus-d{fill:var(--cactus-dim);}
.s-camel{fill:var(--camel);}
.s-camel-d{fill:var(--camel-dim);}

.palm-left{left:4%; bottom:78px; width:78px;}
.palm-right{right:6%; bottom:84px; width:64px;}
.cactus-1{left:24%; bottom:70px; width:34px;}

/* Trees are hidden-gem click targets (see local/features/06_desert_scene_animations) —
   the .scene wrapper stays pointer-events:none so the decoration never blocks page
   interaction, and only these specific sprites opt back in. */
.palm-left,.palm-right,.camel-1,.camel-2{pointer-events:auto; cursor:pointer;}

/* Camels walk left-to-right across the scene at a constant linear speed (same idea as the
   clouds' drift). Both camels share the exact same walk duration so their time offset
   (animation-delay) stays a fixed gap forever instead of drifting — that's what keeps them
   evenly spaced instead of slowly catching up to or lapping one another. Different
   sizes/heights/bob speeds still read as a little caravan rather than clones.
   Body bob and leg lift both use steps() rather than smooth easing — a blocky pixel-art
   sprite gliding with ease-in-out reads as floating/eerie, not walking; snapping between
   discrete positions (2 dips per cycle, matching each diagonal leg pair's footfall) reads
   as an actual gait.
   animation-name/-duration/-timing-function/-iteration-count/-delay are declared as
   longhand lists (rather than the `animation` shorthand) so the .is-flying variant below can
   add a 3rd (camel-fly) animation without restarting these two — see that comment. */
.camel-1,.camel-2{
  animation-name:bob, camel-walk;
  animation-timing-function:steps(1,jump-end), linear;
  animation-iteration-count:infinite, infinite;
}
.camel-1{bottom:72px; width:96px; animation-duration:1.4s, 96s;}
.camel-2{bottom:52px; width:70px; animation-duration:1.6s, 96s; animation-delay:-.4s, -24s;}
@keyframes bob{0%,50%,100%{transform:translateY(0);}25%,75%{transform:translateY(-2px);}}
/* camel-walk carries BOTH the horizontal crossing (left, defined only at 0%/100% so speed
   stays constant and linear) AND a slow vertical undulation (margin-bottom) so the camels ride
   up over the dune crests and dip into the valleys instead of gliding in a dead-straight line —
   which read as floating. margin-bottom, not transform, because transform is already the walking
   `bob` gait (and the `camel-fly` easter egg) — margin-bottom composes with those and is additive
   on top of each camel's own `bottom`, so the two keep their different base heights. Folded into
   camel-walk rather than a new animation so the .is-flying variant's fixed 3-animation list
   (bob, camel-walk, camel-fly) is untouched; the tiny margin offset during flight is negligible
   against the big fly arc. */
@keyframes camel-walk{
  0%{left:-140px; margin-bottom:-6px;}
  14%{margin-bottom:8px;}
  30%{margin-bottom:-4px;}
  48%{margin-bottom:11px;}
  64%{margin-bottom:-2px;}
  82%{margin-bottom:7px;}
  100%{left:110%; margin-bottom:-6px;}
}

/* ── Camel easter egg: double-click straps on a jetpack, lets it visibly ignite, then
   launches the camel skyward on an arc. This only adds a 3rd (camel-fly) animation to the
   camel sprite's list; camel-fly is listed last so its `transform` wins over bob's while it
   plays. animation-fill-mode:forwards holds it (and opacity:0) until js/desert-scene.js
   removes .is-flying on animationend (with a setTimeout fallback there too, in case
   animationend never fires — that's the "flew once, never again" bug: .is-flying's own
   guard permanently blocks re-triggering if nothing ever removes the class). That same
   cleanup also forces bob/camel-walk to restart from scratch (style.animation='none' +
   reflow) rather than seamlessly resuming wherever they'd have been — the camel should
   start its next lap from off-screen left, not pop back in mid-air where it took off.
   camel-fly spends its first ~25% holding still — the jet visibly popping onto its back and
   igniting (see the .s-jet/.s-flame rules below, timed to that same opening window) —
   before the actual launch. */
.camel-1.is-flying,.camel-2.is-flying{
  animation-name:bob, camel-walk, camel-fly;
  /* linear, not ease-in: the arc is already described by the keyframes below, and a timing
     function is applied between *every* pair of them — easing on top re-accelerates at each
     step and turns one smooth curve into a series of lurches. */
  animation-timing-function:steps(1,jump-end), linear, linear;
  animation-iteration-count:infinite, infinite, 1;
  animation-fill-mode:none, none, forwards;
  /* .scene is only 230px tall with overflow:hidden, which flattened the old arc — the camel
     hit that ceiling almost immediately and the curve was invisible. Switching to fixed
     re-anchors it to the viewport instead of the scene box, and since .scene sets no
     transform/filter it creates no containing block for fixed children, so the clip no
     longer applies and the camel can arc up through the whole page. The coordinates carry
     over unchanged: .scene is itself fixed, full-width and bottom:0, so `bottom` and a
     percentage `left` already resolve against the same edges the viewport would give. */
  position:fixed;
}
.camel-1.is-flying{animation-duration:1.4s, 96s, 4.5s; animation-delay:0s, 0s, 0s;}
.camel-2.is-flying{animation-duration:1.6s, 96s, 4.5s; animation-delay:-.4s, -24s, 0s;}
/* Escaping the clip isn't enough on its own — .scene has z-index:1 and so opens a stacking
   context its children can never climb out of, which would fly the camel *behind* the page
   content (z-index:3). Raised only while a flight is in progress; desert-scene.js adds and
   removes this alongside .is-flying. */
.scene.has-flyer{z-index:6;}
/* A genuine parabola across the whole sky: steep climb, apex a little past the middle of the
   flight, then a long shallow descent into the distance. Distances are in vw/vh rather than
   px so the same curve reads correctly on a phone and on a widescreen monitor — the old
   fixed-px version barely left the dunes on a large display. The nose rotates with the
   direction of travel (pitched up on the way out, level at the top, pitched down coming
   back) and the camel shrinks as it goes, so it recedes into the distance rather than
   sliding off an invisible edge. */
@keyframes camel-fly{
  0%,15%{transform:translate(0,0) rotate(0deg) scale(1); opacity:1;}
  25%{transform:translate(4vw,-10vh) rotate(-12deg) scale(1); opacity:1;}
  40%{transform:translate(16vw,-28vh) rotate(-16deg) scale(.92); opacity:1;}
  55%{transform:translate(32vw,-40vh) rotate(-8deg) scale(.80); opacity:1;}
  70%{transform:translate(50vw,-45vh) rotate(4deg) scale(.62); opacity:1;}
  85%{transform:translate(70vw,-37vh) rotate(15deg) scale(.40); opacity:.7;}
  100%{transform:translate(92vw,-22vh) rotate(24deg) scale(.16); opacity:0;}
}

/* Jetpack rects sit hidden on the camel's back (behind the hump) until .is-flying reveals
   them. jet-open is a one-shot pop-in (with a little overshoot, like it's unfolding);
   flame-ignite is a one-shot fade-in timed to when the jet has finished opening, handing off
   to flame-flicker's continuous loop once lit — two separate animations on the same element
   so the flicker doesn't replay the fade-in every cycle. */
.s-jet,.s-jet-d{opacity:0; transform-box:fill-box; transform-origin:center;}
.s-flame,.s-flame2{opacity:0;}
.s-jet{fill:var(--border2);}
.s-jet-d{fill:var(--border);}
.s-flame{fill:var(--glow);}
.s-flame2{fill:var(--glow2);}
.camel-1.is-flying .s-jet,.camel-1.is-flying .s-jet-d,
.camel-2.is-flying .s-jet,.camel-2.is-flying .s-jet-d{
  animation:jet-open .35s steps(1,jump-end) forwards;
}
.camel-1.is-flying .s-flame,.camel-1.is-flying .s-flame2,
.camel-2.is-flying .s-flame,.camel-2.is-flying .s-flame2{
  animation:flame-ignite .15s ease-in forwards .32s, flame-flicker .12s steps(2,jump-none) infinite .47s;
}
@keyframes jet-open{
  0%{opacity:0; transform:scale(.2);}
  65%{opacity:1; transform:scale(1.2);}
  100%{opacity:1; transform:scale(1);}
}
@keyframes flame-ignite{0%{opacity:0;}100%{opacity:1;}}
@keyframes flame-flicker{0%,100%{opacity:1;}50%{opacity:.55;}}

/* ── Tree easter egg: double-click drops a coconut that bounces once and fades. Spawned
   and removed by js/desert-scene.js; pointer-events:none so it never becomes clickable
   itself. */
.tree-drop{position:absolute; pointer-events:none; z-index:2; animation:tree-drop-fall 1.1s cubic-bezier(.3,0,.7,1) forwards;}
.tree-drop .td-shell{fill:var(--camel-dim);}
.tree-drop .td-shell-hi{fill:var(--camel);}
@keyframes tree-drop-fall{
  0%{transform:translateY(0) rotate(0deg); opacity:1;}
  55%{transform:translateY(46px) rotate(160deg); opacity:1;}
  70%{transform:translateY(34px) rotate(200deg);}
  100%{transform:translateY(40px) rotate(220deg); opacity:0;}
}

/* Legs: two diagonal pairs (front-left+back-right, front-right+back-left) alternate
   lifting, like a real quadruped trot. scaleY anchored at the top so the hip stays put
   and only the lower leg appears to lift off the ground. */
.s-leg{transform-box:fill-box; transform-origin:top;}
.s-leg-a{animation:leg-step .7s steps(2,jump-none) infinite;}
.s-leg-b{animation:leg-step .7s steps(2,jump-none) infinite; animation-delay:-.35s;}
@keyframes leg-step{0%,100%{transform:scaleY(1);}50%{transform:scaleY(.55);}}

/* Mario clouds */
.cloud{position:fixed; z-index:1; pointer-events:none;}
.cloud .c-body{fill:var(--cloud);}
.cloud .c-edge{fill:var(--cloud-edge);}
.cloud-1{top:12%; width:110px; animation:drift1 38s linear infinite;}
.cloud-2{top:24%; width:78px; animation:drift2 52s linear infinite;}
.cloud-3{top:8%; width:64px; animation:drift1 64s linear infinite; animation-delay:-20s;}

/* Checkered-flag cloud (feedback #18) — hidden Easter egg, opens the camel marathon game
   (js/marathon-game.js). Needs its own pointer-events opt-in same as the palm/camel click
   targets above, since .cloud is pointer-events:none by default. */
.cloud-checkered{pointer-events:auto; cursor:pointer;}
.cloud-checkered:hover{filter:brightness(1.15) drop-shadow(0 0 4px rgba(255,255,255,.6));}
@keyframes drift1{from{left:-160px;}to{left:110%;}}
@keyframes drift2{from{left:110%;}to{left:-160px;}}

@media(max-width:520px){
  .switcher{padding:8px 9px;}
  .nav-link{font-size:6px; padding:8px 10px;}
  .palm-left,.palm-right{width:50px;} .camel-1{width:70px;} .camel-2{width:52px;} .scene{height:170px;}
}
