:root{
  --gold:#d9b45a; --gold-lit:#f2c14e; --navy:#1c2436; --ink:#0e1017;
  --panel:rgba(18,22,32,.82); --line:rgba(217,180,90,.35); --txt:#eae6da; --dim:#9aa0ad;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;background:#0e1017;color:var(--txt);
  font-family:"Segoe UI",Roboto,Helvetica,Arial,sans-serif;overflow:hidden;
  /* no rubber-band / pull-to-refresh riding on top of a look drag */
  overscroll-behavior:none;-webkit-tap-highlight-color:transparent}
/* THE CANVAS OWNS THE GESTURE. Without `touch-action:none` the browser treats a
   swipe on the canvas as a candidate for its own panning/zooming, and fires
   pointercancel a handful of pixels in — js/scene.js endDrag() then drops the
   look drag halfway through the swipe and the camera stops turning. That is the
   "each swipe moves the view about a millimetre" phone and iPad players
   reported: the first few pixels arrive, the rest of the gesture belongs to the
   browser. The walking joystick never had it because js/mobile.js sets
   touch-action:none on #m-joy. Scoped to the canvas on purpose: panels, menus
   and the chat keep their ordinary scrolling. */
#scene{position:fixed;inset:0;width:100vw;height:100vh;display:block;touch-action:none}

/* DE ☰ NAAST DE BADGE, NIET EROVERHEEN.
   js/esc_menu.js zet zijn ☰-knop rechtsboven neer (right:14). Dat is in de stad
   een lege hoek, maar in de club staat daar de badge-knop van js/badges.js —
   58 px breed op dezelfde plek. Gemeten op een scherm van 1280x800:
   #esc-open op 1228,12 en #badge-open op 1208,12, een overlap van 38x34 px.
   Dat zijn de twee ronde knoppen die half over elkaar stonden.
   14 (marge) + 58 (de badge) + 8 (lucht) = 80. Alleen hier, want dit bestand is
   van de club; de stad houdt zijn eigen plaatsing.
   Op een aanraakscherm is de ☰ sowieso verborgen — daar is de menubalk de
   ingang (js/hub_menu.js). Dit gaat dus over de computer. */
#esc-open{right:calc(80px + env(safe-area-inset-right)) !important}

#brand-tag{position:fixed;top:14px;left:18px;z-index:5;line-height:1.1;pointer-events:none;
  text-shadow:0 2px 10px rgba(0,0,0,.7)}
#brand-tag b{font-size:20px;color:var(--gold-lit);letter-spacing:.3px;
  font-family:Georgia,"Times New Roman",serif}
#brand-tag span{display:block;font-size:11px;color:var(--dim);letter-spacing:2px;text-transform:uppercase}

.hidden{display:none !important}

/* The name screen shown on the way INTO the club (js/main.js enterTheClub) sits
   over the portal curtain (#portal-fade, z-index 9000) instead of over a room.
   The curtain is what guarantees the player never sees the retired lot behind
   it; the modal has to be above it or the curtain swallows the form. */
body.entry-over-curtain #entry-modal{z-index:9500}

/* fade transition */
#transition{position:fixed;inset:0;background:#000;z-index:40;opacity:0;pointer-events:none;
  transition:opacity .6s ease}
#transition.show{opacity:1}

/* overlays */
.overlay{position:fixed;inset:0;z-index:30;display:flex;align-items:center;justify-content:center;
  background:rgba(6,8,14,.55);backdrop-filter:blur(9px);-webkit-backdrop-filter:blur(9px)}
/* 9 sept 2026 -- HIER STOND `animation:fade .25s ease` OP .overlay. Niet doen.
   Gemeten in de club: de animatie liep helemaal niet. Ook na 900 ms stond hij nog
   op zijn eerste beeld. Oorzaak: op datzelfde element staat backdrop-filter, en
   daardoor kan de browser de opacity niet op de compositor draaien maar moet hij
   het op de hoofddraad doen -- precies de draad die de 3D-lus bezet houdt. Met
   from{opacity:0} betekende dat: het blad blijft onzichtbaar. Vier bladen (Club
   texts, Play a video, Music, Invite codes) leken daardoor kapot terwijl ze er
   gewoon stonden. Nu verschijnen ze meteen. Een fade terugzetten kan alleen op
   een element ZONDER backdrop-filter. */
@keyframes fade{from{opacity:0}to{opacity:1}}   /* blijft staan: andere plekken gebruiken hem nog */
.panel{position:relative;width:min(440px,92vw);background:var(--panel);border:1px solid var(--line);
  border-radius:16px;padding:26px 26px 22px;box-shadow:0 24px 70px rgba(0,0,0,.6);
  backdrop-filter:blur(4px)}
.panel.wide{width:min(640px,94vw)}
.panel h1{margin:.1em 0 .3em;font-size:22px;color:var(--gold-lit);letter-spacing:.5px;
  font-family:Georgia,serif}
.panel .sub{margin:0 0 16px;color:var(--dim);font-size:14px}
.panel .x{position:absolute;top:12px;right:14px;background:none;border:none;color:var(--dim);
  font-size:26px;cursor:pointer;line-height:1}
.panel .x:hover{color:var(--txt)}

.fld{display:block;margin:12px 0}
.fld span{display:block;font-size:12px;color:var(--dim);margin-bottom:6px;letter-spacing:.5px}
.fld input{width:100%;padding:12px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.14);
  background:rgba(0,0,0,.35);color:var(--txt);font-size:15px;outline:none}
.fld input:focus{border-color:var(--gold)}
.primary{width:100%;margin-top:10px;padding:13px;border:none;border-radius:11px;cursor:pointer;
  font-weight:700;letter-spacing:.6px;color:#241a06;
  background:linear-gradient(180deg,#f2c14e,#cf9f3c);box-shadow:0 8px 22px rgba(217,180,90,.28)}
.primary:hover{filter:brightness(1.06)} .primary:disabled{opacity:.6;cursor:default}
.msg{min-height:18px;margin-top:10px;font-size:13px}
.msg.err{color:#ef8f7e}.msg.ok{color:#8fd6a6}
.dim{color:var(--dim)}.small{font-size:12px}

/* whiteboard menu */
.tabs{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 14px}
.tab{padding:8px 12px;border-radius:8px;border:1px solid rgba(255,255,255,.12);
  background:rgba(255,255,255,.04);color:var(--dim);font-size:13px;cursor:pointer}
.tab.active{color:#241a06;background:linear-gradient(180deg,#f2c14e,#cf9f3c);border-color:transparent;font-weight:700}
.wb-body{max-height:52vh;overflow:auto;line-height:1.6;font-size:14.5px;white-space:pre-wrap}
.wb-body h3{color:var(--gold-lit);margin:.2em 0 .4em}
.wb-body a{color:var(--gold-lit)}
.faq-q{color:var(--gold-lit);font-weight:700;margin-top:12px}
.faq-a{color:var(--txt)}

.discord-row{margin-top:14px}.or{color:var(--dim);text-align:center;margin:8px 0;font-size:12px}
/* TIJDELIJK: Telegram-uitnodiging op de plek van de Discord-mededeling in de VIP-poort. */
.tg-note{margin-top:14px;padding-top:14px;border-top:1px solid var(--line);text-align:center}
.tg-copy{margin:0 0 10px;color:var(--dim);font-size:13px;line-height:1.45}
.tg-link{display:block;padding:11px 14px;border-radius:10px;text-decoration:none;font-weight:700;
  font-size:14px;letter-spacing:.3px;color:var(--gold-lit);border:1px solid rgba(217,180,90,.42);
  background:rgba(217,180,90,.10);overflow-wrap:anywhere}
.tg-link:hover,.tg-link:focus-visible{background:rgba(217,180,90,.20);border-color:var(--gold)}
.discord{display:block;text-align:center;padding:11px;border-radius:10px;background:#5865F2;color:#fff;
  text-decoration:none;font-weight:600}

/* HUD */
#hud{position:fixed;top:12px;left:50%;transform:translateX(-50%);z-index:6;text-align:center}
#room-name{font-size:15px;color:var(--gold-lit);letter-spacing:1px;margin-bottom:6px;
  text-shadow:0 2px 10px rgba(0,0,0,.8);font-family:Georgia,serif}
#hud-controls{display:flex;gap:8px;justify-content:center}
.room-btn{padding:8px 12px;border-radius:9px;border:1px solid rgba(217,180,90,.3);
  background:rgba(18,22,32,.7);color:var(--txt);font-size:13px;cursor:pointer;backdrop-filter:blur(4px)}
.room-btn:hover{border-color:var(--gold)} .room-btn.active{background:rgba(217,180,90,.22);border-color:var(--gold)}
.room-btn.vip::after{content:" ★";color:var(--gold-lit)}

#help{position:fixed;bottom:14px;left:50%;transform:translateX(-50%);z-index:6;color:var(--dim);
  font-size:12px;background:rgba(6,8,14,.5);padding:6px 12px;border-radius:20px;backdrop-filter:blur(4px)}

#cinema-controls{position:fixed;bottom:70px;left:50%;transform:translateX(-50%);z-index:7;display:flex;gap:6px;
  align-items:center;background:rgba(6,8,14,.7);padding:8px;border-radius:12px;backdrop-filter:blur(6px)}
#cinema-controls input{width:280px;max-width:44vw;padding:9px 12px;border-radius:8px;border:1px solid rgba(255,255,255,.14);
  background:rgba(0,0,0,.4);color:var(--txt)}
#cinema-controls button{padding:9px 12px;border-radius:8px;border:none;cursor:pointer;background:var(--gold);color:#241a06;font-weight:600}
#yt-mute{background:rgba(0,0,0,.4);color:var(--txt);border:1px solid rgba(255,255,255,.14);min-width:40px;font-size:15px}
#yt-vol{-webkit-appearance:none;appearance:none;width:110px;height:6px;border-radius:4px;
  background:linear-gradient(90deg,var(--gold) 0%,var(--gold) 60%,rgba(255,255,255,.18) 60%);outline:none;cursor:pointer}
#yt-vol::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:15px;height:15px;border-radius:50%;
  background:var(--gold);border:2px solid #241a06;cursor:pointer}
#yt-vol::-moz-range-thumb{width:15px;height:15px;border-radius:50%;background:var(--gold);border:2px solid #241a06;cursor:pointer}

#chat{position:fixed;left:14px;bottom:14px;z-index:6;width:min(340px,80vw)}
#chat-log{max-height:34vh;overflow:auto;display:flex;flex-direction:column;gap:3px;margin-bottom:6px}
.chat-line{background:rgba(6,8,14,.55);padding:6px 10px;border-radius:9px;font-size:13.5px;backdrop-filter:blur(3px);
  max-width:100%;word-wrap:break-word}
.chat-line.system{color:var(--dim);font-style:italic;background:transparent;padding:2px 10px}
.chat-line .who{color:var(--gold-lit);font-weight:700}
/* ONE BIG CHATBOX (server/chat.js): the club and &Investmint City share one
   conversation, so a line can come from somewhere you are not. The tag appears
   only for lines spoken in another zone, and .old dims the backlog that is
   replayed on arrival so it is not mistaken for live talk. */
.chat-line .zone{font-size:10px;letter-spacing:.5px;opacity:.55;margin-right:5px;
                 border:1px solid rgba(226,178,60,.35);border-radius:5px;padding:0 4px}
.chat-line.old{opacity:.6}
#chat-form input{width:100%;padding:10px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.14);
  background:rgba(6,8,14,.72);color:var(--txt);outline:none;backdrop-filter:blur(4px)}
#chat-form input:focus{border-color:var(--gold)}

.voice{position:fixed;right:14px;bottom:14px;z-index:6;padding:10px 14px;border-radius:22px;border:1px solid rgba(217,180,90,.3);
  background:rgba(18,22,32,.7);color:var(--txt);cursor:pointer;backdrop-filter:blur(4px)}
.voice.on{background:#7bb661;color:#10240f;border-color:transparent}

#yt-overlay-frame{position:fixed;z-index:4;border:none;background:#000}
#yt-holder{position:fixed;z-index:4;overflow:hidden;background:#000;opacity:0;pointer-events:auto;
  border-radius:2px;transition:opacity .2s}
#yt-holder iframe{width:100%;height:100%;border:0;display:block}

/* emote wheel: the rules moved into js/emote_wheel.js (same values, plus literal
   fallbacks for --line/--dim) so city.html, which does not load this stylesheet,
   renders the identical wheel. Only the hub's own hide-rules stay in index.html. */

/* character selection */
.char-choices{display:flex;gap:10px;flex-wrap:wrap}
.char-btn{flex:1 1 0;min-width:120px;display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:12px 10px;border-radius:12px;cursor:pointer;color:var(--dim);
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.12);transition:all .12s ease}
.char-btn:hover{border-color:var(--gold);color:var(--txt)}
.char-btn .char-ic{font-size:30px;line-height:1}
.char-btn .char-nm{font-size:13px;letter-spacing:.3px}
.char-btn.active{background:linear-gradient(180deg,rgba(242,193,78,.22),rgba(207,159,60,.12));
  border-color:var(--gold);color:var(--txt);box-shadow:0 6px 18px rgba(217,180,90,.22)}
.char-btn.active .char-nm{color:var(--gold-lit);font-weight:700}

/* ==========================================================================
   PHONES AND TABLETS — one screen, nothing on top of anything else
   ==========================================================================
   Measured on a 390x844 phone before this block existed: EIGHT overlapping
   pairs. The logo sat on the room name and the teleport buttons (152x34 px of
   overlap), the bottom help line ran straight through the chat box (195x43),
   the chat ran into the Voice button (57x39), and everything along the bottom
   ended 14 px above the screen edge — underneath the home indicator, which is
   about 34 px tall. Nothing used env(safe-area-inset-*).

   The layout is now a top band and a bottom band with the middle left clear:

     top-left     the logo, then the room name under it, then the chat
     top-right    a COLUMN of round icons: profile (js/badges.js), microphone,
                  DJ booth — see the ladder further down
     bottom-left  the walking stick            (js/mobile.js)
     bottom-right Interact and Dance            (js/mobile.js)

   Both bands are pushed in by the safe-area insets, so nothing lands under the
   notch or the home bar. The help line and the teleport buttons are gone from
   index.html, which is what frees the bottom centre and the top middle.

   The query is (hover:none) and (pointer:coarse) — the same test js/mobile.js
   uses to decide to draw the thumb stick at all, so the two can never disagree.
   A laptop with a touchscreen keeps hover and a fine pointer, and keeps the
   desktop layout.  */
@media (hover: none) and (pointer: coarse) {
  /* ---- top-left: logo, room name, chat ---- */
  #brand-tag{top:calc(8px + env(safe-area-inset-top));left:calc(14px + env(safe-area-inset-left))}
  #brand-tag b{font-size:15px}

  /* #hud is the room name and nothing else now. Off the centre line, under the
     logo, so the two cannot collide however long either string gets. */
  #hud{top:calc(32px + env(safe-area-inset-top));left:calc(14px + env(safe-area-inset-left));
       right:auto;transform:none;text-align:left}
  #room-name{font-size:11px;letter-spacing:1.6px;opacity:.72;margin:0}

  /* The chat moves OFF the bottom-left corner, which belongs to the thumb stick,
     and hangs under the room name instead. Narrower, and a shorter log: half the
     screen of scrollback is not something anybody reads on a phone. */
  #chat{left:calc(14px + env(safe-area-inset-left));top:calc(56px + env(safe-area-inset-top));
        bottom:auto;width:min(64vw,240px)}
  #chat-log{max-height:20vh}
  #chat-form input{padding:8px 10px;font-size:13px}

  /* ---- top-right: A LADDER OF ICONS, ONE UNDER THE OTHER ------------------
     Labels cost 179 px of a 390 px wide screen and say what the icon already
     says. The microphone keeps its state in its colour (.voice.on stays green).

     THEY STAND IN A COLUMN, NOT A ROW, and that is the whole point. A row was
     the first attempt and it collided within a day: js/badges.js puts the
     profile button (🎖) at top-right too — it says so in its own comment, "top
     right on the hub page is free" — and it was hidden until you are inside the
     club, so it was not on screen when the row was measured. The DJ icon ended
     up underneath it (z-index 86 over 40): two buttons, one spot.

     A row cannot survive that. The brand line already eats 202 px of the 390,
     the profile button grows when it carries a count, and every conditional
     button that appears later wants the same corner. A column has room for all
     of them and never has to be re-measured: the next one goes at 156.

       12   #badge-open   (js/badges.js — its own rule, deliberately untouched)
       60   .voice
      108   #dj-controls
      156   #m-fs         (full screen — js/mobile.js)
      204   ...the next one

     The offsets are absolute rather than a flex gap because the three elements
     are built by three different modules and appended to <body> separately;
     there is no shared parent to lay them out in. */
  .voice{top:calc(60px + env(safe-area-inset-top));right:calc(14px + env(safe-area-inset-right));
         bottom:auto;width:40px;height:40px;padding:0;border-radius:50%;font-size:0;
         display:flex;align-items:center;justify-content:center}
  .voice::before{content:'\1F3A4';font-size:17px}
  #dj-controls{top:calc(108px + env(safe-area-inset-top));right:calc(14px + env(safe-area-inset-right));
               bottom:auto;align-items:flex-end}
  /* Full screen. Worth more on a phone than anywhere else: the URL bar and the
     system bars cost about a third of the height, and in landscape that is the
     dimension there is least of. Built in js/mobile.js, and only when the browser
     actually supports it — iOS Safari does not, and gets no button rather than a
     dead one. */
  #m-fs{position:fixed;top:calc(156px + env(safe-area-inset-top));
        right:calc(14px + env(safe-area-inset-right));z-index:60;
        width:40px;height:40px;padding:0;border-radius:50%;
        border:1px solid rgba(217,180,90,.3);background:rgba(20,10,26,.72);color:#f4e9c9;
        font-size:19px;line-height:1;display:flex;align-items:center;justify-content:center;
        -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
        touch-action:none;-webkit-user-select:none;user-select:none}
  #m-fs.m-fs-on{background:rgba(217,180,90,.35);color:#241a06;border-color:transparent}
  #dj-toggle{width:40px;height:40px;padding:0;border-radius:50%;justify-content:center}
  #dj-toggle span:not(.dj-ic){display:none}
  /* the track list opens DOWNWARD from the icon now that the icon lives up top */
  #dj-controls{flex-direction:column-reverse}
  #dj-panel{max-width:min(78vw,280px)}

  /* ---- door prompts clear of the thumbs ----------------------------------
     js/portal.js puts its prompt at bottom:96 and its refusal line at
     bottom:150, from the days when the bottom of the screen was empty. The
     walking stick now starts 188 px up, and "This door is closed." was landing
     on its top-right corner (measured: 38x38 px). Both move above the thumb
     band, which is also simply where you can read them.

     !important, and this is the one place it is earned: portal.js injects its
     own <style> into <head> at run time, so its rules come AFTER this file with
     the same one-id specificity and would otherwise always win. Overriding it
     here rather than editing portal.js keeps &Investmint City — which loads
     that module and NOT this stylesheet — exactly as it is. */
  #portal-hint{bottom:calc(226px + env(safe-area-inset-bottom)) !important}
  #portal-notice{bottom:calc(282px + env(safe-area-inset-bottom)) !important}

  /* ======================================================================
     SIDEWAYS — a different shape of screen, not the same one rotated
     ======================================================================
     Portrait is 390x844: tall, so a top band and a bottom band cost little.
     Landscape is 844x390: the SAME two bands now eat the dimension there is
     least of, and the icon ladder alone (four icons, 12 to 196) would run down
     half the screen.

     So sideways the ladder lies DOWN — the same four icons in a row along the
     top edge, where 844 px of width makes them free — and the thumb controls
     shrink. The safe areas move with the phone: the notch is at the left or the
     right now, which is why every offset in this file is written against
     env(safe-area-inset-left/right) rather than a bare number.

     Nothing is hidden to make it fit. Everything that is on screen in portrait
     is on screen here. */
  @media (orientation: landscape) {
    /* the ladder lies down: a row along the top, right to left */
    .voice{top:calc(8px + env(safe-area-inset-top));right:calc(92px + env(safe-area-inset-right))}
    #dj-controls{top:calc(8px + env(safe-area-inset-top));right:calc(138px + env(safe-area-inset-right))}
    #m-fs{top:calc(8px + env(safe-area-inset-top));right:calc(184px + env(safe-area-inset-right))}
    .voice,#dj-controls #dj-toggle,#m-fs{width:38px;height:38px}

    /* the left column tightens: the room name and the chat move up under the
       logo instead of stepping down the screen */
    #hud{top:calc(28px + env(safe-area-inset-top))}
    #chat{top:calc(48px + env(safe-area-inset-top));width:min(40vw,260px)}
    #chat-log{max-height:26vh}

    /* thumbs: smaller, because a 128 px stick is a third of the height here */
    #m-joy{width:104px;height:104px;bottom:calc(18px + env(safe-area-inset-bottom))}
    #m-knob{width:42px;height:42px;left:31px;top:31px}
    .m-btn{width:56px;height:56px;font-size:22px}
    #m-btns{gap:10px;bottom:calc(20px + env(safe-area-inset-bottom))}

    /* the bottom centre is free sideways (stick left, buttons right), so the
       door prompts go back down where they read best */
    #portal-hint{bottom:calc(26px + env(safe-area-inset-bottom)) !important}
    #portal-notice{bottom:calc(80px + env(safe-area-inset-bottom)) !important}
  }
}

/* THE BAR AT THE BOTTOM IS GONE FOR GOOD, FOR EVERYBODY.
   First it lost its own text; then it turned out js/propeditor.js was still
   borrowing it, so "prop editor: drag to move" kept appearing across the bottom
   of the screen for the owner — the same strip of clutter with a different
   author. The editor now keeps its hint inside its own panel (#pe-hintline), so
   nothing writes here at all and the bar can simply be off.
   The ELEMENT stays because js/main.js revealHud() and js/director.js address it
   by id; removing it would throw before the player ever sees the club. */
#help{display:none !important}
