/* Gypsy Chat 2000 — styles */
/* Cinzel and IM Fell English (the two display/body fonts loaded in index.html) both draw their
   digits noticeably smaller than their letters -- Cinzel especially, since it's really an
   all-caps display face where numerals were never the focus. Rather than swap either typeface
   site-wide, redirect JUST the digit characters (U+0030-0039) to a normal-sized numeral face
   using the same family names: the browser picks whichever @font-face covers a given character's
   codepoint, so every existing font-family:Cinzel/"IM Fell English" declaration below keeps its
   letterforms untouched and only its digits change, with no markup or JS changes needed anywhere.
   Georgia's numerals are a good match in weight/style for both; on platforms without a local
   Georgia (most Android devices) the local() match simply fails and these digits fall through to
   the next font in each declaration's own font-family list, same as any other missing font. */
@font-face{font-family:'Cinzel';src:local('Georgia');unicode-range:U+0030-0039;font-weight:400}
@font-face{font-family:'Cinzel';src:local('Georgia Bold'),local('Georgia');unicode-range:U+0030-0039;font-weight:700}
@font-face{font-family:'IM Fell English';src:local('Georgia');unicode-range:U+0030-0039;font-weight:400}
/* text-size-adjust: iOS Safari otherwise "helpfully" inflates text it decides is too small once a
   page is wider than the screen or rotates to landscape, and it does so per element -- so the room
   could end up with mismatched, oversized runs of text that no rule in this file asked for. 100%
   pins every size to exactly what the stylesheet says. No effect on desktop browsers. */
html,body{margin:0;min-height:100%;background:#000000;-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)}

:root{
--stone:#0a0806; --stone-2:#17120e; --stone-3:#251e19;
--gold:#c49a52; --gold-hi:#e8d3a2; --gold-lo:#6b5024;
--bone:#cdc1a6; --ash:#8f8371; --blood:#b3261e; --ember:#e08a2c; --leaf:#5aa15a;
/* Level-badge tiers, ten levels wide -- see levelTier() in app.js for which level maps to which. */
--lvl-1:#eef0e6; --lvl-2:#4d79e6; --lvl-3:#a259e6; --lvl-4:#f1d98a; --lvl-5:#ff5fa8; --lvl-6:#2ed3e0;
--lvl-7:#39ff6a; --lvl-8:#ff8a2b; --lvl-9:#c9d6f2; --lvl-10:#f5f8ff; --lvl-11:#ffdf7e;
--me:#f1d98a; --them:#e6b25a; --sys:#8f8371;
}
*{box-sizing:border-box}
.gc-root{min-height:100vh;font:14px "IM Fell English",Georgia,serif;color:var(--bone);display:flex;justify-content:center;padding:6px 0;
background:radial-gradient(ellipse at 50% 0%,#1d150e 0%,#000000 70%);min-height:100%}
.win{width:100%;max-width:760px;background:linear-gradient(180deg,var(--stone-2),var(--stone));position:relative;
border:3px double var(--gold-lo);outline:1px solid #000;box-shadow:0 0 0 2px var(--gold),0 0 0 3px #000,0 0 28px #000,inset 0 0 40px #000}
.win::before,.win::after,.corner{content:"";position:absolute;width:26px;height:26px;pointer-events:none;
border:2px solid var(--gold-hi);}
.win::before{top:-3px;left:-3px;border-right:none;border-bottom:none}
.win::after{top:-3px;right:-3px;border-left:none;border-bottom:none}
.corner.bl{bottom:-3px;left:-3px;border-right:none;border-top:none}
.corner.br{bottom:-3px;right:-3px;border-left:none;border-top:none}
.title{display:flex;align-items:center;justify-content:center;gap:12px;padding:5px 10px 4px;
background:linear-gradient(180deg,#281f15,#110c07);border-bottom:2px solid var(--gold-lo);box-shadow:0 2px 0 #000}
.title .name{font:700 20px Cinzel,"Trajan Pro",Georgia,serif;letter-spacing:2px;color:var(--gold);
text-shadow:0 0 10px rgba(201,162,74,.55),0 2px 0 #000,0 -1px 0 #000}
/* The two hanging lanterns that flank the title. Drawn as inline SVG rather than a bitmap so they
   stay crisp at any density and can be recoloured from the same gold variables as the rest of the
   chrome -- and so the flame can be animated as its own element instead of as a sprite sheet.
   The taller-than-wide box is why .title's vertical padding above is smaller than the old diamonds
   needed: the lantern carries the bar's height now, so the header stays about where it was. */
.title .lantern{width:15px;height:26px;flex:none;overflow:visible;
/* two stacked shadows rather than one big blur: a wide purple haze for reach, and a tight pale
   one right against the glass so the lantern reads as lit rather than just outlined */
filter:drop-shadow(0 0 12px rgba(163,42,255,.8)) drop-shadow(0 0 4px rgba(214,80,255,.85))}
.title .lantern .lt-hook{fill:none;stroke:var(--gold);stroke-width:1.1}
.title .lantern .lt-cap{fill:var(--gold);stroke:var(--gold-lo);stroke-width:.6;stroke-linejoin:round}
.title .lantern .lt-glass{fill:rgba(186,70,255,.3);stroke:none}
.title .lantern .lt-pane{fill:none;stroke:var(--gold);stroke-width:1.1}
.title .lantern .lt-bars{fill:none;stroke:var(--gold-lo);stroke-width:.7}
/* The flame is two stacked shapes filled from the shared radial gradients declared at the top
   of the page, not from flat colour -- these two rules are only the fallback for a browser that
   cannot resolve the url(#...) fill. The old flat pale-lilac core was what made the whole
   lantern read as washed out: at this size the core is most of what you see, so a near-white
   centre drained the colour out of the entire thing. The gradients put the strongest colour in
   the middle of the flame and let it deepen towards the edge. */
.title .lantern .lt-flame-out{fill:#c33cff}
.title .lantern .lt-flame-in{fill:#e072ff}
/* fill-box so the flame scales from the wick at its own base, not from the whole 18x30 viewBox */
.title .lantern .lt-flame{transform-box:fill-box;transform-origin:50% 100%}
.body{display:grid;grid-template-columns:1fr var(--users-w,160px);gap:10px;padding:12px}
@media (max-width:500px){
  .body{grid-template-columns:1fr}
  /* (An old `.users{display:none}` used to sit here. It never actually applied -- the plain
     `.users{display:flex}` rule further down has the same specificity and comes later in the
     file, so it always won -- and the panel is meant to be visible on a phone anyway, as the
     foldable block between the log and the composer; see "Online/Friends panel on a phone" below.) */
  .gc-root{padding:4px 0}
  .win{max-width:100%;min-height:calc(100vh - 8px);display:flex;flex-direction:column}
  /* iOS Safari's address bar shrinks/grows the visual viewport without firing a resize the way
     100vh expects, which can leave the frame short or clip the cooldown/mute banner and warning
     popup below the fold. 100dvh tracks the real visible area there; browsers that don't know it
     (this rule is simply skipped) keep the 100vh value set just above. */
  .win{min-height:calc(100dvh - 8px)}
  .win > .title{position:sticky;top:0;z-index:15;box-shadow:0 2px 0 #000,0 4px 12px rgba(0,0,0,.6)}
  .win > .body{flex:1;display:grid;grid-template-rows:1fr auto;min-height:0;padding:8px}
  .win > .body .log{height:auto;min-height:0}
  .win > .body .login{align-self:center}
  /* Once signed in, the frame needs to be EXACTLY viewport-tall, not just at least that tall.
     .body's grid row for .log is `1fr`, and a `1fr` track only resolves to a bounded, finite size
     when the grid's own ancestor chain has a firm height to divide up -- min-height alone lets
     .win (and everything below it) keep growing to fit its content instead, so .log's "1fr" row
     was silently computing to the height of every message ever posted in the room, not the space
     actually visible on screen. That turned .log from an internally-scrolling pane into an
     ordinary block the whole page had to be scrolled past, and it also put the watermark's
     background-position:center dead in the vertical middle of that enormous box -- nowhere near
     whatever slice of it a scrolled-to-the-bottom phone was actually looking at, once the room
     had more than one screenful of history. That's why the artwork could work once (a fresh, short
     log fits a screen fine) and quietly disappear later as the room filled up.
     The sign-on screen still needs the old grow-to-fit min-height above -- her portrait footer
     (.login .gw) relies on the page being free to grow past one screen without clipping her -- so
     this firmer height only takes over once .signed-on lands on .gc-root. */
  .gc-root.signed-on .win{height:calc(100vh - 8px)}
  .gc-root.signed-on .win{height:calc(100dvh - 8px)}
}
.sunk{background:linear-gradient(180deg,#050200,#0e0906);border:1px solid var(--gold-lo);box-shadow:inset 0 0 18px #000,inset 0 0 0 1px #000,0 0 0 1px #2a2119}
.log{height:420px;overflow-y:auto;padding:8px 10px;line-height:1.5;word-wrap:break-word;scrollbar-color:var(--gold-lo) #0f0d0b}
.log .m b{font-weight:normal;font-family:Cinzel,Georgia,serif;font-size:12px;letter-spacing:.5px}
.log .m b.who{cursor:pointer}
.log .m b.who:hover,.log .m b.who:focus-visible{text-decoration:underline;outline:none}
.log .me b{color:var(--me)} .log .them b{color:var(--them)}
.log .sys{color:var(--sys);font-style:italic}

.log .t{color:#5f5648;font-size:11px;margin-right:6px}
.log .e{font-size:16px;vertical-align:-2px;filter:sepia(.35) saturate(.9)}
/* Report-this-message flag -- faint until hovered/focused so it doesn't compete with the message
   text itself, but always present (not hover-only) so it works on touch too. Shared rule below
   also covers the whisper-window copy of this button (.im .ilog .rpt-msg). */
.log .rpt-msg,.im .ilog .rpt-msg{background:none;border:none;padding:0;margin-right:6px;font-size:10px;line-height:1;vertical-align:2px;cursor:pointer;opacity:.35;filter:grayscale(1)}
.log .rpt-msg:hover,.log .rpt-msg:focus-visible,.im .ilog .rpt-msg:hover,.im .ilog .rpt-msg:focus-visible{opacity:1;filter:none;outline:none}
/* build 283: the report flag measured 12x11 -- the worst target on the site, on the debt list since
   the 281 sweep. It sits INLINE in the message line, deliberately faint so it does not compete with
   the words, and that placement is the whole difficulty.

   MEASURED, and this is the part worth keeping: the flag CANNOT reach 24x24 where it sits. The
   message line box is 23px tall, and a target cannot be taller than the line it sits in without
   taking the difference out of a neighbour. An invisible 24px target capped at 24x23 and took 3px
   from the line above; at 44px it was still 23 tall and took 13px -- enough to swallow taps meant
   for the sender's name on the previous line. Growing the glyph to 17px reached only 22x20, STILL
   under the minimum, while doubling every message row from 23 to 45.

   So the line gets the room first (1.5 -> 1.95 on touch, +4px a row), and then a 24x24 target fits
   inside its own line and steals nothing. The glyph itself is untouched -- same size, same faint
   opacity. Both copies of the button are covered: the room log and the whisper windows.

   The rule itself lives further down, just after `.im .ilog` is defined. It has to: `.im .ilog`
   sets line-height:1.45 at line ~254, the same specificity as the override, so a copy placed up
   here lost on source order and the whisper flag measured 24x23 while the room's measured 24x24.
   The sweep caught the one-pixel difference; nothing else would have. */
.users{display:flex;flex-direction:column}
.users .hd{padding:5px 6px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);text-align:center;
border-bottom:1px solid var(--gold-lo);text-shadow:0 1px 0 #000}
.users .list{flex:1;padding:6px 8px;overflow-y:auto;line-height:1.6}
.users .list div{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;padding:0 2px}
.users .list div:hover,.users .list div:focus-visible{color:var(--gold-hi);background:rgba(201,162,74,.12);outline:none}
.users .list div.self{cursor:default;color:var(--ash)}
.users .list div.self:hover{background:none;color:var(--ash)}
.users .list div.on{color:#e2c4ff}
.users .list div.blocked{color:#5f5648;text-decoration:line-through}
.users .list div.blocked::before{background:#362b1f;box-shadow:none}
.nmenu{position:fixed;z-index:60;display:none;min-width:190px;padding:4px;
background:linear-gradient(180deg,var(--stone-3),var(--stone));border:2px double var(--gold-lo);box-shadow:0 0 0 1px #000,0 8px 24px #000}
.nmenu.open{display:block}
.nmenu .hd{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px 8px;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);padding:8px 10px 10px;border-bottom:1px solid var(--gold-lo);margin-bottom:3px;text-align:center}
.nmenu .hd .hd-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:150px}
.nmenu .hd .ava-menu{width:54px;height:54px;font-size:22px;margin-right:0;flex:none;border-width:3px}
.nmenu .hd .lvl{margin-left:0}
.nmenu button{display:block;width:100%;text-align:left;font:inherit;color:var(--bone);background:none;border:1px solid transparent;padding:5px 8px;cursor:pointer}
.nmenu button:hover,.nmenu button:focus-visible{color:var(--gold-hi);border-color:var(--gold-lo);background:rgba(201,162,74,.1);outline:none}
.nmenu button.danger{color:#e07a7a}
.nmenu button.danger:hover,.nmenu button.danger:focus-visible{color:#ff9c9c;border-color:#7a2a2a;background:rgba(179,38,30,.15)}
.users .hint{padding:4px 8px 6px;font-size:11px;color:#5f5648;font-style:italic;border-top:1px solid #2a2119}
.users .list div.unread{color:#e2c4ff;text-shadow:0 0 6px rgba(200,150,255,.8)}
.users .list div.unread::before{background:#c9a3e6;box-shadow:0 0 6px rgba(200,150,255,.9)}
.users .hd.frhd{border-top:1px solid var(--gold-lo)}
/* build 299: the Online bar is a tab strip on a phone and plain centred text everywhere else.
   Desktop keeps exactly what it had -- the word "Online" over one list and "Friends" over the
   other -- so .utab is stripped back to look like the text it replaced, and the second tab is
   simply not shown there. */
/* the 24px floor lives HERE, on the base rule, not on the phone rule below it. The phone styling
   is scoped to .users-stacked, which is a class JS sets after measuring where the panel landed --
   so there are real moments, and whole harness surfaces, where the tab is a live button with none
   of that styling on it. taps24 caught exactly that: 49x16 and 106x22. A minimum belongs on the
   control itself, never on a conditional dressing of it. */
.users .hd .utab{font:inherit;color:inherit;letter-spacing:inherit;background:none;border:none;padding:0 4px;cursor:default;
min-height:24px;display:inline-flex;align-items:center;justify-content:center}
.users .hd #uTabFriends{display:none}
.users .list div.f-online{color:var(--gold-hi);text-shadow:0 0 6px rgba(241,217,138,.6)}
.users .list div.f-online::before{background:var(--leaf);box-shadow:0 0 6px rgba(90,161,90,.9)}
.users .list div.f-offline{color:#5f5648}
.users .list div.f-offline::before{background:#362b1f;box-shadow:none}
.users .list div.f-away::before{background:var(--gold);box-shadow:0 0 5px rgba(201,162,74,.7)}
.users .list div.f-busy::before{background:var(--blood);box-shadow:0 0 5px rgba(179,38,30,.7)}
.users .list div.f-idle::before{background:#5f6b7a;box-shadow:0 0 5px rgba(95,107,122,.6)}
.users .list .off{font-size:10px;font-style:italic;color:#4a4238}
.users .list .empty{color:#5f5648;font-style:italic;font-size:11px;cursor:default;white-space:normal;padding:2px}
.users .list .empty::before{display:none}
.users .list div.st-away::before{background:var(--gold);box-shadow:0 0 5px rgba(201,162,74,.7)}
.users .list div.st-busy::before{background:var(--blood);box-shadow:0 0 5px rgba(179,38,30,.7)}
.users .list div.st-idle::before{background:#5f6b7a;box-shadow:0 0 5px rgba(95,107,122,.6)}
/* Idle overrides whatever colour the name would otherwise have (including the lilac glow an
   unread whisper gives it) -- someone who's stepped away shouldn't read as more "lit up" than
   someone who's actually here. The higher-specificity .unread.st-idle rule is what wins that
   fight; without it the single .unread class would still win on source order alone. */
.users .list div.st-idle{color:var(--ash);text-shadow:none}
.users .list div.unread.st-idle{color:var(--ash);text-shadow:none}
.users .list .stag{font-size:10px;font-style:italic;color:#8f8371;margin-left:2px}
.users .list .fg-hd{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-lo);text-transform:uppercase;padding:6px 2px 2px;white-space:nowrap}
.users .list .fg-hd:first-child{padding-top:2px}
.users .list div.f-away{color:var(--gold)}
.users .list div.f-busy{color:#e07a7a}
.users .list div.f-idle{color:#7a8494}
/* .savebtn/.notifbtn were missing from this list, so "Save with email" and "Notifications" rendered as
   the browser's stock light-grey buttons among the dark ones -- v66 brings them in line. */
.status .statusbtn,.status .soundbtn,.status .dmbtn,.status .avabtn,.status .morebtn,.status .bugbtn,.status .leaderboardbtn,.status .savebtn,.status .notifbtn,.status .whisperbtn,.status .reportsbtn,.status .ideabtn{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);padding:1px 8px;cursor:pointer;border-radius:2px;flex:none}
.status .statusbtn:hover,.status .soundbtn:hover,.status .dmbtn:hover,.status .avabtn:hover,.status .morebtn:hover,.status .bugbtn:hover,.status .leaderboardbtn:hover,.status .savebtn:hover,.status .notifbtn:hover,.status .whisperbtn:hover,.status .reportsbtn:hover,.status .ideabtn:hover{color:var(--gold-hi);border-color:var(--gold)}
.status .avabtn{padding:1px 6px}
.ava-thumb{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;background:#251e19;color:var(--gold);font-size:12px;line-height:1;overflow:hidden;vertical-align:-3px}
.ava-thumb img{width:16px;height:16px;border-radius:50%;object-fit:cover;display:block}
.status .statusbtn[data-status="online"]{color:var(--leaf);border-color:#2f5a34}
.status .statusbtn[data-status="away"]{color:var(--gold);border-color:var(--gold-lo)}
.status .statusbtn[data-status="busy"]{color:#e07a7a;border-color:#7a2a2a}
.status .statusbtn[data-status="idle"]{color:#7a8494;border-color:#3a4048}
.status .soundbtn,.status .dmbtn{padding:1px 6px}
.status .dmbtn[aria-pressed="true"]{color:#e07a7a;border-color:#7a2a2a;text-decoration:line-through}
/* Mobile bottom-bar declutter: on a wide screen the "more" button never shows and #statusPopover
   is display:contents, so its buttons (avatar, save/key, sound, reports) render inline in .status
   exactly as before -- nothing changes for desktop. Below 500px they disappear from the row and
   live inside a small popover the "..." button opens instead, so the row itself only ever shows
   the sign-on text, the status dot, and the DM toggle. */
#moreBtn{display:none}
#statusPopover{display:contents}
/* Labels next to the popover's icons (Change picture / Save with email / Sound / Reports) --
   hidden everywhere by default since on a wide screen these same buttons render inline in the
   status bar itself (display:contents flattens #statusPopover there) and there's no room for
   text next to them; the mobile media query below is the only place that turns them back on. */
.popover-label{display:none}
/* Hidden on a wide screen for the same reason .popover-label is: #statusPopover is display:contents
   there, flattening its children straight into the .status bar, so an always-visible text node
   here would show up as a stray line of text sitting among the icon buttons. Only meant to be
   read inside the actual mobile popover, where the media query below turns it back on. */
.popover-version{display:none}
@media (max-width:500px){
.status{position:relative}
#moreBtn{display:inline-flex;align-items:center;justify-content:center}
#statusPopover{display:none;flex-direction:column;gap:6px;position:absolute;right:8px;bottom:32px;
background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);outline:1px solid #000;
padding:8px;border-radius:4px;z-index:48;box-shadow:0 0 0 1px #000,0 6px 18px #000;min-width:190px} /* 48: above the Messages dock's pill (45), which floats right where this opens */
#statusPopover.open{display:flex}
#statusPopover .cell{width:100%;display:flex;align-items:center;gap:8px;text-align:left}
#statusPopover .popover-label{display:inline;font-size:11px}
#statusPopover .popover-version{display:block;font-size:9px;color:var(--ash);opacity:.5;text-align:center;
padding-top:5px;margin-top:2px;border-top:1px solid var(--gold-lo)}
}
/* whisper conversations -- each one is a .im view inside the Messages dock (see .dm-dock at the
   end of this file). They used to be free-floating fixed windows with their own z-index band,
   drag bar and resize corners; now they fill the dock's body and only the active one is shown. */
.im{position:absolute;inset:0;display:flex;flex-direction:column;min-height:0;color:var(--bone)}
.im .bar{display:flex;align-items:center;gap:8px;padding:5px 8px;-webkit-user-select:none;user-select:none;flex:none;
background:linear-gradient(180deg,#2c1e36,#110918);border-bottom:2px solid #7a4bb0;box-shadow:0 2px 0 #000}
/* Header status dot for who this window is with -- same presence-dot classes/colors the threads
   board uses (see presence-dot rules above), just placed here instead of per-message since a
   whisper only ever has one other person. margin:0 since .bar's own flex `gap` already spaces it
   from .wava/.nm -- the default presence-dot margin would double up. */
.im .bar .nm-dot{margin:0}
.im .bar .nmwrap{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.im .bar .nm{flex:none;font:700 13px Cinzel,Georgia,serif;letter-spacing:1.5px;color:#e2c4ff;text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}
.im .bar .nm:hover,.im .bar .nm:focus-visible{text-decoration:underline;outline:none}
.im .bar .x,.im .bar .buzz,.im .bar .back{font:700 13px Cinzel,Georgia,serif;color:#c9a3e6;background:none;border:1px solid #7a4bb0;width:22px;height:20px;line-height:16px;cursor:pointer;padding:0;flex:none}
.im .bar .x:hover,.im .bar .buzz:hover,.im .bar .back:hover{color:#fff;border-color:#e2c4ff;box-shadow:0 0 8px rgba(200,150,255,.6)}
/* back arrow to the inbox: a shade bigger than the other bar buttons, it is the main way out */
.im .bar .back{width:26px;font-size:18px;line-height:14px}
/* build 284: the whisper title bar. Three buttons pinned at 22x20 (back 26x20) and the name at
   231x16 -- all four under WCAG 2.5.8's 24x24, found when the whisper surface was added to the
   sweep in 283.

   These matter more than their size suggests, and it is the ADJACENCY not the pixels: Buzz and
   Collapse sit 8px apart, so a missed tap does not do nothing, it does the neighbouring thing.
   Miss Buzz and the conversation collapses; miss Collapse and you have buzzed the person.

   TWO mechanisms, because one does not cover both:
   - The buttons carry an invisible ::after. Padding cannot work on them: `*{box-sizing:border-box}`
     at line 31 means padding eats the fixed 22x20 rather than adding to it. The bar sets no
     overflow, so nothing clips the pseudo-element, and 22->24 wide only spends 1px each side of an
     8px gap -- the three targets stay 6px apart and do not steal from one another.
   - `.nm` cannot use the ::after at all: it sets overflow:hidden for its ellipsis, which clips a
     pseudo-element exactly as the scrolling chip strip did in 282. It has no explicit height, so
     padding DOES grow its hit box, and a matching negative margin hands the space straight back to
     the layout -- the same give-and-take build 274 used for the header glow. The bar does not
     change height and the ellipsis still works, because overflow clips the text to the padding box
     while the padding itself stays part of the element. */
@media all{   /* build 286: was (hover:none) and (pointer:coarse); a mouse is precise but WCAG 2.5.8 does not exempt it, and two sets of sizes is two things to keep right */
  .im .bar .x,.im .bar .buzz,.im .bar .back{position:relative}
  .im .bar .x::after,.im .bar .buzz::after,.im .bar .back::after{content:"";position:absolute;
    left:50%;top:50%;transform:translate(-50%,-50%);width:24px;height:24px}
  /* Bottom margin stays at 0 on purpose. `margin:-4px 0` handed BOTH pads back to the layout,
     which pulled `.im-sub` ("Online") up over the name's lower padding -- and since the sub paints
     later it won those pixels, leaving the name 21 tall instead of 24. Cancelling only the top
     keeps the bar's growth to 4px and pushes the sub clear. */
  .im .bar .nm{padding:4px 0;margin:-4px 0 0}
}
.im .bar .buzz{font-size:13px}
.im.shake,.dm-dock.shake{animation:gcshake .4s}
@keyframes gcshake{10%,90%{transform:translateX(-1px)}20%,80%{transform:translateX(2px)}30%,50%,70%{transform:translateX(-4px)}40%,60%{transform:translateX(4px)}}
.im .ilog{flex:1 1 auto;min-height:60px;overflow-y:auto;padding:6px 8px;margin:6px 6px 0;line-height:1.45;word-wrap:break-word;scrollbar-color:#7a4bb0 #0f0d0b;
background:linear-gradient(180deg,#050207,#0e090e);border:1px solid #4d2f6b;box-shadow:inset 0 0 16px #000}
@media all{   /* build 286: was (hover:none) and (pointer:coarse); a mouse is precise but WCAG 2.5.8 does not exempt it, and two sets of sizes is two things to keep right */
  .log,.im .ilog{line-height:1.95}
  .log .rpt-msg,.im .ilog .rpt-msg{position:relative}
  .log .rpt-msg::after,.im .ilog .rpt-msg::after{content:"";position:absolute;left:50%;top:50%;
    transform:translate(-50%,-50%);width:24px;height:24px}
}
.im .ilog .m b{font-weight:normal;font-family:Cinzel,Georgia,serif;font-size:12px}
.im .ilog .me b{color:var(--gold-hi)} .im .ilog .them b{color:#e2c4ff}
/* Names in a whisper transcript open the same Get Info/Whisper/Tag in Chat/Block menu a name click
   opens everywhere else (see win.log.onclick in app.js) -- same hover treatment as .log b.who. */
.im .ilog .m b.who{cursor:pointer}
.im .ilog .m b.who:hover,.im .ilog .m b.who:focus-visible{text-decoration:underline;outline:none}
.im .ilog .sys{color:var(--sys);font-style:italic}
.im .ilog .t{color:#5a4f63;font-size:11px;margin-right:6px}
.im .ilog .e{font-size:16px;vertical-align:-2px}
/* build 313: WhatsApp-style marks at the end of each whisper you send (updateTicks in app.js), in place
   of the old "Seen" line. Grey: sent. Blue: delivered to their app. Two blue, overlapping: read. The
   blue is WhatsApp's own read blue, which the owner asked for by name. */
.im .ilog .m .tick{display:inline-block;margin-left:5px;vertical-align:-1px;line-height:0;white-space:nowrap}
.im .ilog .m .tick svg{display:block}
.im .ilog .m .tick-sent{color:#8f8371}
.im .ilog .m .tick-delivered,.im .ilog .m .tick-read{color:#53bdeb}
/* Composer. The dock is only 260-340px wide on desktop, so the attachment buttons sit in a row
   UNDER the field there (the field and Send get the full width); on a phone the dock is
   full-screen and everything fits on one line (the emoji button steps aside for the phone's own
   keyboard -- see the max-width:500px rule). */
.im .icomp{display:grid;grid-template-columns:auto auto auto auto 1fr auto;gap:6px;padding:6px;flex:none}
@media (min-width:501px){
  /* v111: a fourth icon column for the mic. The named areas are why this had to change in step
     with the markup -- a button added to .icomp without a cell to sit in silently lands in the
     next free grid slot, which here is the one the textarea occupies. */
  .im .icomp{grid-template-columns:auto auto auto auto 1fr;grid-template-areas:"ta ta ta ta send" "emo media games mic ."}
  .im .icomp textarea{grid-area:ta}
  .im .icomp .btn.emo{grid-area:emo;height:28px;min-width:34px;font-size:14px}
  .im .icomp .btn.media{grid-area:media;height:28px;min-width:34px;font-size:14px}
  .im .icomp .btn.games{grid-area:games;height:28px;min-width:34px;font-size:14px}
  .im .icomp .btn.mic{grid-area:mic;height:28px;min-width:34px;font-size:14px}
  .im .icomp .btn:last-child{grid-area:send}
}
.im .icomp textarea{font:inherit;color:var(--bone);resize:none;height:44px;padding:5px 8px;outline:none;caret-color:#e2c4ff;
background:linear-gradient(180deg,#050207,#0e090e);border:1px solid #4d2f6b;box-shadow:inset 0 0 16px #000}
.im .icomp textarea:focus{box-shadow:inset 0 0 16px #000,0 0 0 1px #a67ad1}
.im .icomp .btn{color:#e2c4ff;border-color:#7a4bb0;background:linear-gradient(180deg,#3a2a48,#110918)}
.im .icomp .btn:hover{box-shadow:inset 0 1px 0 rgba(241,217,138,.15),inset 0 -2px 4px #000,0 0 0 1px #000,0 0 10px rgba(166,122,209,.6)}
.im .icomp .btn.media,.im .icomp .btn.games,.im .icomp .btn.emo,.im .icomp .btn.mic{font-size:15px;min-width:38px;padding:0 6px}
/* the dock's inbox: one .im-tab row per conversation (newest activity first -- app.js moves a row
   to the top when a message lands in it) */
.im-tray{display:flex;flex-direction:column}
.im-tab{position:relative;display:flex;align-items:center;gap:10px;padding:8px 30px 8px 10px;cursor:pointer;-webkit-user-select:none;user-select:none;
color:#e2c4ff;border-bottom:1px solid #2a1f33;background:linear-gradient(180deg,rgba(49,37,58,.35),rgba(26,19,32,.35));
touch-action:pan-y;transition:transform .18s ease,opacity .18s ease,background .15s ease}
.im-tab:hover,.im-tab:focus-visible{background:linear-gradient(180deg,#2c1e36,#170d1f);outline:none}
.im-tab.dragging{transition:none}
.im-tab .tava{flex:none;display:inline-flex}
.im-tab .tava .ava,.im-tab .tava .ava-fallback{width:34px;height:34px;font-size:14px;margin:0;vertical-align:0;border-color:#7a4bb0}
.im-tab .tmeta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.im-tab .nm{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.im-tab .snippet{font-size:12px;color:var(--ash);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:1em}
.im-tab.unread .nm{color:#fff;text-shadow:0 0 8px rgba(200,150,255,.6)}
.im-tab.unread .snippet{color:var(--bone)}
.im-tab .badge{flex:none;background:var(--blood);color:#fff;font:700 10px Georgia,serif;min-width:16px;height:16px;line-height:16px;text-align:center;border-radius:8px;padding:0 4px;box-shadow:0 0 0 1px #000}
.im-tab.flash{animation:tabflash 1s ease-in-out 2}
@keyframes tabflash{50%{background:linear-gradient(180deg,#4a3560,#241534);box-shadow:inset 0 0 18px rgba(200,150,255,.6)}}
/* Small always-present remove control, for anyone who can't (or doesn't know to) swipe a row away --
   keyboard and screen-reader users in particular. Dim by default so it doesn't visually compete with
   the swipe gesture; a hover/focus reveal on pointer devices, always reachable by Tab either way. */
.im-tab .tab-close{position:absolute;top:50%;right:6px;transform:translateY(-50%);width:18px;height:18px;line-height:16px;text-align:center;
padding:0;font:700 11px Georgia,serif;color:var(--ash);background:none;border:1px solid transparent;border-radius:50%;
cursor:pointer;opacity:.45}
.im-tab .tab-close:hover,.im-tab .tab-close:focus-visible{opacity:1;color:#fff;background:var(--blood);border-color:#000;outline:none}
/* Swipe-to-dismiss hint: a soft red wash grows in behind the row as it's dragged far enough to let go
   and close it, so the gesture has visible feedback before release. */
.im-tab.past-threshold{background:linear-gradient(180deg,#4a2130,#240a18)}
.users .list div::before{content:"";display:inline-block;width:7px;height:7px;transform:rotate(45deg);background:var(--leaf);
border:1px solid var(--gold-lo);margin-right:7px;vertical-align:0;box-shadow:0 0 5px rgba(90,161,90,.7)}
.compose{grid-column:1 / -1;display:grid;grid-template-columns:auto auto 1fr auto;gap:6px;align-items:stretch;position:relative}
.compose textarea{font:inherit;color:var(--bone);resize:none;height:60px;padding:6px 8px;outline:none;caret-color:var(--gold-hi)}
.compose textarea::placeholder{color:#5f5648}
.compose textarea:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold),0 0 10px rgba(201,162,74,.35)}
.btn:disabled,.compose textarea:disabled{opacity:.45;cursor:not-allowed;filter:grayscale(.4)}
.cooldown{position:absolute;left:0;right:0;bottom:100%;margin-bottom:6px;padding:6px 10px;font:700 12px Cinzel,Georgia,serif;
letter-spacing:.5px;text-align:center;color:#f1d98a;background:linear-gradient(180deg,#362508,#110906);
border:2px double var(--gold-lo);outline:1px solid #000;box-shadow:0 0 0 1px #000,0 4px 14px #000;z-index:6}
.cooldown.muted{color:#ffb3b3;border-color:#7a2a2a}
/* Sits in the same spot as .cooldown above (bottom:100% of the composer it's inside) and yields
   that spot entirely when a cooldown/mute message is up (see renderRoomTyping() in app.js), so
   the two never stack. Its own background matters more here than .cooldown's does: the main
   compose row has a real gap above it (.body's grid gap), but a whisper window's .ilog and
   .icomp sit flush against each other with none, so without an opaque backing this would show
   up sitting directly on top of the last line of chat. */
.typing-indicator{position:absolute;left:0;right:0;bottom:100%;margin-bottom:4px;padding:3px 10px;
font-style:italic;font-size:12px;text-align:center;color:var(--sys);pointer-events:none;
background:linear-gradient(180deg,#110906,#1a111f);border-top:1px solid var(--gold-lo)}
.im .icomp{position:relative}
.im .icomp .typing-indicator{font-family:"IM Fell English",Georgia,serif;font-size:11px;color:#c9a3e6;
padding:2px 8px;margin-bottom:0;background:linear-gradient(180deg,#08030a,#1a111f);border-top:1px solid #7a4bb0}
.modal-overlay{position:fixed;inset:0;z-index:70;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.65);padding:16px}
.modal-overlay.hidden{display:none}
.modal{width:100%;max-width:340px;background:linear-gradient(180deg,var(--stone-2),var(--stone));border:3px double var(--gold-lo);
outline:1px solid #000;box-shadow:0 0 0 2px var(--gold),0 0 0 3px #000,0 0 28px #000;padding:16px;text-align:center}
.modal-hd{font:700 16px Cinzel,"Trajan Pro",Georgia,serif;letter-spacing:1.5px;color:var(--gold);text-shadow:0 0 10px rgba(201,162,74,.55);margin-bottom:8px}
.modal-body{font:14px "IM Fell English",Georgia,serif;color:var(--bone);line-height:1.5;margin-bottom:14px}
.modal .btn{min-width:90px}
/* Prompt modal (Away message, Move to Group, ...) -- same input look as the save-your-character
   form, just without a <label> above it since the modal title already says what's being asked. */
.prompt-modal{text-align:left}
.prompt-modal input{width:100%;padding:6px 8px;font:14px "IM Fell English",Georgia,serif;color:var(--bone);
background:linear-gradient(180deg,#050200,#0e0906)}
.prompt-modal .modal-body{font-size:12px;color:var(--ash);margin-bottom:8px}
/* Image lightbox -- reuses .modal-overlay for the full-screen dark backdrop and centering, but
   skips the .modal card: just the picture at (almost) full size, tap/click-outside or ✕ to close. */
.lightbox-overlay{z-index:90;background:rgba(0,0,0,.88);padding:40px 16px}
.lightbox-img{max-width:92vw;max-height:88vh;display:block;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 0 40px #000}
.lightbox-close{position:fixed;top:14px;right:16px;width:34px;height:32px;line-height:28px;font:700 15px Cinzel,Georgia,serif;
color:var(--gold);background:#050200;border:1px solid var(--gold-lo);cursor:pointer;padding:0}
.lightbox-close:hover,.lightbox-close:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
/* Tap-to-refresh prompt shown once app.js notices a new service-worker version has taken over
   this tab (see the controllerchange listener near the bottom of app.js) -- above everything
   else (.lightbox-overlay's 90 included) since it's a "your copy of the whole app is stale"
   notice, not a piece of the app's own UI. Fixed to the bottom so it can't land on top of the
   compose box or a whisper window's own controls. */
.update-banner{position:fixed;left:8px;right:8px;bottom:8px;z-index:95;display:flex;align-items:center;
justify-content:space-between;gap:10px;padding:8px 10px;background:linear-gradient(180deg,#24190f,#0e0906);
border:2px double var(--gold-lo);outline:1px solid #000;box-shadow:0 0 0 1px #000,0 6px 18px #000;
color:var(--bone);font-size:12px;max-width:420px;margin:0 auto}
.update-banner.hidden{display:none}
.btn{font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);cursor:pointer;min-width:66px;padding:0 12px;
background:linear-gradient(180deg,#362b1f,#140e08);border:1px solid var(--gold-lo);
box-shadow:inset 0 1px 0 rgba(241,217,138,.25),inset 0 -2px 4px #000,0 0 0 1px #000;text-shadow:0 1px 0 #000}
.btn:hover{color:var(--gold-hi);border-color:var(--gold);box-shadow:inset 0 1px 0 rgba(241,217,138,.25),inset 0 -2px 4px #000,0 0 0 1px #000,0 0 10px rgba(201,162,74,.5)}
.btn:active{background:linear-gradient(180deg,#140e08,#362b1f);transform:translateY(1px)}
.btn:focus-visible{outline:1px solid var(--gold-hi);outline-offset:2px}
.btn.emo{font-size:18px;min-width:46px;padding:0 6px}
.btn.gif{font-size:11px;min-width:42px;padding:0 6px}
.picker{position:fixed;z-index:56;padding:6px;display:none;grid-template-columns:repeat(8,32px);gap:3px;
background:linear-gradient(180deg,var(--stone-3),var(--stone));border:2px double var(--gold-lo);box-shadow:0 0 0 1px #000,0 8px 24px #000}
.picker.open{display:grid}
.picker button{font-size:18px;width:32px;height:32px;background:#050200;border:1px solid #3a3026;cursor:pointer;padding:0}
.picker button:hover,.picker button:focus-visible{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.6);outline:none}
/* Reaction quick-pick -- same popup shell as .picker above, just a 4-wide grid since it's a
   curated set of 8 rather than the full compose emoji list. */
.rpicker{position:fixed;z-index:57;padding:6px;display:none;grid-template-columns:repeat(4,32px);gap:3px;
background:linear-gradient(180deg,var(--stone-3),var(--stone));border:2px double var(--gold-lo);box-shadow:0 0 0 1px #000,0 8px 24px #000}
.rpicker.open{display:grid}
.rpicker button{font-size:18px;width:32px;height:32px;background:#050200;border:1px solid #3a3026;cursor:pointer;padding:0}
.rpicker button:hover,.rpicker button:focus-visible{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.6);outline:none}
/* Reaction pills under a message/thread post -- square chips rather than rounded pills to match
   this app's sharp-edged Diablo-window look (nothing else here uses border-radius). No more "+"
   button lives here -- reacting is a tap-and-hold (or right-click) on the message itself, see
   attachLongPress in app.js -- so .reactions only ever grows a footprint once there's something
   in it, instead of a permanent extra control sitting on every single message. */
.reactions{display:flex;flex-wrap:wrap;align-items:center;gap:4px}
.reactions:not(:empty){margin-top:3px}
.react-pill{font:11px/16px inherit;background:#050200;border:1px solid #3a3026;color:var(--bone);padding:1px 6px;cursor:pointer}
.react-pill span{color:#8a8070;margin-left:2px}
.react-pill:hover,.react-pill:focus-visible{border-color:var(--gold-lo);outline:none}
.react-pill.mine{border-color:var(--gold);color:var(--gold-hi);box-shadow:0 0 6px rgba(201,162,74,.35)}
.react-pill.mine span{color:var(--gold)}
/* Long-press-in-progress feedback -- a slow fade-in timed roughly to LONG_PRESS_MS so the
   highlight visibly builds while held, giving the same "something's about to happen" cue a
   native app's press-and-hold has, then it's undone instantly on release/cancel. */
.log .m,.tp-posts .tp-post{-webkit-touch-callout:none}
.log .m.pressing,.tp-posts .tp-post.pressing{background:rgba(201,162,74,.14);transition:background-color .45s linear}
/* Level badge -- shown next to a name once someone has actually received at least one reaction
   (see levelBadgeHtml); [hidden] keeps the node in the DOM so a live level-up just reveals and
   updates it rather than needing new markup spliced in. */
.lvl{font-size:9px;color:var(--gold);border:1px solid var(--gold-lo);padding:0 3px;margin-left:4px;letter-spacing:.5px;vertical-align:1px}
/* Ten-wide color tiers (1-9 through 90-99), then a gold eleventh for 100+ -- see levelTier() in
   app.js. Glow grows with the tiers so a high level reads as "more" even before you parse the
   number, capping with both a text glow and a soft box-shadow on the crescent/full/gold-moon tiers
   to make the moon icon actually look lit rather than just tinted. */
.lvl-t1{color:var(--lvl-1);border-color:rgba(238,240,230,.4)}
.lvl-t2{color:var(--lvl-2);border-color:rgba(77,121,230,.5)}
.lvl-t3{color:var(--lvl-3);border-color:rgba(162,89,230,.5)}
.lvl-t4{color:var(--lvl-4);border-color:rgba(241,217,138,.6)}
.lvl-t5{color:var(--lvl-5);border-color:rgba(255,95,168,.5)}
.lvl-t6{color:var(--lvl-6);border-color:rgba(46,211,224,.5)}
.lvl-t7{color:var(--lvl-7);border-color:rgba(57,255,106,.5);text-shadow:0 0 4px rgba(57,255,106,.6)}
.lvl-t8{color:var(--lvl-8);border-color:rgba(255,138,43,.6);text-shadow:0 0 4px rgba(255,138,43,.55)}
.lvl-t9{color:var(--lvl-9);border-color:rgba(201,214,242,.55);text-shadow:0 0 4px rgba(201,214,242,.5)}
.lvl-t10{color:var(--lvl-10);border-color:rgba(245,248,255,.65);text-shadow:0 0 5px rgba(245,248,255,.65)}
.lvl-t11{color:var(--lvl-11);border-color:var(--gold-hi);text-shadow:0 0 6px rgba(255,223,126,.75);box-shadow:0 0 6px rgba(255,223,126,.35)}
.gifpicker{position:fixed;z-index:56;display:none;flex-direction:column;width:280px;max-width:calc(100vw - 20px);
background:linear-gradient(180deg,var(--stone-3),var(--stone));border:2px double var(--gold-lo);box-shadow:0 0 0 1px #000,0 8px 24px #000}
.gifpicker.open{display:flex}
.gifpicker .gsearch{display:flex;gap:4px;padding:6px}
.gifpicker .gsearch input{flex:1;min-width:0;font:inherit;color:var(--bone);padding:5px 6px;outline:none;
background:linear-gradient(180deg,#050200,#0e0906);border:1px solid var(--gold-lo);box-shadow:inset 0 0 10px #000}
.gifpicker .gsearch input:focus{box-shadow:inset 0 0 10px #000,0 0 0 1px var(--gold)}
.gifpicker .gsearch .btn{min-width:40px;padding:0 8px}
.gifpicker .gresults{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;padding:0 6px 6px;max-height:220px;overflow-y:auto;scrollbar-color:var(--gold-lo) #0f0d0b}
/* Square thumbnail cells are sized with the classic padding-top:100% box (height:0, padding-top
   pegged to width) rather than the `aspect-ratio` CSS property. Newer iOS Safari (seen on 26.6.1)
   has a timing bug where an <img> inside an aspect-ratio-sized box can paint using the box's
   not-yet-resolved intrinsic size on first layout -- the row already visible on screen (the top
   row of results) renders with the image cropped against the wrong box, while rows that lay out
   after the picture already has a settled size (effectively everything below the fold) come out
   fine. padding-top:100% has given every browser, iOS included, a fixed pixel height before the
   image ever starts loading, so there's no not-yet-resolved size for it to race against. */
.gifpicker .gresults button{position:relative;display:block;width:100%;height:0;padding:0 0 100%;border:1px solid #3a3026;background:#050200;cursor:pointer;overflow:hidden}
.gifpicker .gresults button:hover,.gifpicker .gresults button:focus-visible{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.6);outline:none}
.gifpicker .gresults img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#050200;display:block}
.gifpicker .gmsg{grid-column:1 / -1;padding:10px 4px;color:var(--ash);font-style:italic;font-size:12px;text-align:center}
/* Posted pictures show as small thumbnails everywhere, never at native size -- click one to see
   it full-size in the lightbox (openLightbox in app.js). */
.log img.gif,.im .ilog img.gif{max-width:160px;max-height:160px;display:block;margin-top:3px;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000;cursor:zoom-in;transition:filter .15s ease}
.log img.gif:hover,.im .ilog img.gif:hover{filter:brightness(1.15)}
.ava{width:23px;height:23px;border-radius:50%;object-fit:cover;vertical-align:-6px;margin-right:5px;display:inline-block;border:1px solid var(--gold-lo)}
.ava-fallback{width:23px;height:23px;border-radius:50%;background:#251e19;color:var(--gold);font:700 12px Cinzel,Georgia,serif;display:inline-flex;align-items:center;justify-content:center;vertical-align:-6px;margin-right:5px;border:1px solid var(--gold-lo)}
.users .list div .ava,.users .list div .ava-fallback{width:19px;height:19px;font-size:11px;vertical-align:-5px}
.wava{display:inline-flex;vertical-align:middle;margin-right:2px}
.wava .ava,.wava .ava-fallback{width:21px;height:21px;font-size:11px;margin-right:0;border-color:#7a4bb0}
.mention{color:var(--gold-hi);font-weight:700}
.m.mention-me{background:rgba(201,162,74,.14);box-shadow:inset 2px 0 0 var(--gold)}
.mention-menu{position:fixed;z-index:56;display:none;flex-direction:column;min-width:150px;max-width:240px;max-height:190px;overflow-y:auto;
background:linear-gradient(180deg,var(--stone-3),var(--stone));border:2px double var(--gold-lo);box-shadow:0 0 0 1px #000,0 8px 24px #000;scrollbar-color:var(--gold-lo) #0f0d0b}
.mention-menu.open{display:flex}
.mention-menu button{display:block;width:100%;text-align:left;padding:6px 10px;background:none;border:none;border-bottom:1px solid #2a2620;
color:var(--bone);font:600 13px Cinzel,Georgia,serif;cursor:pointer}
.mention-menu button:last-child{border-bottom:none}
.mention-menu button.active,.mention-menu button:hover{background:rgba(201,162,74,.18);color:var(--gold-hi)}
.status{display:flex;justify-content:space-between;gap:8px;padding:5px 12px;font-size:12px;color:var(--ash);
border-top:2px solid var(--gold-lo);background:#050200;box-shadow:inset 0 2px 0 #000}
.status .cell{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* "made by" + version watermark for the roulette teaser panel -- .roulette-panel is position:fixed,
   giving it a stable positioning context, so an absolute corner watermark works cleanly there with
   no collision risk against other content. Kept as an overlay since that's never been an issue. */
.room-watermark{position:absolute;right:10px;bottom:34px;font:10px Cinzel,Georgia,serif;letter-spacing:1px;
color:var(--ash);opacity:.65;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:1}
@media (max-width:500px){.room-watermark{bottom:42px;right:8px;font-size:9px}}
/* Small "made by" + version footer for the main chat room -- the login screen has its own copy
   in .madeby, but that whole block disappears once #login is hidden at sign-on, so the room gets
   its own. Earlier this sat as an absolute overlay pinned above the status bar, but that kept
   landing on/inside the status bar at various widths since the assumed gap never quite matched
   the status bar's real height. Simpler and collision-proof: a normal in-flow row, last child of
   .win, right after .status -- it just becomes the next line in the window instead of floating
   over anything. */
.room-footer{text-align:center;padding:3px 10px 4px;font:10px Cinzel,Georgia,serif;letter-spacing:1px;
color:var(--ash);opacity:.65;pointer-events:none;-webkit-user-select:none;user-select:none;border-top:1px solid var(--gold-lo);
background:#050200}
@media (max-width:500px){.room-footer{padding:2px 8px 3px;font-size:9px}}
.login{grid-column:1 / -1;padding:22px 12px 18px;text-align:center;position:relative}
.login h1{font:700 30px Cinzel,Georgia,serif;letter-spacing:3px;color:var(--gold);margin:0 0 4px;
text-shadow:0 0 14px rgba(201,162,74,.5),0 2px 0 #000}
.login .rule{width:180px;height:1px;margin:6px auto 12px;background:linear-gradient(90deg,transparent,var(--gold),transparent)}
.login .tag{color:var(--ash);font-style:italic;margin-bottom:16px}
/* Deliberately tiny and low-contrast -- this exists purely so "which build is this device
   actually running" has an instant answer without opening dev tools, not to be a visible piece
   of UI. See BUILD_NUMBER in app.js. */
.buildtag{color:var(--ash);opacity:.4;font-size:10px;letter-spacing:.5px;margin:-10px 0 14px}
.login label{display:block;margin:0 auto 6px;width:240px;text-align:left;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold)}
.login input{font:inherit;color:var(--bone);width:240px;padding:6px 8px;display:block;margin:0 auto 10px;outline:none}
.login input:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold)}
.login .err{color:var(--blood);min-height:16px;margin-bottom:6px}
/* The gypsy woman on the sign-on screen. The chat log already uses this PNG as a faint
   watermark; here she is a deliberate piece of furniture filling the dead space to the right of
   the form, so she is drawn larger and lifted a little with brightness() -- the artwork's fade is
   baked into its own alpha, so CSS opacity can only take it down, never up.
   The form is not re-centred by hand: .login keeps text-align:center and simply gains a
   padding-right the width of the picture, so the whole column re-centres itself in what is left.
   She is absolutely positioned inside that reserved strip, which keeps her out of the flow --
   nothing below her can be pushed around if the form grows (an error line, the Turnstile box).
   Below 620px she stops being a side panel and becomes a footer instead: a portrait phone has
   no horizontal dead space to fill, but it has plenty of vertical room under the button, and
   empty space was the whole reason she was added. There she is static rather than absolute, so
   she takes part in the flow and the panel grows to hold her. */
.login .gw{display:block;position:static;width:min(62%,240px);height:auto;margin:14px auto 0;
pointer-events:none;-webkit-user-select:none;user-select:none;filter:brightness(1.3)}
.login .madeby{margin-top:14px;font:11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash)}
@media (min-width:620px){
.login{padding-right:280px}
/* a notch smaller than the 30px default: the heading now has to fit beside the picture rather
   than across the whole window, and at 30px it is within a few pixels of wrapping */
.login h1{font-size:27px}
/* wide enough now for her to leave the flow and stand beside the form instead */
.login .gw{position:absolute;margin:0;right:4px;top:50%;transform:translateY(-50%);width:280px}
}
@media (min-width:760px){
.login{padding-right:400px}
.login .gw{width:400px;right:6px}
}
.admin-fields{margin:0 auto 4px;width:240px}
.admin-fields label{display:block;margin:0 auto 6px;width:100%;text-align:left;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold)}
.admin-fields input{font:inherit;color:var(--bone);width:100%;padding:6px 8px;display:block;margin:0 auto 10px;outline:none}
.admin-fields input:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold)}
.turnstile-wrap{display:flex;justify-content:center;margin:4px auto 10px;min-height:65px}
.admin-toggle-wrap{margin-top:10px}
.admin-toggle{font:inherit;font-size:11px;font-style:italic;color:var(--ash);background:none;border:none;cursor:pointer;padding:0;text-decoration:underline}
.admin-toggle:hover,.admin-toggle:focus-visible{color:var(--gold-hi);outline:none}
.hidden{display:none !important}
/* Flame: a squash-and-stretch flicker on the flame itself, plus a glow that surges on the lantern
   as a whole. Both use uneven stops (11/24/38/52/66/80) rather than a tidy pulse, because evenly
   spaced keyframes read as a machine breathing; the odd spacing is what makes it look like fire.
   The flame's transform-origin is its own base, so it stretches and gutters from the wick instead
   of ballooning around its middle. The two animations run at durations that do not divide into
   each other, and the right-hand lantern is offset again, so the pair never settles into a loop. */
@keyframes lt-flicker{0%,100%{transform:scale(1,1);opacity:1}
11%{transform:scale(.82,1.2);opacity:.72}
24%{transform:scale(1.14,.88);opacity:1}
38%{transform:scale(.88,1.14);opacity:.66}
52%{transform:scale(1.12,.92);opacity:.97}
66%{transform:scale(.85,1.18);opacity:.8}
80%{transform:scale(1.08,.95);opacity:1}}
@keyframes lt-glow{0%,100%{filter:drop-shadow(0 0 12px rgba(163,42,255,.8)) drop-shadow(0 0 4px rgba(214,80,255,.85))}
22%{filter:drop-shadow(0 0 22px rgba(163,42,255,1)) drop-shadow(0 0 7px rgba(224,114,255,1))}
45%{filter:drop-shadow(0 0 14px rgba(163,42,255,.85)) drop-shadow(0 0 4px rgba(214,80,255,.9))}
68%{filter:drop-shadow(0 0 24px rgba(163,42,255,1)) drop-shadow(0 0 9px rgba(224,114,255,1))}}
@media (prefers-reduced-motion:no-preference){
.title .lantern .lt-flame{animation:lt-flicker 1.1s ease-in-out infinite}
.title .lantern{animation:lt-glow 2.3s ease-in-out infinite}
.title .lantern:last-of-type .lt-flame{animation-duration:1.3s;animation-delay:-.5s}
.title .lantern:last-of-type{animation-duration:2.7s;animation-delay:-1.1s}
}

/* ---------- threads board: a standalone "/gen/ — General" board page ----------
   One single board, no category tabs (per the brief, that can come later). It always opens as a
   full-page takeover -- replacing the chat window entirely, at EVERY viewport width -- rather
   than living in a cramped sidebar next to a dimmed chat. That used to be two different things
   (a persistent 260px sidebar above 1340px that widened when a thread was open, versus a
   full-screen swap below that width); now it's the one full-page layout everywhere, so a wide
   desktop window gets a proper 4chan-style catalog (a wrapping grid of small-thumbnail tiles)
   instead of a squeezed column, and a phone gets exactly what it already got. */
.threads-panel{display:none;flex-direction:column;
background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8}
.tp-hd{display:flex;align-items:center;justify-content:center;gap:8px;padding:10px 10px 8px;flex:none;
background:linear-gradient(180deg,#281f15,#110c07);border-bottom:2px solid var(--gold-lo);box-shadow:0 2px 0 #000;
font:700 15px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold);text-shadow:0 0 8px rgba(201,162,74,.5)}
.tp-back{font:700 13px Cinzel,Georgia,serif;color:var(--gold);background:none;border:1px solid var(--gold-lo);width:24px;height:22px;line-height:18px;cursor:pointer;padding:0;flex:none}
.tp-back:hover{color:var(--gold-hi);border-color:var(--gold)}
/* Shiny diamond flourishes flanking the thread title -- only when a thread is open (.tp-detail),
   not on the board's catalog header. Rotated squares with a gem-like radial-gradient highlight,
   same technique/colors as the DM window's purple .im .bar .gem. */
.tp-detail .tp-hd span{display:inline-flex;align-items:center;gap:9px}
.tp-detail .tp-hd span::before,.tp-detail .tp-hd span::after{content:"";width:9px;height:9px;flex:none;
transform:rotate(45deg);background:radial-gradient(circle at 35% 35%,#e0b3ff,#7a4bb0 60%,#240d34);
border:1px solid #4d2f6b;box-shadow:0 0 6px rgba(224,179,255,.8),0 0 2px #000}
.tp-list,.tp-detail{display:flex;flex-direction:column;flex:1;min-height:0}
.tp-newwrap{padding:10px;flex:none;width:100%;max-width:700px;margin:0 auto;box-sizing:border-box}
/* "Create new post": a Diablo II stat-point button -- an embossed red square with a gold cross --
   with the label beside it, sized to its content instead of stretched across the column. The
   square is all CSS: a red bevel (light top edge, dark bottom edge) inside a thin gold frame, and
   the cross is two gold bars from the pseudo-elements. Pressing sinks it a pixel. */
.tp-new{display:inline-flex;align-items:center;gap:10px;width:auto;padding:2px 6px 2px 2px;background:none;border:0;cursor:pointer;
font:700 13px Cinzel,Georgia,serif;letter-spacing:1.2px;color:var(--gold);text-shadow:0 0 6px rgba(201,162,74,.35)}
.tp-new-gem{position:relative;width:34px;height:34px;flex:none;border-radius:3px;
background:linear-gradient(160deg,#c0392e 0%,#8e1c12 45%,#4a0b07 100%);border:1px solid #2a0705;
box-shadow:inset 0 1px 0 rgba(255,160,140,.6),inset 1px 0 0 rgba(255,130,110,.3),inset 0 -2px 0 rgba(0,0,0,.65),inset -1px 0 0 rgba(0,0,0,.45),
0 0 0 1px var(--gold-lo),0 0 0 2px #000,0 2px 6px #000}
.tp-new-gem::before,.tp-new-gem::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
background:linear-gradient(180deg,#f6dd8f,#c9a24a 55%,#8a6821);box-shadow:0 1px 2px rgba(0,0,0,.8),0 0 6px rgba(246,221,143,.35)}
.tp-new-gem::before{width:18px;height:5px}
.tp-new-gem::after{width:5px;height:18px}
.tp-new:hover .tp-new-gem,.tp-new:focus-visible .tp-new-gem{box-shadow:inset 0 1px 0 rgba(255,160,140,.6),inset 1px 0 0 rgba(255,130,110,.3),inset 0 -2px 0 rgba(0,0,0,.65),inset -1px 0 0 rgba(0,0,0,.45),
0 0 0 1px var(--gold),0 0 0 2px #000,0 2px 6px #000,0 0 12px rgba(201,162,74,.6)}
.tp-new:hover .tp-new-label,.tp-new:focus-visible .tp-new-label{color:var(--gold-hi)}
.tp-new:focus-visible{outline:none}
.tp-new:active .tp-new-gem{transform:translateY(1px);box-shadow:inset 0 2px 3px rgba(0,0,0,.7),0 0 0 1px var(--gold-lo),0 0 0 2px #000}
.tp-newpost{padding:0 10px 10px;display:flex;flex-direction:column;gap:6px;flex:none;width:100%;max-width:700px;margin:0 auto;box-sizing:border-box}
.tp-newpost textarea,.tp-reply textarea{font:inherit;color:var(--bone);resize:none;padding:6px 8px;outline:none;caret-color:var(--gold-hi)}
.tp-newpost textarea{height:64px}
.tp-newpost textarea:focus,.tp-reply textarea:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold)}
.tp-composebar{display:flex;gap:6px;align-items:center;flex:none}
.tp-composebar .tp-img{font-size:11px;min-width:38px;padding:0 6px;flex:none}
.tp-preview-wrap{position:relative;display:inline-block;align-self:flex-start;margin:2px 0;flex:none}
.tp-preview-img{max-width:120px;max-height:120px;display:block;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000}
.tp-img-remove{position:absolute;top:-8px;right:-8px;width:20px;height:20px;line-height:16px;padding:0;font-size:12px;color:#fff;
background:var(--blood);border:1px solid #000;border-radius:50%;cursor:pointer}
.tp-img-remove:hover{background:#d33}
.tp-newactions{display:flex;gap:6px;justify-content:flex-end}
/* Catalog grid, like 4chan's board index: small fixed-width tiles that wrap to fill however much
   width the page has, instead of one narrow full-width column. */
.tp-items{flex:1;overflow-y:auto;padding:12px;display:flex;flex-wrap:wrap;align-content:flex-start;justify-content:center;gap:10px;scrollbar-color:var(--gold-lo) #0f0d0b}
.tp-item{display:flex;flex-direction:column;width:150px;text-align:left;padding:6px;cursor:pointer;font:inherit;color:var(--bone);background:#050200;border:1px solid #3a3026}
.tp-item:hover,.tp-item:focus-visible{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.4);outline:none}
.tp-op{font:700 11px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold-hi);margin-bottom:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-preview{font-size:11px;line-height:1.35;color:var(--bone);overflow:hidden;display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical}
.tp-meta{font-size:9px;color:var(--ash);margin-top:4px;font-style:italic}
.tp-empty{padding:16px 8px;text-align:center;color:#5f5648;font-style:italic;font-size:12px;width:100%}
/* Catalog pager -- appears once there's more than one page of threads (THREADS_PAGE_SIZE in app.js). */
.tp-pages{flex:none;display:flex;flex-wrap:wrap;justify-content:center;gap:6px;padding:0 10px 12px}
.tp-page{font:700 12px Cinzel,Georgia,serif;color:var(--bone);background:#050200;border:1px solid var(--gold-lo);
width:26px;height:24px;line-height:22px;padding:0;cursor:pointer}
.tp-page:hover,.tp-page:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
.tp-page.active{color:#1a1511;background:linear-gradient(180deg,var(--gold-hi),var(--gold));border-color:var(--gold-hi)}
.tp-posts{flex:1;overflow-y:auto;padding:10px 14px;line-height:1.5;word-wrap:break-word;scrollbar-color:var(--gold-lo) #0f0d0b;
width:100%;max-width:900px;margin:0 auto;box-sizing:border-box}
.tp-posts .tp-post{margin-bottom:8px}
.tp-posts .tp-post b{font-weight:normal;font-family:Cinzel,Georgia,serif;font-size:12px;letter-spacing:.5px;color:var(--them)}
.tp-posts .tp-post.op b{color:var(--me)}
/* Admin-authored posts (including an admin OP) render in the site's admin red, same convention as
   admin names in the main chat log/online list. Must come after .op so red wins over the OP gold
   when a post is both. Pinning to the top of the list is handled in appendThreadPost() (app.js). */
.tp-posts .tp-post.admin b{color:var(--admin);text-shadow:0 0 8px rgba(209,59,47,.45)}
.tp-posts .tp-post .t{color:#5f5648;font-size:11px;margin-right:6px}
/* Names in the threads board open the same Get Info/Whisper/Tag in Chat/Block menu a name click
   opens everywhere else (see tpPosts.onclick in app.js) -- same hover treatment as .log b.who. */
.tp-posts .tp-post b.who{cursor:pointer}
.tp-posts .tp-post b.who:hover,.tp-posts .tp-post b.who:focus-visible{text-decoration:underline;outline:none}
/* Status dot before a name -- used in the threads board AND whisper windows (header + transcript,
   see .im rules below). Colors match the Online list exactly (st-away/st-busy/st-idle in the
   .users rules above), plus a plain grey "recently online" dot (presence-dot-recent) for someone
   within the 30-minute reachable window but not live in the room right now. See presenceDotClass/
   presenceDotHtml in app.js. */
.presence-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin:0 5px 1px 0;vertical-align:middle;flex:none}
.presence-dot-online{background:var(--leaf);box-shadow:0 0 5px rgba(90,161,90,.9)}
.presence-dot-away{background:var(--gold);box-shadow:0 0 5px rgba(201,162,74,.7)}
.presence-dot-busy{background:var(--blood);box-shadow:0 0 5px rgba(179,38,30,.7)}
.presence-dot-idle{background:#5f6b7a;box-shadow:0 0 5px rgba(95,107,122,.6)}
.presence-dot-recent{background:#6b7280;box-shadow:none}
.tp-posts .tp-loading{color:#5f5648;font-style:italic;font-size:12px;padding:8px}
/* Reply/OP pictures are thumbnails too -- click to open the lightbox (openLightbox in app.js) --
   sized to match the room/whisper thumbnails (.log img.gif) rather than their old, larger 200px cap. */
.tp-posts img.gif,.tp-posts img.tp-posted-img{max-width:160px;max-height:160px;display:block;margin-top:3px;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000;cursor:zoom-in;transition:filter .15s ease}
.tp-posts img.gif:hover,.tp-posts img.tp-posted-img:hover{filter:brightness(1.15)}
.tp-del{display:inline-block;margin-left:8px;font-size:10px;line-height:14px;color:#e07a7a;background:none;border:1px solid #7a2a2a;padding:0 4px;cursor:pointer;vertical-align:middle}
.tp-del:hover,.tp-del:focus-visible{color:#ff9c9c;border-color:#b3261e;background:rgba(179,38,30,.15);outline:none}
/* Catalog-tile thumbnail: small and fixed-size (like 4chan's ~125px tiles), not the old full-width
   banner -- clicking it pops the lightbox directly rather than opening the thread (see the
   tpItems click handler in app.js), same as 4chan's catalog. */
.tp-thumb{width:100%;height:110px;object-fit:cover;display:block;margin-bottom:5px;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000;cursor:zoom-in;transition:filter .15s ease}
.tp-thumb:hover{filter:brightness(1.15)}
.tp-reply{display:flex;gap:6px;padding:8px;border-top:1px solid var(--gold-lo);flex:none;align-items:flex-end;width:100%;max-width:900px;margin:0 auto;box-sizing:border-box}
.tp-reply-compose{flex:1;display:flex;flex-direction:column;gap:6px;min-width:0}
.tp-reply-compose textarea{height:44px}
/* Same "made by" + version copy as the main room's .room-watermark, but laid out in normal flow
   here instead of absolutely overlaid -- the reply bar is already docked to this panel's own
   bottom edge, so an overlay watermark at a fixed offset would end up sitting on top of it (worst
   on mobile, where both go full-width). As the threads-panel's last flex child it just renders as
   a slim, quiet footer below whichever of .tp-list/.tp-detail is currently showing. */
.tp-watermark{flex:none;text-align:center;padding:2px 8px 5px;font:9px Cinzel,Georgia,serif;
letter-spacing:1px;color:var(--ash);opacity:.65;pointer-events:none;-webkit-user-select:none;user-select:none}

/* threads board toggle: one floating button, at every viewport width, that swaps the whole screen
   between the chat window and the threads board (see .mobile-threads-open below -- the class name
   predates this being a desktop behaviour too, but nothing about it is mobile-specific anymore). */
.thread-toggle-fab{display:none;position:fixed;right:12px;bottom:104px;z-index:55;width:46px;height:46px;padding:0;
border-radius:4px;align-items:center;justify-content:center;font-size:20px;cursor:pointer;color:var(--gold-hi);
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);
box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
.thread-toggle-fab:hover,.thread-toggle-fab:focus-visible{border-color:var(--gold);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 16px rgba(201,162,74,.7);outline:none}
.thread-toggle-fab.open{color:#fff;border-color:var(--gold)}
.thread-toggle-fab.ready{display:flex}
.gc-root.mobile-threads-open .win{display:none}
.gc-root.mobile-threads-open .threads-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;
height:100%;border-width:0;border-radius:0;z-index:40}
@media (max-width:500px){.thread-toggle-fab{bottom:100px;right:8px}}

/* option to hide the whisper "tray" tabs (and any open whisper windows) entirely — a purely
   client-side/visual toggle; whispers still arrive and are remembered, just not shown until re-enabled */
.gc-root.no-dms .dm-dock{display:none !important}

/* "Gypsy Roulette — coming soon" teaser. Fills the empty gutter to the LEFT of the window,
   mirroring the threads board on the right: same fixed offset from centre (394px = half the
   760px window + its border/glow), same width, same frame treatment. It only appears at the
   width where that gutter actually exists (1340px, the same breakpoint the threads panel uses)
   -- below that the window fills the viewport and there is no dead space to fill. */
.roulette-panel{position:fixed;top:6px;bottom:6px;right:calc(50% + 394px);width:260px;display:none;
flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:24px 20px;
background:linear-gradient(180deg,var(--stone-2),var(--stone));border:3px double var(--gold-lo);outline:1px solid #000;
box-shadow:0 0 0 2px var(--gold-lo),0 0 0 3px #000,0 0 24px #000,inset 0 0 30px #000;overflow:hidden;z-index:8}
@media (min-width:1340px){.roulette-panel{display:flex}}
/* dim it along with the main window when the threads board is expanded, so focus stays there --
   but only in the desktop side-gutter placement above. On narrow screens .mobile-roulette-open
   takes the roulette panel full-screen (see the media query below); thread-open dimming it there
   left a dark, washed-out layer over the whole roulette tab whenever it was opened straight from
   an open thread, since closing the thread's full-screen view doesn't clear .thread-open. */
.roulette-panel{transition:opacity .22s ease,filter .22s ease}
.gc-root.thread-open:not(.mobile-roulette-open) .roulette-panel{opacity:.28;filter:saturate(.4)}
.rp-eyebrow{font:700 10px Cinzel,Georgia,serif;letter-spacing:3px;text-transform:uppercase;color:var(--ash);margin-bottom:12px}
.rp-title{font:700 26px Cinzel,"Trajan Pro",Georgia,serif;letter-spacing:2px;line-height:1.15;color:var(--gold);
text-shadow:0 0 12px rgba(201,162,74,.55),0 2px 0 #000,0 -1px 0 #000}
.rp-rule{width:70%;height:1px;margin:16px 0;background:linear-gradient(90deg,transparent,var(--gold-lo),transparent)}
.rp-blurb{font-size:13px;line-height:1.7;color:var(--bone);opacity:.8}
/* The caravan wheel (inline SVG in index.html, v67 -- it used to be a 56px dashed circle with a
   star in it). 160px is as big as the 260px desktop gutter panel can carry with its padding;
   the full-screen phone/tablet presentation below has room for 200px. Slowed from 14s to 22s:
   a wheel this size at the old rate read as a fan, not a wagon wheel rolling along. */
.rp-wheel{margin-top:24px;width:160px;height:160px;border-radius:50%;flex:none;
filter:drop-shadow(0 0 12px rgba(201,162,74,.28)) drop-shadow(0 6px 10px #000)}
.rp-wheel svg{display:block;width:100%;height:100%;overflow:visible}
.gc-root.mobile-roulette-open .rp-wheel{width:200px;height:200px;margin-top:28px}
@media (prefers-reduced-motion:no-preference){.rp-wheel{animation:rp-spin 22s linear infinite}}
@keyframes rp-spin{to{transform:rotate(360deg)}}

/* Gypsy-woman line art as a watermark in the chat log's dead space. Two background layers:
   the artwork sits on top of .sunk's gradient, which has to be repeated here because a
   background-image declaration would otherwise replace it (a gradient IS a background image).
   It stays put while messages scroll over it -- background-attachment defaults to `scroll`,
   which pins the background to the element's own box rather than to its scrolling content.
   The gold tint and the opacity are baked into the PNG, since background-image takes no
   CSS opacity of its own. */
.log{background-image:url(../img/gypsy-woman.png),linear-gradient(180deg,#050200,#0e0906);
background-repeat:no-repeat,no-repeat;background-position:center,center;
background-size:230px auto,cover}
@media (max-width:500px){.log{background-size:150px auto,cover}}

/* Pinned character name on the sign-on screen (see restoreIdentity() in app.js). The locked
   field is styled as a statement of who you already are rather than an input to fill in. */
#sn.locked{color:var(--gold-hi);cursor:default;font-family:Cinzel,Georgia,serif;letter-spacing:1px}
#sn.locked:focus{outline:none}
.sn-note{margin:4px 0 2px;font-size:11px;font-style:italic;color:var(--ash);text-align:center;line-height:1.5}
.sn-reset{background:none;border:none;padding:0;font:inherit;color:var(--gold);text-decoration:underline;cursor:pointer}
.sn-reset:hover,.sn-reset:focus-visible{color:var(--gold-hi);outline:none}

/* Save-your-character dialog (anonymous -> email account upgrade) */
.status .savebtn{font-size:13px;line-height:1}
.save-modal{max-width:420px;width:calc(100vw - 32px);text-align:left}
.save-modal .modal-body{max-height:min(60vh,520px);overflow-y:auto}

/* Admin-only "review reports" bell -- same treatment as the other status-bar cell buttons, plus
   a small red count badge for open reports so an admin doesn't have to open it to know something
   is waiting. */
.status .reportsbtn{position:relative}
.rbadge{position:absolute;top:-6px;right:-6px;min-width:15px;height:15px;padding:0 3px;border-radius:8px;
background:var(--blood);color:#fff;font:700 10px Cinzel,Georgia,serif;line-height:15px;text-align:center;
box-shadow:0 0 0 1px #000}
/* Admin Reports page (v108): the two review modals became one full-page takeover with two tabs
   (#adminPanel in index.html) -- same .gc-root.<state>-open pattern and .tp-hd header as the
   leaderboard. The .report-row cards below are unchanged; only their container moved. */
.admin-panel{display:none;flex-direction:column;background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8}
.gc-root.admin-open .win{display:none}
.gc-root.admin-open .thread-toggle-fab,.gc-root.admin-open .roulette-toggle-fab{display:none !important}
.gc-root.admin-open .admin-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;height:100%;border-width:0;border-radius:0;z-index:40}
.adm-tabs{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;padding:10px 10px 0;flex:none}
.adm-tab{display:inline-flex;align-items:center;gap:8px;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash);
background:rgba(0,0,0,.25);border:1px solid var(--gold-lo);border-bottom-color:transparent;padding:8px 14px;cursor:pointer;border-radius:3px 3px 0 0}
.adm-tab:hover,.adm-tab:focus-visible{color:var(--gold-hi);outline:none}
.adm-tab.active{color:var(--gold-hi);background:rgba(201,162,74,.1);border-color:var(--gold)}
.adm-tab .adm-count{position:static;flex:none;font-size:10px;letter-spacing:0}
.adm-body{flex:1;min-height:0;overflow-y:auto;padding:12px 14px;scrollbar-color:var(--gold-lo) #0f0d0b;width:100%;max-width:700px;margin:0 auto;box-sizing:border-box;border-top:1px solid var(--gold-lo)}
.reports-list .empty{color:#5f5648;font-style:italic;font-size:13px;padding:6px 0}
.report-row{border:1px solid var(--gold-lo);background:rgba(0,0,0,.25);padding:8px 10px;margin-bottom:8px}
.report-row .rr-hd{font-size:12px;color:var(--ash);margin-bottom:4px}
.report-row .rr-hd b{color:var(--gold-hi);font-weight:700}
.report-row .rr-msg{font-size:12px;color:var(--ash);font-style:italic;line-height:1.4;background:rgba(0,0,0,.3);border-left:2px solid var(--gold-lo);padding:4px 8px;margin-bottom:8px;white-space:pre-wrap;word-break:break-word}
.report-row .rr-reason{font-size:13px;color:var(--bone);line-height:1.4;margin-bottom:8px;white-space:pre-wrap;word-break:break-word}
.report-row .rr-actions{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap;align-items:center}
.report-row .rr-actions .btn{min-width:0;padding:0 10px;height:26px;font-size:12px}
.report-row .rr-select{height:26px;font-size:12px;background:rgba(0,0,0,.35);color:var(--bone);border:1px solid var(--gold-lo);border-radius:4px;padding:0 4px;max-width:100%}
.report-row .rr-actions .rr-apply{color:#e07a7a;border-color:#7a2a2a}
.report-row .rr-actions .rr-apply:hover{color:#ff9c9c;border-color:#7a2a2a;background:rgba(179,38,30,.15)}

/* Leaderboard -- top players by reactions received, presented as its own full-page panel (the same
   .gc-root.<state>-open takeover as .threads-panel/.roulette-panel -- see .gc-root.leaderboard-open
   below) rather than a modal. Reuses .tp-hd/.tp-back/.tp-watermark for the header, back button and
   footer chrome since it's the same "full-page panel with a header and a back button" shape as the
   threads board. Rows are their own thing (.lb-row) since they show an avatar, name, level badge
   and a count rather than a report's quote/reason/actions. */
.leaderboard-panel{display:none;flex-direction:column;
background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8}
.gc-root.leaderboard-open .win{display:none}
/* The floating bubbles sit above the panel (z 55 vs 40) and, on desktop, land right on the #1
   row's reaction count; they belong to the room, so they step out with .win. */
.gc-root.leaderboard-open .thread-toggle-fab,.gc-root.leaderboard-open .roulette-toggle-fab{display:none !important}
.gc-root.leaderboard-open .leaderboard-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;
height:100%;border-width:0;border-radius:0;z-index:40}
.lb-list{flex:1;overflow-y:auto;padding:10px 14px;scrollbar-color:var(--gold-lo) #0f0d0b;
width:100%;max-width:700px;margin:0 auto;box-sizing:border-box}
.lb-list .empty{padding:16px 8px;text-align:center;color:#5f5648;font-style:italic;font-size:12px}
.lb-row{display:flex;align-items:center;gap:8px;border:1px solid var(--gold-lo);background:rgba(0,0,0,.25);padding:7px 10px;margin-bottom:6px;cursor:pointer}
.lb-row:hover,.lb-row:focus-visible{background:rgba(201,162,74,.12);outline:none}
.lb-row.lb-top{background:rgba(201,162,74,.09);border-color:var(--gold-hi)}
.lb-row.lb-top:hover{background:rgba(201,162,74,.18)}
.lb-rank{flex:none;width:28px;text-align:center;font:700 12px Cinzel,Georgia,serif;color:#8f8371}
.lb-medal{flex:none;width:28px;text-align:center;font-size:18px}
.lb-row .lb-ava{margin-right:0}
.lb-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--bone);font-weight:700}
.lb-name.admin{color:var(--admin);text-shadow:0 0 7px rgba(209,59,47,.4)}
.lb-row .lvl{flex:none}
.lb-count{flex:none;font-size:11px;color:#8f8371;white-space:nowrap}

/* "Report a bug" -- composer (.bug-report-modal, reached from the status-bar "..." popover) and
   the admin review queue (.bug-reports-modal, same .reports-modal/.report-row shape as the abuse
   -reports queue above, plus .rr-attachments/.rr-context for the two things a bug report has that
   an abuse report doesn't). */
.bug-report-modal{max-width:420px;width:calc(100vw - 32px);text-align:left}
.bug-report-modal .modal-body{max-height:min(70vh,560px);overflow-y:auto}
.bug-hint{font-size:12px;color:var(--ash);line-height:1.45;margin-bottom:10px}
.bug-desc{display:block;width:100%;min-height:90px;padding:8px;font:13px "IM Fell English",Georgia,serif;
color:var(--bone);resize:vertical;outline:none;box-sizing:border-box;margin-bottom:10px;caret-color:var(--gold-hi)}
.bug-desc:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold),0 0 10px rgba(201,162,74,.35)}
.bug-attach-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.bug-attach-hint{font-size:11px;color:#5f5648}
.bug-attach-list{display:flex;flex-wrap:wrap;gap:10px}
.bug-attach-chip{position:relative;display:flex;flex-direction:column;align-items:center;width:64px}
.bug-attach-chip img,.bug-attach-video{width:64px;height:64px;box-sizing:border-box;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000}
.bug-attach-chip img{object-fit:cover;display:block}
.bug-attach-video{display:flex;align-items:center;justify-content:center;font-size:24px;background:rgba(0,0,0,.3)}
.bug-attach-name{font-size:9px;color:var(--ash);max-width:64px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.bug-attach-remove{position:absolute;top:-8px;right:-8px;width:20px;height:20px;line-height:16px;padding:0;font-size:12px;color:#fff;
background:var(--blood);border:1px solid #000;border-radius:50%;cursor:pointer}
.bug-attach-remove:hover{background:#d33}
.report-row .rr-attachments{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.rr-att,.rr-att-video{width:56px;height:56px;display:block;box-sizing:border-box;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000}
.rr-att img{width:100%;height:100%;object-fit:cover;display:block}
.rr-att-video{display:flex;align-items:center;justify-content:center;font-size:22px;background:rgba(0,0,0,.3);text-decoration:none}
.report-row .rr-context{font-size:10px;color:#5f5648;font-style:italic;word-break:break-word;margin-bottom:8px}
.save-lead{margin:0 0 12px;line-height:1.6;color:var(--bone)}
.save-lead b{color:var(--gold-hi);font-weight:normal;font-family:Cinzel,Georgia,serif;letter-spacing:.5px}
.save-modal label{display:block;margin:10px 0 3px;font:700 10px Cinzel,Georgia,serif;letter-spacing:1.5px;
text-transform:uppercase;color:var(--gold)}
.save-modal input{width:100%;padding:6px 8px;font:14px "IM Fell English",Georgia,serif;color:var(--bone);
background:linear-gradient(180deg,#050200,#0e0906)}
.save-err{min-height:0;margin-top:8px;font-size:12px;color:var(--blood)}
.save-err.shown{min-height:16px}
.privacy-note{margin-top:16px;padding:10px 12px;border:1px solid var(--gold-lo);
background:rgba(201,162,74,.06)}
.privacy-note .pn-hd{font:700 10px Cinzel,Georgia,serif;letter-spacing:1.5px;text-transform:uppercase;
color:var(--gold);margin-bottom:6px}
.privacy-note p{margin:0 0 6px;font-size:12px;line-height:1.6;color:var(--ash)}
.privacy-note p:last-child{margin-bottom:0}
.privacy-note b{color:var(--bone)}
.save-actions{display:flex;gap:8px;justify-content:flex-end;padding:10px 14px 14px}
.save-actions .btn{height:30px;padding:0 14px}

/* Mobile bubble for the roulette teaser, twinned with the threads bubble. Below 1340px the
   left gutter the panel normally lives in does not exist, so the panel becomes a full-screen
   takeover reached from its own floating button -- exactly how the threads board behaves. */
.roulette-toggle-fab{display:none;position:fixed;right:12px;bottom:158px;z-index:55;width:46px;height:46px;padding:0;
align-items:center;justify-content:center;font:400 20px Cinzel,Georgia,serif;color:var(--gold);
background:linear-gradient(180deg,#281f15,#110c07);border:2px solid var(--gold-lo);border-radius:50%;
box-shadow:0 0 0 1px #000,0 4px 14px #000;cursor:pointer}
.roulette-toggle-fab:hover,.roulette-toggle-fab:focus-visible{border-color:var(--gold);
box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 16px rgba(201,162,74,.7);outline:none}
.roulette-toggle-fab.open{color:#fff;border-color:var(--gold)}
/* the "Back to chat" button only belongs to the full-screen mobile presentation */
.rp-back{display:none;margin-top:22px;height:30px;padding:0 16px}
@media (max-width:1339px){
  .roulette-toggle-fab.ready{display:flex}
}
/* v106: the roulette takeover used to exist only below 1340px, because below 1340px the floating
   bubble was the only way in and above it the gutter teaser was the whole feature. Now that the
   button lives in the title bar at every desktop width, a wide desktop needs somewhere for it to
   go -- so the takeover rules come out of that media query and apply everywhere, exactly as the
   threads board's already do. The gutter teaser is unaffected and still sits there when the page
   is closed; opening it just covers the teaser along with everything else. */
.gc-root.mobile-roulette-open .win{display:none}
.gc-root.mobile-roulette-open .roulette-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;
height:100%;right:auto;top:0;bottom:0;border-width:0;z-index:40;transition:none}
.gc-root.mobile-roulette-open .rp-back{display:inline-flex;align-items:center;justify-content:center}
@media (max-width:500px){.roulette-toggle-fab{bottom:154px;right:8px}}

/* The status bar doubles as the rename control once you're in the room -- it reads "Change name"
   rather than restating who you are (that moved to a hover tooltip, see setSignedOnStatus() in
   app.js), lit up neon orange with a glow so the affordance reads as a live control rather than
   plain status text. */
.status #st.renamable{cursor:pointer;color:#ff7a1a;text-shadow:0 0 4px rgba(255,122,26,.85),0 0 10px rgba(255,90,0,.55)}
.status #st.renamable:hover{color:#ffa64d;text-shadow:0 0 6px rgba(255,166,77,.95),0 0 14px rgba(255,122,26,.75)}

/* Float the two bubbles at the vertical middle of the screen rather than down by the composer:
   easier to reach one-handed mid-scroll, and clear of the Send button and the iOS home bar.
   The pair is centred as a unit -- 46px buttons with an 8px gap puts each 27px off centre.
   These come last on purpose, to override the bottom offsets set where each bubble is defined. */
.thread-toggle-fab{top:50%;bottom:auto;transform:translateY(calc(-50% + 27px))}
.roulette-toggle-fab{top:50%;bottom:auto;transform:translateY(calc(-50% - 27px))}
@media (max-width:500px){
  .thread-toggle-fab{bottom:auto;right:8px}
  .roulette-toggle-fab{bottom:auto;right:8px}
}

/* Draggable / sweepable bubbles (see makeFabDraggable() in app.js). touch-action:none stops a
   drag on a phone from also scrolling the page underneath it, matching the .uz resize grip
   above. The left/top transition is what makes a release (snap back into the viewport, or dock
   against an edge) glide instead of jump -- suppressed while a drag is actively in progress, or
   it would fight the pointer and lag a frame behind your finger. */
.thread-toggle-fab,.roulette-toggle-fab{touch-action:none;transition:left .22s ease,top .22s ease,opacity .18s ease}
.thread-toggle-fab.fab-dragging,.roulette-toggle-fab.fab-dragging{transition:none;box-shadow:0 0 0 1px #000,0 6px 20px #000,0 0 20px rgba(201,162,74,.9)}
/* Docked = swept mostly off-screen, just a tab's width left showing at the edge. Dimmed so it
   reads as tucked away rather than as a normal, ready-to-tap button; full opacity on hover/focus
   so it's still easy to find with a mouse. */
.thread-toggle-fab.fab-docked,.roulette-toggle-fab.fab-docked{opacity:.5}
.thread-toggle-fab.fab-docked:hover,.thread-toggle-fab.fab-docked:focus-visible,
.roulette-toggle-fab.fab-docked:hover,.roulette-toggle-fab.fab-docked:focus-visible{opacity:1}

/* Watermark: a touch larger and nudged right of centre. Sized as a share of the log rather than
   a fixed pixel width -- the log runs ~570px wide on a full desktop window but barely 260px in a
   squeezed one, and a fixed 300px simply ran off the right-hand edge there. A percentage scales
   with whatever the log actually is, so the figure always sits fully inside it. */
.log{background-size:56% auto,cover;background-position:66% center,center}
@media (max-width:500px){.log{background-size:52% auto,cover;background-position:64% center,center}}

/* Admin names in deep red, wherever a name is drawn: the chat log, the Online list, the Friends
   list and the tap-a-name menu header. The colour is deliberately louder than the gold everyone
   else wears, with a faint glow so it still reads against the near-black panels. Which names get
   it comes from the admins table, never from presence -- see isAdminId() in app.js. */
:root{--admin:#d13b2f}
.log .m b.who.admin{color:var(--admin);text-shadow:0 0 8px rgba(209,59,47,.45)}
.log .me b.who.admin,.log .them b.who.admin{color:var(--admin)}
.users .list div.admin{color:var(--admin);text-shadow:0 0 7px rgba(209,59,47,.4)}
.users .list div.admin:hover,.users .list div.admin:focus-visible{color:#ef6a5c}
.users .list div.self.admin,.users .list div.self.admin:hover{color:var(--admin)}
.users .list div.blocked.admin{color:#5f5648;text-shadow:none}
.nmenu .hd .hd-name.admin{color:var(--admin);text-shadow:0 0 8px rgba(209,59,47,.45)}
/* Drag handle on the left edge of the Online/Friends panel -- horizontal only, by design: the
   column's height is already tied to the chat log beside it, so a vertical drag would just
   desynchronise the two. Width is driven by --users-w on .body rather than by an inline width,
   so the grid track and the panel can never disagree about how wide the column is.
   Hidden below 431px, where the panel itself is hidden and the layout is a single column. */
.users{position:relative}
.users .uz{position:absolute;top:0;bottom:0;left:-9px;width:12px;z-index:6;cursor:col-resize;
touch-action:none}
.users .uz::after{content:"";position:absolute;top:50%;left:4px;width:3px;height:34px;
transform:translateY(-50%);border-radius:2px;background:var(--gold-lo);opacity:.55;
transition:opacity .15s ease,background .15s ease}
.users .uz:hover::after,.users .uz:focus-visible::after{opacity:1;background:var(--gold)}
.users .uz:focus-visible{outline:none}
.gc-root.users-resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}
.gc-root.users-resizing .uz::after{opacity:1;background:var(--gold)}
@media (max-width:500px){.users .uz{display:none}}

/* Roulette bubble on the sign-on screen. Once you are in the room it is one of a pair, centred
   as a unit with the threads bubble; before you sign on the threads bubble does not exist yet,
   so the lone bubble sat oddly low against a screen whose content is all in the upper half.
   .signed-on is added to .gc-root the moment the sign-on panel is swapped for the chat. */
.gc-root:not(.signed-on) .roulette-toggle-fab{top:28%;transform:translateY(-50%)}

/* ---------- Online/Friends panel on a phone: foldable, and draggable by its top edge ----------
   Below 431px the panel is no longer a side column; it is a block between the chat log and the
   composer, where every pixel it occupies is a pixel of conversation you cannot see. So there it
   gets a fixed height you can drag, and a button that folds it down to just its "Online" bar --
   the bar stays put rather than the panel vanishing, so there is always something to press to
   bring it back. Both controls are phone-only: on a wider screen the panel is a column whose
   height is set by the chat log beside it, and neither gesture would have anything to do. */
.users .hd{position:relative}
.users .umin{display:none;position:absolute;right:2px;top:50%;transform:translateY(-50%);
width:26px;height:20px;padding:0;line-height:18px;font-size:10px;cursor:pointer;
color:var(--gold);background:none;border:1px solid var(--gold-lo)}
.users .umin:hover,.users .umin:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
.users .uzv{display:none;position:absolute;top:-10px;left:0;right:0;height:16px;z-index:6;
cursor:row-resize;touch-action:none}
.users .uzv::after{content:"";position:absolute;left:50%;top:6px;width:40px;height:3px;
transform:translateX(-50%);border-radius:2px;background:var(--gold-lo);opacity:.55;
transition:opacity .15s ease,background .15s ease}
.users .uzv:hover::after,.users .uzv:focus-visible::after{opacity:1;background:var(--gold)}
.users .uzv:focus-visible{outline:none}
.gc-root.users-resizing-v{-webkit-user-select:none;user-select:none}
.gc-root.users-resizing-v .uzv::after{opacity:1;background:var(--gold)}
/* These two controls appear whenever the panel is STACKED under the chat rather than standing
   beside it -- .users-stacked is set by measuring where the panel actually landed (see app.js),
   not by guessing a screen width. The first attempt keyed them off a 430px media query, which
   is narrower than the newest large phones report, so on those the button and the grip were
   never shown at all. Measuring the layout cannot drift out of step with it. */
.gc-root.users-stacked .users{height:var(--users-h,150px);min-height:0}
.gc-root.users-stacked .users .umin,.gc-root.users-stacked .users .uzv{display:block}
.gc-root.users-stacked .users .uz{display:none} /* the sideways grip has no column to size */
/* folded: the bar only. height:auto lets the grid row shrink to the header, and the lists, the
   Friends heading and the hint all come out of the box rather than being clipped inside it. */
.gc-root.users-stacked.users-folded .users{height:auto}
.gc-root.users-stacked.users-folded .users .list,
.gc-root.users-stacked.users-folded .users .frhd,
.gc-root.users-stacked.users-folded .users .hint{display:none}

/* ---------- friend requests: a bell + dropdown inbox, siblings of .win (see the comment on
   #ims/#imTray in index.html for why -- same reasoning applies here). z-index 46 sits in the
   whisper-window band (41-54) since neither one needs to beat the other; both stay under
   .nmenu (60) and modals (70).
   --frq-right: on a wide screen .win is centered and capped at max-width:760px (see .win), so it
   stops well short of the actual browser edge -- plain `right:8px` here would strand the button out
   in that empty margin, nowhere near the card it belongs to. calc(50% - 380px + 8px) targets the
   card's own right edge instead (380 = half of .win's 760px cap; +8 tucks the icon in over the
   corner like a badge); max() falls back to a flat 8px once the viewport is narrow enough that .win
   is no longer capped and genuinely fills it (the calc() side goes negative right around there). */
/* v107: friend requests moved out of a floating 🤝 bell and its dropdown into the top of the
   Messages dock's inbox (#frqSection). Same swipeable rows as before (below); only the container
   changed, so it takes the dock's purple trim rather than the room's gold. Hidden when empty. */
.frq-section{flex:none;border-bottom:2px solid #7a4bb0;box-shadow:0 2px 0 #000;background:rgba(0,0,0,.18)}
.frq-hd{display:flex;align-items:center;gap:8px;padding:7px 10px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#e2c4ff;
text-transform:uppercase;border-bottom:1px solid #3d2a4d;text-shadow:0 1px 0 #000}
.frq-hd .frq-count{position:static;flex:none;font-size:10px;letter-spacing:0}
.frq-list{scrollbar-color:#7a4bb0 #0f0d0b}

/* Each row is a swipeable card: .frq-bg sits underneath full-size and only shows in the gap left
   behind as .frq-content (the actual visible row, dragged by pointer events in app.js) slides off
   to one side -- see swipe handling near renderFriendReqPanel. Right = accept, left = decline,
   matching the request. Explicit Accept/Decline buttons stay in the row too, since swipe alone
   would lock out anyone on a desktop mouse or using a screen reader. */
.frq-row{position:relative;overflow:hidden;border-bottom:1px solid #3d2a4d;touch-action:pan-y}
.frq-row:last-child{border-bottom:none}
.frq-bg{position:absolute;inset:0;display:flex;align-items:center;font:700 12px Cinzel,Georgia,serif;
letter-spacing:.5px;color:#fff;padding:0 12px;opacity:0}
.frq-bg.accept{background:var(--leaf);justify-content:flex-start}
.frq-bg.decline{background:var(--blood);justify-content:flex-end}
.frq-content{position:relative;display:flex;align-items:center;gap:8px;padding:8px 10px;
background:linear-gradient(180deg,#1a111f,#0d0510);cursor:grab;touch-action:pan-y}
.frq-content .ava,.frq-content .ava-fallback{width:28px;height:28px;font-size:13px;flex:none}
.frq-name{flex:1;min-width:0;font-size:13px;color:var(--bone);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the optional one-line intro that came with the request (friends_only_whispers.sql) */
.frq-intro{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font:italic 12px/1.3 "IM Fell English",Georgia,serif;color:var(--ash);overflow:hidden;white-space:normal}
.frq-actions{display:flex;gap:4px;flex:none}
.frq-actions button{font:700 11px Cinzel,Georgia,serif;padding:3px 7px;cursor:pointer;border-radius:2px}
.frq-accept{color:#cdeecd;background:rgba(90,161,90,.18);border:1px solid var(--leaf)}
.frq-accept:hover,.frq-accept:focus-visible{background:rgba(90,161,90,.35);outline:none}
.frq-decline{color:#f3c9c6;background:rgba(179,38,30,.18);border:1px solid var(--blood)}
.frq-decline:hover,.frq-decline:focus-visible{background:rgba(179,38,30,.35);outline:none}
/* Mobile: the in-app emoji picker (#emoBtn) is redundant next to the phone's own emoji keyboard,
   so it's dropped entirely below 500px and the friend-request bell takes over that reclaimed spot
   in the compose bar instead -- bottom-left, rather than its desktop home at the top-right corner
   of the card, since that's where the emoji button used to sit. The bell/panel stay `position:fixed`
   (not actually moved into #compose in the DOM) so they keep working the same way #ims/#imTray do:
   still reachable even while Threads/Leaderboard/Roulette hide the rest of .win. The panel opens
   upward from the bell now instead of downward, since the bell moved from the top of the screen to
   the bottom. */
@media (max-width:500px){
  #emoBtn{display:none}
  /* .compose's 4 explicit columns (emo/gif/textarea/send) assumed 4 items; with emoBtn gone that
     would leave only 3 flowing into them and shove the textarea out of its 1fr track (see gifBtn
     landing in column 1, textarea inheriting gifBtn's old auto-sized column 2, send ballooning
     into the real 1fr column 3) -- drop to 3 columns here so gif/textarea/send land right. */
  .compose{grid-template-columns:auto 1fr auto}
}

/* Desktop: Threads moves off the floating, vertically-centred bubble (still the mobile behaviour
   below 500px, see makeFabDraggable's desktopFixed flag in app.js -- no dragging here either) and
   into a fixed spot up in the header, near the friend-request bell but with a real gap so the two
   don't read as one control. 62px = friendreq-btn's own 34px width + a 20px gap from its left edge
   + friendreq-btn's own 8px base offset; the calc() branch mirrors the exact "track .win's actual
   right edge past the 760px cap, not the raw viewport corner" logic .friendreq-btn already uses, so
   both buttons cross from their flat fallback to the calc() formula at the same viewport width and
   the 54px gap between them (62-8) never drifts, wide monitor or narrow desktop window alike.
   !important guards against a stale inline position from a drag made back when this bubble was
   still mobile-narrow (see makeFabDraggable) -- belt and braces alongside the JS-side guards there. */
@media (min-width:501px){
  .thread-toggle-fab{position:fixed !important;top:8px !important;bottom:auto !important;
  right:max(62px,calc(50% - 380px + 62px)) !important;left:auto !important;transform:none !important}
}

/* ==================== phone overhaul (v65) ====================
   Everything in this section is scoped to a touch device and/or a phone-width screen, and comes
   last in the file on purpose so it wins over the earlier per-feature rules it adjusts. Nothing
   here changes how a desktop browser with a mouse renders the room.

   1. The "I have to zoom out every time I open it" complaint from iPhone testers. iOS Safari
      zooms the whole page IN the moment an input, textarea or select with a computed font-size
      under 16px gets focus (it's a legibility heuristic, not something the page asked for). The
      room's base size is 14px and every field uses font:inherit, so tapping the invite-key field
      -- the first thing anyone does on the sign-on screen -- zoomed the page, and it stayed
      zoomed until they pinched it back. 16px on every field, on touch devices only, is the fix.
      !important because a few fields set their size via the `font:` shorthand at higher
      specificity (.prompt-modal input, .save-modal input, .report-row .rr-select). */
@media (hover:none) and (pointer:coarse){
  input:not([type=file]),textarea,select{font-size:16px !important}
  /* 2. Touch targets. Several small controls were sized for a mouse pointer (16-24px); a finger
        needs closer to 40. Widen the hit area without redrawing the control. */
  .status button.cell{min-height:32px;min-width:40px}
  .im-tab{padding-right:38px}
  .im-tab .tab-close{width:28px;height:28px;line-height:26px;opacity:.7}
  .users .umin{width:44px;height:28px;line-height:26px;font-size:12px}
  .lightbox-close{width:44px;height:40px;line-height:36px}
  .tp-back{width:38px;height:30px;line-height:26px}
  .frq-actions button{padding:7px 10px}
  .rp-back,.modal .btn{min-height:36px}
  /* build 263. The phone header is the one place the rule above cannot reach, and it took a
     measurement to see why: below 501px the bell, the ballot box, the contest and ⋯ are MOVED out
     of .status and into .title-tools, which drops them out of ".status button.cell" -- so they have
     been sitting at 26x26 on a phone the whole time their neighbours were getting 40x32.
     They cannot simply be widened. The row is pinned to the right edge with 4px between buttons;
     three 44px buttons need 132px where there are 86, so they would overlap each other and run off
     the screen. Overlapping hit areas are worse than small ones -- the later button in the markup
     wins, so aiming at the ballot box would sometimes open the bell, silently, and only on a phone.
     So the button keeps its 26x26 look and an invisible pseudo-element carries the touch: 30 wide,
     which eats the 4px gutter exactly and not one pixel more, and 44 tall, which is free inside a
     50px header and is the axis a thumb actually misses on -- you come up from below and undershoot.
     Nearly double the area, nothing moves, nothing overlaps.
     Not touched: .users .umin two lines up is already 44x28 here, and the desktop sizes are fine. */
  .title-tools > button{position:relative}
  .title-tools > button::after{content:"";position:absolute;left:50%;top:50%;
    transform:translate(-50%,-50%);width:30px;height:44px}
}

@media (max-width:500px){
  /* 3. Belt and braces against the other cause of a shrunk-to-fit page: any element that ever
        ends up a few pixels wider than the screen would make Safari lay the page out wider than
        the viewport. Clip that instead of letting it change the zoom. Set on html so it applies
        to the viewport itself; body keeps its own overflow untouched. */
  html{overflow-x:hidden}
  /* 3b. No vertical wiggle either, once signed on. The page was a little taller than the screen
        on an iPhone: .gc-root's min-height is the static 100vh (which on iOS includes the space
        behind Safari's toolbar), the frame inside it is 100dvh (the space you can actually see),
        and body adds the safe-area insets on top -- so the document could always be dragged up and
        down by that leftover, and the fixed-position 🤝 bell and bubbles visibly stayed put while
        the room slid under them, which is what made them feel stuck on rather than part of the
        page. Signed on, the room is exactly the visible height (insets included) and the document
        itself can't scroll at all -- the log, threads, leaderboard and dock all scroll internally.
        The sign-on screen is left as it was: it's allowed to grow past one screen for the portrait.
        :has() is how the html/body rules key off .gc-root's class; a browser without it just keeps
        the old behaviour.
        Sizing is a plain height:100% chain from html down, NOT 100dvh minus env() insets: in the
        Home Screen (standalone) app the dvh/inset arithmetic came out taller than the screen and
        clipped the status bar and footer, while Safari was fine. html's 100% is the visible area
        in both -- Safari's layout viewport with its toolbar, the whole screen when installed --
        and body's safe-area padding is counted INSIDE that 100% (border-box), so the frame lands
        between the notch and the home indicator with nothing to subtract. */
  html:has(.gc-root.signed-on),body:has(.gc-root.signed-on){height:100%;overflow:hidden;overscroll-behavior:none}
  body:has(.gc-root.signed-on){box-sizing:border-box}
  .gc-root.signed-on{min-height:0;height:100%;box-sizing:border-box;overflow:hidden}
  /* min-height:0 matters: the frame's earlier min-height of calc(100dvh - 8px) (the sign-on
     screen's grow-to-fit floor) would otherwise hold it at full-screen height regardless, which
     is exactly what pushed the status bar and footer off the bottom of the installed app */
  .gc-root.signed-on .win{height:100%;min-height:0}
  /* 4. Give the room back some of its own width and height: a tighter gutter inside the frame,
        and a composer that isn't a 60px-tall block on a screen this short. The GIF/Send buttons
        stretch to the textarea's height, so shrinking it shrinks them too -- 48px is still a
        comfortable finger-sized button. */
  .win > .body{padding:6px;gap:6px}
  .compose textarea{height:48px}
  /* 5. (The 50px status-bar indent that used to clear the floating friend-request bell in the
        bottom-left corner is gone with the bell -- requests live in the Messages dock now, v107.) */
  /* the buttons grew to finger height (rule 2), so centre the text beside them instead of letting it sit at the top of the row */
  .status{align-items:center}
  /* 6. Every row of the "..." popover gets a finger-height minimum. (The dark styling for the
        "Save with email" / "Notifications" rows now comes from the shared .status button rule
        near the top of the file, same as on a wide screen.) */
  #statusPopover .cell{min-height:36px}
  /* 7. Online/Friends panel, stacked under the log on a phone (see "Online/Friends panel on a
        phone" above). It now starts FOLDED on a phone the first time (app.js), so all it costs
        until you want it is its one-line "Online" bar -- which therefore carries the head count,
        so the folded bar still tells you something. Unfolded, the Online list gets the lion's
        share of the height rather than splitting it 50/50 with a usually-shorter Friends list. */
  .gc-root.users-stacked .users .hd .ucount{display:inline;margin-left:5px;color:var(--ash);letter-spacing:0;font-weight:400}
  /* Unfolded, the two lists sit SIDE BY SIDE rather than one above the other: a phone is short
     on height but has plenty of width for two columns of names, and stacking them vertically
     gave the Online list two rows before the Friends heading cut in. The grips (.uz/.uzv) are
     absolutely positioned so they never occupy a cell. Folded, the panel goes back to the plain
     column so the lone "Online" bar spans the full width. */
  /* build 299: ONE LIST AT A TIME, FULL WIDTH, BEHIND TABS -- replacing the two columns above.
     Measured at 360 with a realistic roster (15 online, 5 friends, real handles): the two columns
     were 170px each, and into 170px goes an avatar, a name, a level badge and a status tag. Five
     of twenty names were cut off at 360 and TEN of twenty at 320. Full width cuts off none of them
     at either size, and the rows go from 24px to 30. The count each tab carries means both numbers
     are still readable without switching, which is most of what the second column was for. */
  .gc-root.users-stacked:not(.users-folded) .users{display:grid;grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr) auto}
  .gc-root.users-stacked:not(.users-folded) .users .hd:first-of-type{grid-area:1/1/2/2}
  .gc-root.users-stacked:not(.users-folded) .users .frhd{display:none}
  .gc-root.users-stacked:not(.users-folded) .users #ulist,
  .gc-root.users-stacked:not(.users-folded) .users #flist{grid-area:2/1/3/2;border-left:none}
  .gc-root.users-stacked:not(.users-folded) .users.tab-friends #ulist{display:none}
  .gc-root.users-stacked:not(.users-folded) .users:not(.tab-friends) #flist{display:none}
  .gc-root.users-stacked:not(.users-folded) .users .hint{grid-area:3/1/4/2}
  /* the tab strip itself. 36px tall so each tab clears the 24px floor with room to spare, and the
     fold arrow keeps its own 44x28 at the end. */
  .gc-root.users-stacked .users .hd:first-of-type{display:flex;align-items:stretch;padding:0;text-align:center;position:relative}
  .gc-root.users-stacked .users .hd #uTabFriends{display:block}
  .gc-root.users-stacked .users .hd .utab{flex:1;min-height:36px;padding:9px 6px;color:var(--ash);border-bottom:2px solid transparent;cursor:pointer}
  .gc-root.users-stacked .users .hd .utab[aria-selected="true"]{color:var(--gold-hi);border-bottom-color:var(--gold);background:rgba(201,162,74,.07)}
  .gc-root.users-stacked .users .hd .utab .ucount{display:inline;margin-left:4px;opacity:.85}
  /* build 300: THE FOLD ARROW IS A THIRD CELL IN THE BAR, not a thing floating over one of the
     tabs. It was position:absolute at 26x20 -- under the 24px minimum on its own -- and 299 lifted
     the tabs to z-index:7 to clear the resize grip, which painted the Friends tab straight over it:
     every probe point on the arrow returned the tab, so the panel could not be shut at all. Making
     it a real flex item takes it out of the stacking contest entirely: it has its own 44x36 cell,
     its own divider, and nothing overlaps it because nothing is on top of anything. The tabs give
     back the 30px of right padding they only had to dodge it. */
  .gc-root.users-stacked .users .umin{position:static;transform:none;flex:none;width:44px;min-height:36px;height:auto;
  z-index:8;border:none;border-left:1px solid var(--gold-lo);border-radius:0;font-size:14px;color:var(--gold-hi);
  background:rgba(201,162,74,.10);display:flex;align-items:center;justify-content:center}
  /* AND THE TABS HAVE TO OUTRANK THE RESIZE GRIP. `.users .uzv` is position:absolute, left:0,
     z-index:6, top:-10px and 24px tall on touch -- so it reaches 14px DOWN into this bar and sat on
     top of both tabs. taps24 measured them at 22px high instead of 36, and a press in that top
     third would have started a panel resize instead of switching tab: a wrong-action bug, the same
     one build 286 found under the minimise caret, which is why that build made the handle stop
     short of it. It cannot stop short of these -- they span the whole bar -- so the tabs are lifted
     above it instead. The grip keeps the 10px it has ABOVE the panel edge, which is where a hand
     reaches for it anyway, and its visible grab bar is unmoved. */
  .gc-root.users-stacked .users .hd .utab{position:relative;z-index:7}
  /* and the rows get the height the full width paid for: 24px was the two-column compromise, where
     every pixel of height was another name lost off the bottom of a 138px box. One list has twice
     the room, so the rows go to 30 -- clears the project's 24px floor with margin, and is a good
     deal easier to hit than 24 exactly. */
  .gc-root.users-stacked .users .list div[data-id]{padding-top:4px;padding-bottom:4px}
  .gc-root.users-stacked:not(.users-folded) .users .list{min-height:0}
  /* the whole bar toggles the fold on a phone (app.js), so it should look tappable */
  .gc-root.users-stacked .users .hd:first-of-type{cursor:pointer;user-select:none;-webkit-user-select:none}
}
/* The head count in the Online bar is a phone-only affordance (rule 7 just above): on a wide
   screen the bar heads a full column where the names speak for themselves, and the room footer
   already shows "N online" there, so the span stays hidden everywhere the panel isn't stacked. */
.users .hd .ucount{display:none}
.gc-root.users-stacked .users .hd .ucount{display:inline}

/* ==================== the Messages dock (v68) ====================
   One panel for every whisper, pinned to the bottom-right corner of the screen the way
   Instagram's web inbox is. Three states, set by syncDock() in app.js:
     .collapsed  -- just the bar ("Messages", unread total, chevron), 260px wide
     (neither)   -- expanded on the inbox: the bar, then one .im-tab row per conversation
     .thread     -- expanded on one conversation: its own .im header (back arrow, name, buzz,
                    collapse) replaces the bar, then the transcript and composer
   z-index 45 sits in the old whisper-window band: above the full-screen takeover panels
   (threads/leaderboard/roulette, 40) so a message can still be read from inside them, under
   the emoji/reaction pickers (56/57), .nmenu (60) and the modals (70), all of which open from
   inside a conversation and have to land on top of it. */
/* Width: 340px when there's room, but the room's window is a centred 760px card, and on a
   typical laptop (1280-1440 wide) a 340px panel in the corner would sit over the card's right
   column and its Send button. clamp() sizes the panel to the gap beside the card instead --
   (50vw - 380px) is that gap, minus the 8px inset on each side -- never narrower than 260px. */
.dm-dock{position:fixed;right:4px;bottom:4px;z-index:45;width:clamp(260px,calc(50vw - 396px),340px);height:min(480px,calc(100vh - 16px));
display:flex;flex-direction:column;
background:linear-gradient(180deg,#1a111f,#08030a);border:3px double #7a4bb0;outline:1px solid #000;
box-shadow:0 0 0 2px #a67ad1,0 0 0 3px #000,0 10px 30px #000,inset 0 0 30px #000;color:var(--bone)}
.dm-dock.collapsed{width:260px;height:auto}
.dm-dock.collapsed .dm-body{display:none}
.dm-bar{display:flex;align-items:center;gap:8px;padding:8px 10px;cursor:pointer;user-select:none;-webkit-user-select:none;flex:none;
font:700 13px Cinzel,Georgia,serif;letter-spacing:1.5px;color:#e2c4ff;text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000;
background:linear-gradient(180deg,#2c1e36,#110918);border-bottom:2px solid #7a4bb0;box-shadow:0 2px 0 #000}
.dm-dock.collapsed .dm-bar{border-bottom:none;box-shadow:none}
.dm-bar:hover,.dm-bar:focus-visible{color:#fff;outline:none}
.dm-bar .dm-bar-ico{font-size:15px;flex:none}
.dm-bar .dm-bar-title{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* the unread total: .rbadge is the same red pill the friend-request bell and the reports button
   use, but sitting in the row's flow here rather than pinned to a corner */
.dm-bar .dm-bar-badge{position:static;flex:none;font-size:10px;letter-spacing:0}
.dm-bar .dm-bar-chev{flex:none;font-size:14px;line-height:1;color:#c9a3e6;transform:translateY(2px);transition:transform .18s ease}
.dm-dock:not(.collapsed) .dm-bar .dm-bar-chev{transform:translateY(-1px) rotate(180deg)}
.dm-bar.flash{animation:tabflash 1s ease-in-out 2}
/* Body: the inbox list and the conversation views share the same box; .thread swaps them. */
.dm-body{position:relative;flex:1;min-height:0;display:flex;flex-direction:column}
.dm-inbox{flex:1;min-height:0;overflow-y:auto;scrollbar-color:#7a4bb0 #0f0d0b}
.dm-dock.thread .dm-bar{display:none}
.dm-dock.thread .dm-inbox{display:none}
.dm-dock #ims{display:none}
.dm-dock.thread #ims{display:block;position:absolute;inset:0}
.dm-empty{padding:26px 16px;text-align:center;font-size:12px;line-height:1.7;color:var(--ash);font-style:italic}
.dm-empty b{color:#e2c4ff;font-style:normal}
/* Phone: the collapsed bar becomes a small pill floating over the bottom-right of the chat, clear
   of the composer and the folded roster bar beneath it; expanded, the dock takes the screen
   below the title bar, since a 340px panel would cover most of the room anyway. */
@media (max-width:500px){
  .dm-dock.collapsed{width:auto;max-width:200px;right:6px;bottom:142px;border-width:2px}
  /* dragged somewhere (app.js applyPill): the pill sits where it was put, until it expands */
  /* build 302: THE DOCK RETRACTS INTO THE PILL INSTEAD OF TELEPORTING TO IT.
     It was positioned by left/top while collapsed and fell back to right/bottom while open -- and
     `left` cannot animate to or from `auto`, so opening was a single-frame jump and closing flew
     the pill diagonally across the screen from wherever the open box had been:
     14,67 -> 62,182 -> 86,240 -> 101,274 -> 112,302 on a middle-parked pill. Both states are
     right/bottom anchored now (app.js setPillAnchors keeps all four vars in step), so the same
     property animates at both ends and the box genuinely travels.
     Width and height are numbers rather than `auto` for the same reason -- `auto` does not
     interpolate, and the retract needs something to shrink TO. They come from the pill's own
     measured size, cached from a genuinely-collapsed frame. */
  .dm-dock.collapsed.moved{right:var(--pill-r);bottom:var(--pill-b);left:auto;top:auto}
  .dm-dock.collapsed{width:var(--pill-w,140px);height:var(--pill-h,39px);max-width:none}
  .dm-dock{transition:right .24s ease,bottom .24s ease,width .24s ease,height .24s ease}
  /* build 308: `.dm-dock.pill-dragging{transition:none}` stood here -- a duplicate of the older
     `.dm-dock.collapsed.pill-dragging` further down, and the pill can only be dragged collapsed.
     The guard-deletion pass removed it and nothing noticed; guards.js now watches the one that stays. */
  /* and the body rides the box down instead of being deleted on the first frame. It used to be
     display:none the instant `.collapsed` landed, so what travelled was an empty shell -- build
     298's max-height:0 wearing a different hat. The dock is already overflow:hidden, so the
     shrinking box does the clipping; this only has to fade and stop taking presses. */
  .dm-dock .dm-body{transition:opacity .16s ease}
  .dm-dock.collapsed .dm-body{display:block;opacity:0;pointer-events:none;
  position:absolute;left:0;right:0;top:var(--pill-h,39px);bottom:auto}
  /* absolute, not just visible: the takeover pages (Game Room, Threads, the contest) size this pill
     with `width:auto` so it shrinks to the envelope alone, and a body left IN FLOW makes the dock
     as wide as its widest message instead -- 257px where the test wants under 90. Keeping it out of
     flow lets it paint through the retract, clipped by the dock's overflow:hidden, without ever
     voting on how wide the pill is. run29 caught this; it is the cost of not deleting the body on
     the first frame, and it has to be paid somewhere. */
  /* swept to an edge: just a tab of it showing, dimmed, until tapped back out */
  .dm-dock.collapsed.pill-docked{opacity:.55}
  .dm-dock.collapsed.pill-dragging{transition:none}
  .dm-dock.collapsed .dm-bar{touch-action:none}
  .dm-dock.collapsed .dm-bar{padding:7px 10px;font-size:12px}
  /* build 302: the SAME positioning model as the collapsed pill, so the box can animate between
     them. This was `left:6px;right:6px;top:50px;bottom:6px;width:auto;height:auto` -- four insets
     and two autos, none of which interpolates against a pill expressed as right/bottom plus a
     width. Anchored from the bottom-right with an explicit size, the geometry is identical on a
     360x800 phone (348x744 sitting at 6,50, same as the insets produced) and every one of the four
     properties is now a length at both ends of the transition. */
  .dm-dock:not(.collapsed){right:6px;bottom:6px;left:auto;top:auto;width:calc(100vw - 12px);height:calc(100vh - 56px)}
  .dm-dock:not(.collapsed) .dm-bar{padding:10px 12px}
  /* the dock is a full-screen takeover here, so the bubbles and the friend-request bell (all of
     which float above it) step aside until it's collapsed again */
  .gc-root.dm-open .thread-toggle-fab,.gc-root.dm-open .roulette-toggle-fab{display:none !important}
  /* same call as the room composer (#emoBtn above): the phone keyboard already has emoji */
  .im .icomp .emo{display:none}
  .im .icomp{grid-template-columns:auto auto auto 1fr auto}
}
/* Desktop: the roulette bubble floats at the right edge, vertically centred -- right where the
   expanded dock's top-right corner lands on a typical laptop screen. While the dock is open it
   moves left of the panel (only until someone drags it: a dragged bubble carries inline
   left/right, which wins over this). */
@media (min-width:501px){
  .gc-root.dm-open .roulette-toggle-fab{right:calc(clamp(260px,calc(50vw - 396px),340px) + 20px)}
  /* v117 (build 168): an open conversation -- a whisper or a group -- is bigger than the inbox list:
     up to 400px wide (from 340; never under 280) and up to 760px tall (from 480), so a game card
     fits without scrolling. At 480 a Battleship card in play overflowed the log by up to 194px.
     The inbox list keeps the old size. The price, on screens wide enough for the Ballot Box gutter:
     while a conversation is open the dock covers the lower part of the Ballot Box, which comes back
     the moment the dock goes back to the list or is collapsed. */
  .dm-dock.thread{width:clamp(280px,calc(50vw - 396px),400px);height:min(760px,calc(100vh - 16px))}
  .gc-root.dm-open.dm-thread .roulette-toggle-fab{right:calc(clamp(280px,calc(50vw - 396px),400px) + 20px)}
  /* and on a short screen (a 1536x864 laptop at 125% leaves ~730px) the sea gives up a few pixels so the
     whole card still fits: the card is the grid plus ~262px, the log is the dock minus ~159px */
  .dm-dock .bs-grid{max-width:min(340px,100%,max(200px,calc(100vh - 440px)))}
}

/* ==================== the Ballot Box (v69) ====================
   The right-hand gutter's counterpart to the roulette teaser on the left: same fixed offset from
   centre (394px = half the 760px window + its border/glow), same 260px width and frame treatment,
   same 1340px breakpoint -- below that the window fills the viewport and there's no gutter to put
   it in. Only the TOP half of the gutter, by request; the Messages dock keeps the bottom. Hidden
   until signed on (app.js drops .hidden after the room loads). */
.ballot-panel{position:fixed;top:6px;left:calc(50% + 394px);width:260px;height:max(calc(50vh - 9px),360px);display:none;
flex-direction:column;align-items:center;text-align:center;padding:18px 16px 12px;
background:linear-gradient(180deg,var(--stone-2),var(--stone));border:3px double var(--gold-lo);outline:1px solid #000;
box-shadow:0 0 0 2px var(--gold-lo),0 0 0 3px #000,0 0 24px #000,inset 0 0 30px #000;overflow:hidden;z-index:8}
@media (min-width:1340px){.ballot-panel{display:flex}}
.ballot-panel.hidden{display:none !important}
/* dims along with the window when the threads board is up, same as the roulette teaser */
.gc-root.thread-open .ballot-panel{opacity:.28;filter:saturate(.4)}
.bp-title{font:700 22px Cinzel,"Trajan Pro",Georgia,serif;letter-spacing:2px;line-height:1.15;color:var(--gold);
text-shadow:0 0 12px rgba(201,162,74,.55),0 2px 0 #000,0 -1px 0 #000}
.bp-blurb{font-size:12px;line-height:1.5;color:var(--bone);opacity:.75;margin-top:6px}
.bp-box{width:140px;height:auto;margin:4px 0 0;flex:none;filter:drop-shadow(0 6px 8px #000)}
.bp-box svg{display:block;width:100%;height:auto;overflow:visible}
/* the slip drops through the slot when a note is cast (see castBallot in app.js) */
.bp-box .bp-slip{transform-box:fill-box;transform-origin:50% 100%}
.bp-box.casting .bp-slip{animation:bp-drop .9s ease-in forwards}
@keyframes bp-drop{0%{transform:translateY(0);opacity:1}55%{transform:translateY(22px);opacity:1}100%{transform:translateY(34px) scaleY(.2);opacity:0}}
.bp-compose{width:100%;flex:none;display:flex;flex-direction:column;gap:6px}
.bp-compose textarea{font:inherit;font-size:13px;color:var(--bone);resize:none;height:52px;padding:6px 8px;outline:none;caret-color:var(--gold-hi);width:100%}
.bp-compose textarea:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold),0 0 10px rgba(201,162,74,.35)}
.bp-compose textarea::placeholder{color:#5f5648}
.bp-row{display:flex;align-items:center;justify-content:space-between;gap:8px}
.bp-count{font:10px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash)}
.bp-count.low{color:var(--ember)}
.bp-row .btn{height:28px}
.bp-note{min-height:14px;font-size:11px;font-style:italic;color:var(--ash)}
.bp-note.err{color:#e07a7a}
/* The parchment: a thin header sitting on top of the chat window, exactly the window's width
   (v71 -- it used to be a strip along the bottom of the gutter panel). One note at a time crosses
   it right-to-left; the animation runs 15s per crossing and app.js swaps the text at each
   animationiteration, so each note gets exactly one pass. Fixed at the top of the page, centred
   the same way .win is (760px cap, full width below that); the window itself is pushed down
   34px once signed on (see .gc-root.signed-on below) so the two stack rather than overlap. Desktop
   widths only -- phones have the unrolling scroll inside the log instead. */
.bp-header{position:fixed;top:6px;left:50%;transform:translateX(-50%);width:min(760px,100vw);height:26px;z-index:9;overflow:hidden;
background:
 radial-gradient(ellipse at 20% 30%,rgba(255,255,255,.18),transparent 45%),
 radial-gradient(ellipse at 80% 70%,rgba(90,60,20,.25),transparent 40%),
 linear-gradient(180deg,#e2cf9f,#cbb279 60%,#b89d66);
border:2px solid #6b5323;border-bottom:none;border-radius:5px 5px 0 0;outline:1px solid #000;
box-shadow:inset 0 0 14px rgba(90,60,20,.55),inset 0 1px 0 rgba(255,255,255,.35),0 -2px 10px #000}
.bp-header.hidden{display:none !important}
.bp-hlabel{position:absolute;left:8px;top:0;height:22px;line-height:22px;font-size:13px;z-index:1;
filter:sepia(.6) saturate(.8) drop-shadow(0 1px 0 rgba(255,255,255,.4))}
.bp-scroll{position:absolute;inset:0;left:28px;right:22px;display:flex;align-items:center;white-space:nowrap}
.bp-text{display:inline-block;padding-left:100%;font:13px "IM Fell English",Georgia,serif;color:#3a2a10;text-shadow:0 1px 0 rgba(255,255,255,.35);
animation:bp-ticker 15s linear infinite}
.bp-header.paused .bp-text{animation-play-state:paused}
@keyframes bp-ticker{from{transform:translateX(0)}to{transform:translateX(-100%)}}
@media (prefers-reduced-motion:reduce){.bp-text{animation:none;padding-left:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}}
@media (max-width:500px){.bp-header{display:none !important}}
/* room for the header: the window and the two controls pinned to its top corners step down */
/* v123: the header strip is retired (display:none below), so the window no longer steps down for it */
.bp-header{display:none !important}
.bp-remove{position:absolute;top:50%;transform:translateY(-50%);right:4px;width:18px;height:18px;line-height:16px;padding:0;font:700 11px Georgia,serif;
color:#6b5323;background:rgba(255,255,255,.35);border:1px solid #6b5323;border-radius:50%;cursor:pointer;opacity:.6}
.bp-remove:hover,.bp-remove:focus-visible{opacity:1;color:#fff;background:var(--blood);border-color:#000;outline:none}
/* (The expanded dock is allowed to rise over the ballot box on the wide layout -- it's above it in
   stacking order -- and collapsing the dock brings the box back. An earlier cap kept it to the
   bottom half; dropped by request.) */

/* ==================== the Ballot Box as a scroll (v70) ====================
   Every screen WITHOUT the right-hand gutter (below 1340px -- phones first, but a narrow desktop
   window too): a rolled-up parchment tucked into the top-right corner of the chat log. Once a
   minute (app.js showMobileNote) it unrolls leftward across the log, one note rides it, and it
   rolls back up. It's absolutely positioned over the log, never in the flow, so the chat doesn't
   move when it appears; .body gets position:relative purely to anchor it. */
.body{position:relative}
.bp-mscroll{position:absolute;top:14px;right:14px;left:14px;height:44px;z-index:5;pointer-events:none}
@media (min-width:501px){.bp-mscroll{right:calc(var(--users-w,160px) + 24px);top:18px;left:18px}}
/* v123: (the min-width:1340px display:none is gone -- the scroll now shows on the wide layout too) */
/* the roller: a wooden rod with a brass cap, all that shows while rolled up */
.bp-mroller{position:absolute;top:0;right:0;width:18px;height:44px;padding:0;cursor:pointer;pointer-events:auto;
border:1px solid #1c1108;border-radius:9px;
background:linear-gradient(90deg,#361d07,#8a5c32 40%,#c48a52 50%,#8a5c32 60%,#361d07);
box-shadow:0 0 0 1px #000,0 4px 10px #000,inset 0 0 6px rgba(0,0,0,.5);opacity:.9}
.bp-mroller:hover,.bp-mroller:focus-visible{opacity:1;box-shadow:0 0 0 1px #000,0 4px 10px #000,0 0 10px rgba(201,162,74,.6);outline:none}
.bp-mroller-cap{position:absolute;left:2px;right:2px;height:5px;top:-1px;border-radius:3px;background:linear-gradient(90deg,#7a5a1e,#f1d98a,#7a5a1e);box-shadow:0 0 0 1px #000}
.bp-mroller-cap::after{content:"";position:absolute;left:0;right:0;top:40px;height:5px;border-radius:3px;background:inherit;box-shadow:inherit}
/* the parchment unrolls out of the roller, leftward */
.bp-mparch{position:absolute;right:16px;top:4px;bottom:4px;width:0;overflow:hidden;pointer-events:auto;cursor:pointer;
background:
 radial-gradient(ellipse at 20% 30%,rgba(255,255,255,.18),transparent 45%),
 radial-gradient(ellipse at 80% 70%,rgba(90,60,20,.25),transparent 40%),
 linear-gradient(180deg,#e2cf9f,#cbb279 60%,#b89d66);
border-top:2px solid #6b5323;border-bottom:2px solid #6b5323;border-left:2px solid #6b5323;border-radius:4px 0 0 4px;
box-shadow:inset 0 0 14px rgba(90,60,20,.55),0 4px 12px #000;
transition:width .5s ease}
.bp-mscroll.open .bp-mparch{width:calc(100% - 16px)}
.bp-mscroll.held .bp-mparch{box-shadow:inset 0 0 14px rgba(90,60,20,.55),0 4px 12px #000,0 0 0 2px rgba(201,162,74,.7)}
.bp-mtext{position:absolute;left:12px;top:50%;transform:translateY(-50%);white-space:nowrap;
font:15px "IM Fell English",Georgia,serif;color:#3a2a10;text-shadow:0 1px 0 rgba(255,255,255,.35)}
.bp-mtext .who{color:#5a1c14;font:inherit;font-weight:700;cursor:pointer}
.bp-mtext .who:hover,.bp-mtext .who:focus-visible{text-decoration:underline;outline:none}
/* a note wider than the parchment glides leftward by exactly its overflow (--bp-glide, set in
   app.js), then holds at the end so the tail can be read */
@keyframes bp-mglide{from{transform:translate(0,-50%)}to{transform:translate(var(--bp-glide,0),-50%)}}
.bp-mparch .bp-remove{top:50%;transform:translateY(-50%);right:6px}
@media (prefers-reduced-motion:reduce){.bp-mparch{transition:none}.bp-mtext{animation:none !important}}
/* tagged names on the desktop strip get the same treatment */
.bp-text .who{color:#5a1c14;font:inherit;font-weight:700;cursor:pointer}
.bp-text .who:hover,.bp-text .who:focus-visible{text-decoration:underline;outline:none}
/* the 📜 "drop a note" button lives in the status bar (inside the "..." menu on a phone); on the
   wide layout the panel has its own composer, so the button steps aside there */
@media (min-width:1340px){#ballotBtn{display:none}}
.status .ballotbtn{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);padding:1px 8px;cursor:pointer;border-radius:2px;flex:none}
.status .ballotbtn:hover{color:var(--gold-hi);border-color:var(--gold)}
/* the @ menu has to clear the prompt dialog (z-index 70) when it's serving that dialog's field */
.mention-menu.above-modal{z-index:75}

/* ==================== takeover-page chrome (v77, desktop only since v78) ====================
   While the Threads board has the whole screen on a desktop, the 💬 "back to chat" toggle floated
   over the board's top-right corner rather than keeping the offset it uses over the chat window
   (that one is measured against .win's 760px cap and against the ballot strip -- which the board
   covers anyway -- so it landed a row too low, on top of "Create new post"). The header keeps its
   fixed 44px height so a control centres on it exactly.

   As of v104 this is only a fallback. placeThreadBtn() in app.js moves the button into the board's
   header for real on desktop, and .in-header then styles it as a plain glyph beside the title (see
   the v104 block at the end of this file) -- so the :not(.in-header) below is what stands down and
   lets that happen. It is kept rather than deleted so that a desktop browser which somehow never
   ran the move still gets a button in a sensible place instead of one parked over the board at the
   offset meant for the chat window. Phones are left alone either way: the bubble keeps floating
   wherever it was dragged. */
.tp-hd{min-height:44px;box-sizing:border-box;padding-top:8px;padding-bottom:8px}
@media (min-width:501px){
  .gc-root.signed-on.mobile-threads-open .thread-toggle-fab:not(.in-header){position:fixed !important;top:5px !important;right:8px !important;left:auto !important;bottom:auto !important;
  transform:none !important;width:34px;height:34px;font-size:17px;opacity:1;z-index:56}
}

/* ==================== Tic-Tac-Toe in whispers (v109) ====================
   One card per game inside the whisper log (see renderGameCard in app.js). Purple trim to match
   the dock it lives in; gold X, lilac O; the winning three glow when a game ends; only the
   squares you can actually play are enabled, and only on your turn (.live). */
.ttt-card,.uno-card{margin:8px 4px;padding:8px 10px;border:1px solid #7a4bb0;background:linear-gradient(180deg,#1a111f,#0d0510);box-shadow:0 0 0 1px #000,inset 0 0 18px #000}
.ttt-hd{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:6px}
.ttt-title{font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:#e2c4ff;text-shadow:0 1px 0 #000}
.ttt-rec{font:11px "IM Fell English",Georgia,serif;color:var(--ash);white-space:nowrap}
.ttt-board{display:grid;grid-template-columns:repeat(3,44px);grid-auto-rows:44px;gap:3px;justify-content:center;margin:6px auto 8px;padding:4px;
background:#7a4bb0;border-radius:3px;box-shadow:0 0 0 1px #000,0 0 10px rgba(122,75,176,.35);width:max-content}
.ttt-cell{font:700 24px Cinzel,Georgia,serif;line-height:1;color:var(--bone);background:linear-gradient(180deg,#0e0906,#050200);border:0;border-radius:2px;
display:flex;align-items:center;justify-content:center;cursor:default;padding:0;box-shadow:inset 0 0 8px #000}
.ttt-cell.x{color:var(--gold-hi);text-shadow:0 0 8px rgba(241,217,138,.5)}
.ttt-cell.o{color:#c9a3e6;text-shadow:0 0 8px rgba(201,163,230,.5)}
.ttt-cell.win{background:linear-gradient(180deg,#3a2a48,#1d1126);box-shadow:inset 0 0 0 1px #e2c4ff,0 0 10px rgba(226,196,255,.6)}
.ttt-board.live .ttt-cell:not([disabled]){cursor:pointer}
.ttt-board.live .ttt-cell:not([disabled]):hover,.ttt-board.live .ttt-cell:not([disabled]):focus-visible{background:linear-gradient(180deg,#241831,#0e0918);box-shadow:inset 0 0 0 1px #a67ad1;outline:none}
.ttt-status{font:13px "IM Fell English",Georgia,serif;color:var(--bone);text-align:center;margin-bottom:6px}
.ttt-status b{color:#e2c4ff;font-weight:700}
.ttt-cap{color:var(--ash);font-style:italic;font-size:11px}
.ttt-actions{display:flex;justify-content:center;gap:6px;flex-wrap:wrap}
.ttt-actions .btn{min-width:0;height:26px;padding:0 12px;font-size:11px;color:#e2c4ff;border-color:#7a4bb0;background:linear-gradient(180deg,#3a2a48,#110918)}
.ttt-actions .btn.ttt-resign,.ttt-actions .btn.ttt-decline,.ttt-actions .btn.ttt-cancel,.ttt-actions .btn.uno-resign,.ttt-actions .btn.uno-decline,.ttt-actions .btn.uno-cancel,.ttt-actions .btn.uno-nopick{color:var(--ash);border-color:#3d2a4d}
.ttt-actions .btn.ttt-accept,.ttt-actions .btn.uno-accept{color:#cdeecd;border-color:var(--leaf)}
.ttt-actions .btn.uno-call{color:#fff;border-color:var(--blood);background:linear-gradient(180deg,#b3261e,#5a120e);font-weight:700;letter-spacing:1px}
.ttt-actions .btn.uno-catch{color:var(--gold-hi);border-color:var(--gold)}
@media (hover:none) and (pointer:coarse){.ttt-board{grid-template-columns:repeat(3,54px);grid-auto-rows:54px}.ttt-cell{font-size:28px}.ttt-actions .btn{height:34px}}

/* leaderboard tabs (v110) reuse the admin page's tab styling; the streak flame sits beside the level badge */
.lb-tabs{padding-top:8px}
.lb-streak{flex:none;font:700 11px Cinzel,Georgia,serif;color:#ffb14a;text-shadow:0 0 6px rgba(255,140,0,.6);margin-left:2px}

/* ---------- UNO (v112) ----------
   The card chrome (.uno-card, .ttt-hd/.ttt-status/.ttt-actions) is shared with Tic-Tac-Toe above;
   this is just the cards themselves. A card is a .uno-c button: colour class R/G/B/Y/W, .back for
   a face-down card, .small for the opponent's fanned backs, .ok when it can be played right now. */
.uno-c{position:relative;flex:none;width:38px;height:54px;padding:0;border-radius:5px;border:2px solid #f3ead6;box-shadow:0 0 0 1px #000,0 2px 4px #000;
font:700 17px Cinzel,Georgia,serif;line-height:1;color:#fff;text-shadow:0 1px 0 #000,0 0 4px rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;cursor:default}
.uno-c::after{content:"";position:absolute;inset:4px;border-radius:50%/40%;border:1px solid rgba(255,255,255,.35);pointer-events:none}
.uno-c.R{background:radial-gradient(circle at 50% 40%,#f25545,#9c160c)}
.uno-c.G{background:radial-gradient(circle at 50% 40%,#57c561,#18701f)}
.uno-c.B{background:radial-gradient(circle at 50% 40%,#4a97f2,#0f3d94)}
.uno-c.Y{background:radial-gradient(circle at 50% 40%,#f6de5a,#a37f0c)}
.uno-c.W{background:conic-gradient(from 45deg,#e33 0 25%,#f6de5a 0 50%,#57c561 0 75%,#4a97f2 0);color:#fff}
.uno-c.back{background:repeating-linear-gradient(45deg,#110918 0 4px,#3a2a48 4px 8px);border-color:#7a4bb0;color:#e2c4ff;font-size:13px}
.uno-c.back::after{border-color:rgba(226,196,255,.35)}
.uno-c.small{width:22px;height:32px;font-size:10px;border-width:1px;margin-left:-9px;box-shadow:0 0 0 1px #000}
.uno-c.small::after{inset:2px}
.uno-opp{display:flex;align-items:center;justify-content:center;gap:8px;font:12px "IM Fell English",Georgia,serif;color:var(--ash);margin:2px 0 6px;flex-wrap:wrap}
.uno-backs{display:flex;padding-left:9px}
.uno-badge{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:#fff;background:var(--blood);padding:2px 6px;border-radius:3px;box-shadow:0 0 0 1px #000,0 0 8px rgba(179,38,30,.7)}
.uno-table{display:flex;align-items:center;justify-content:center;gap:22px;margin:4px 0 6px}
.uno-pile{display:flex;flex-direction:column;align-items:center;gap:3px;background:none;border:0;padding:2px;cursor:default;color:var(--ash);font:11px "IM Fell English",Georgia,serif}
.uno-pile:not([disabled]){cursor:pointer;color:var(--gold-hi)}
.uno-pile.must .uno-c{border-color:var(--gold-hi);box-shadow:0 0 0 2px var(--gold-hi),0 0 18px 4px rgba(241,217,138,.85);animation:uno-must .9s ease-in-out infinite alternate}
.uno-pile.must{color:var(--gold-hi);text-shadow:0 0 6px rgba(241,217,138,.8)}
@keyframes uno-must{from{box-shadow:0 0 0 2px var(--gold-hi),0 0 10px 2px rgba(241,217,138,.6)}to{box-shadow:0 0 0 2px #fff6c8,0 0 24px 6px rgba(241,217,138,1)}}
.uno-pile:not([disabled]):hover .uno-c,.uno-pile:not([disabled]):focus-visible .uno-c{transform:translateY(-2px);border-color:var(--gold-hi)}
.uno-pile:focus-visible{outline:none}
.uno-top{display:flex;align-items:center;gap:8px}
.uno-top .uno-c{width:46px;height:64px;font-size:22px}
.uno-colour{width:16px;height:16px;border-radius:50%;border:2px solid #f3ead6;box-shadow:0 0 0 1px #000;display:inline-block;flex:none}
.uno-colour.R,.uno-col.R{background:#e0402f}.uno-colour.G,.uno-col.G{background:#3fae4a}.uno-colour.B,.uno-col.B{background:#2f7fe0}.uno-colour.Y,.uno-col.Y{background:#f0cf3c}
.uno-hand{display:flex;gap:7px;overflow-x:auto;padding:8px 6px 6px;margin:0 -4px 4px;scrollbar-width:thin;scrollbar-color:#7a4bb0 transparent;-webkit-overflow-scrolling:touch}
.uno-hand > .uno-c:first-child{margin-left:auto}.uno-hand > .uno-c:last-child{margin-right:auto}
.uno-hand .uno-c{opacity:.5;filter:saturate(.7)}
.uno-hand.live .uno-c.ok{opacity:1;filter:none;cursor:pointer;transform:translateY(-3px);box-shadow:0 0 0 1px #000,0 0 10px rgba(241,217,138,.55)}
.uno-hand.live .uno-c.ok:hover,.uno-hand.live .uno-c.ok:focus-visible{border-color:var(--gold-hi);transform:translateY(-6px);box-shadow:0 0 0 1px #000,0 0 14px rgba(241,217,138,.9);outline:none}
.uno-col{width:30px;height:30px;border-radius:50%;border:2px solid #f3ead6;box-shadow:0 0 0 1px #000;padding:0;cursor:pointer}
.uno-col:hover,.uno-col:focus-visible{transform:scale(1.12);box-shadow:0 0 0 1px #000,0 0 10px rgba(241,217,138,.8);outline:none}
.uno-last{font:italic 11px "IM Fell English",Georgia,serif;color:var(--ash);text-align:center;margin-bottom:4px}
@media (hover:none) and (pointer:coarse){.uno-c{width:44px;height:62px;font-size:19px}.uno-top .uno-c{width:50px;height:70px}.uno-c.small{width:22px;height:32px}.uno-col{width:36px;height:36px}}

/* ---------- v113: whisper title-bar banner, admin flames, turn clock, bottom row, wheel ---------- */
.im .bar .nm.admin{color:var(--admin);text-shadow:0 0 8px rgba(209,59,47,.5),0 1px 0 #000}
.im-sub{display:flex;align-items:center;gap:6px;min-height:14px;font:11px "IM Fell English",Georgia,serif;color:var(--ash);white-space:nowrap;overflow:hidden}
.im-sub .presence-dot{margin:0}
.im-sub .im-st{flex:none}
.im-sub .im-msg{font-style:italic;color:var(--bone);overflow:hidden;text-overflow:ellipsis;min-width:0}
.im-sub .lvl{flex:none}
.adm-title{flex:none;font:700 15px "Dancing Script",cursive;line-height:1;color:#ffcc66;letter-spacing:.5px;
text-shadow:0 0 3px #ffb347,0 0 8px #ff8c00,0 0 16px rgba(255,120,0,.85),0 0 28px rgba(255,90,0,.5)}
/* Admin names: red everywhere (see the --admin rules above), and in the main room and whispers a
   pixel-art fire burns behind the name -- a 12x8 three-frame sprite, scaled 2x with crisp pixels,
   repeated along the width of the name. */
.log .m b.who.admin,.im .ilog b.who.admin{color:var(--admin)}
.log .m b.who.admin .nmt,.im .ilog b.who.admin .nmt,.nmenu .hd .hd-name.admin,.users .list div.admin .nmt,.tp-posts .tp-post b.who.admin .nmt,.tp-op.admin .nmt{position:relative;z-index:0;isolation:isolate;display:inline-block;padding:0 3px;margin:0 1px;color:#ff6d5c;text-shadow:0 1px 0 #000,0 0 2px #000}
.log .m b.who.admin .nmt::after,.im .ilog b.who.admin .nmt::after,.nmenu .hd .hd-name.admin::after,.users .list div.admin .nmt::after,.tp-posts .tp-post b.who.admin .nmt::after,.tp-op.admin .nmt::after{content:"";position:absolute;left:0;right:0;top:0;bottom:-1px;z-index:-1;border-radius:2px;background:rgba(12,4,3,.7);pointer-events:none}
.log .m b.who.admin .nmt::before,.im .ilog b.who.admin .nmt::before,.nmenu .hd .hd-name.admin::before,.users .list div.admin .nmt::before,.tp-posts .tp-post b.who.admin .nmt::before,.tp-op.admin .nmt::before{content:"";position:absolute;left:-4px;right:-4px;bottom:3px;height:16px;z-index:-2;pointer-events:none;opacity:.9;
background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMiAyNCIgd2lkdGg9IjEyIiBoZWlnaHQ9IjI0IiBzaGFwZS1yZW5kZXJpbmc9ImNyaXNwRWRnZXMiPjxyZWN0IHg9IjQiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIzIiB5PSIxIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iNCIgeT0iMSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjgiIHk9IjEiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIyIiB5PSIyIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMyIgeT0iMiIgd2lkdGg9IjIiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjciIHk9IjIiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSI4IiB5PSIyIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iOSIgeT0iMiIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjEiIHk9IjMiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIyIiB5PSIzIiB3aWR0aD0iMyIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iNiIgeT0iMyIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjciIHk9IjMiIHdpZHRoPSIzIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSIwIiB5PSI0IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMSIgeT0iNCIgd2lkdGg9IjkiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjEwIiB5PSI0IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMCIgeT0iNSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjEiIHk9IjUiIHdpZHRoPSIzIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSI0IiB5PSI1IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjYjgyMzFmIi8+PHJlY3QgeD0iNSIgeT0iNSIgd2lkdGg9IjMiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjgiIHk9IjUiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNiODIzMWYiLz48cmVjdCB4PSI5IiB5PSI1IiB3aWR0aD0iMiIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMTEiIHk9IjUiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIxIiB5PSI2IiB3aWR0aD0iMiIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMyIgeT0iNiIgd2lkdGg9IjciIGhlaWdodD0iMSIgZmlsbD0iI2I4MjMxZiIvPjxyZWN0IHg9IjEwIiB5PSI2IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMiIgeT0iNyIgd2lkdGg9IjgiIGhlaWdodD0iMSIgZmlsbD0iI2I4MjMxZiIvPjxyZWN0IHg9IjciIHk9IjgiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIyIiB5PSI5IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iNiIgeT0iOSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjciIHk9IjkiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSIxIiB5PSIxMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjIiIHk9IjEwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iNSIgeT0iMTAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSI2IiB5PSIxMCIgd2lkdGg9IjIiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjkiIHk9IjEwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMSIgeT0iMTEiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIyIiB5PSIxMSIgd2lkdGg9IjIiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjUiIHk9IjExIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iNiIgeT0iMTEiIHdpZHRoPSIyIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSI4IiB5PSIxMSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjkiIHk9IjExIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMTAiIHk9IjExIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMCIgeT0iMTIiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIxIiB5PSIxMiIgd2lkdGg9IjEwIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSIxMSIgeT0iMTIiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIwIiB5PSIxMyIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjEiIHk9IjEzIiB3aWR0aD0iMiIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMyIgeT0iMTMiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNiODIzMWYiLz48cmVjdCB4PSI0IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjciIHk9IjEzIiB3aWR0aD0iMiIgaGVpZ2h0PSIxIiBmaWxsPSIjYjgyMzFmIi8+PHJlY3QgeD0iOSIgeT0iMTMiIHdpZHRoPSIyIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSIxMSIgeT0iMTMiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIxIiB5PSIxNCIgd2lkdGg9IjIiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjMiIHk9IjE0IiB3aWR0aD0iNyIgaGVpZ2h0PSIxIiBmaWxsPSIjYjgyMzFmIi8+PHJlY3QgeD0iMTAiIHk9IjE0IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMiIgeT0iMTUiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiIGZpbGw9IiNiODIzMWYiLz48cmVjdCB4PSIyIiB5PSIxNiIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjEiIHk9IjE3IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMiIgeT0iMTciIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSI3IiB5PSIxNyIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjEiIHk9IjE4IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMiIgeT0iMTgiIHdpZHRoPSIyIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSI2IiB5PSIxOCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjciIHk9IjE4IiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iOCIgeT0iMTgiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIxMCIgeT0iMTgiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIwIiB5PSIxOSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmZDk0YSIvPjxyZWN0IHg9IjEiIHk9IjE5IiB3aWR0aD0iMyIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iNSIgeT0iMTkiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSI2IiB5PSIxOSIgd2lkdGg9IjMiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjEwIiB5PSIxOSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjAiIHk9IjIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMSIgeT0iMjAiIHdpZHRoPSIxMCIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMTEiIHk9IjIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMCIgeT0iMjEiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmQ5NGEiLz48cmVjdCB4PSIxIiB5PSIyMSIgd2lkdGg9IjMiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjQiIHk9IjIxIiB3aWR0aD0iMiIgaGVpZ2h0PSIxIiBmaWxsPSIjYjgyMzFmIi8+PHJlY3QgeD0iNiIgeT0iMjEiIHdpZHRoPSIyIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSI4IiB5PSIyMSIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2I4MjMxZiIvPjxyZWN0IHg9IjkiIHk9IjIxIiB3aWR0aD0iMiIgaGVpZ2h0PSIxIiBmaWxsPSIjZmY3YTFhIi8+PHJlY3QgeD0iMTEiIHk9IjIxIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjZmZkOTRhIi8+PHJlY3QgeD0iMSIgeT0iMjIiIHdpZHRoPSIyIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZjdhMWEiLz48cmVjdCB4PSIzIiB5PSIyMiIgd2lkdGg9IjciIGhlaWdodD0iMSIgZmlsbD0iI2I4MjMxZiIvPjxyZWN0IHg9IjEwIiB5PSIyMiIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0iI2ZmN2ExYSIvPjxyZWN0IHg9IjIiIHk9IjIzIiB3aWR0aD0iOCIgaGVpZ2h0PSIxIiBmaWxsPSIjYjgyMzFmIi8+PC9zdmc+") repeat-x 0 0/24px 48px;image-rendering:pixelated;image-rendering:crisp-edges;
animation:flame-flicker .48s steps(3,jump-none) infinite}
@keyframes flame-flicker{from{background-position-y:0}to{background-position-y:-32px}}
@media (prefers-reduced-motion:reduce){.log .m b.who.admin .nmt::before,.im .ilog b.who.admin .nmt::before,.nmenu .hd .hd-name.admin::before,.users .list div.admin .nmt::before,.tp-posts .tp-post b.who.admin .nmt::before,.tp-op.admin .nmt::before{animation:none}}
/* the Online / Friends rows clip overflow for their ellipsis, so the fire on an admin's row needs room: */
.users .list div.admin{overflow:visible;padding-top:2px;padding-bottom:2px}
.users .list div.admin .nmt::before{bottom:4px}
.users .list div.blocked.admin .nmt{color:inherit}
.users .list div.blocked.admin .nmt::before,.users .list div.blocked.admin .nmt::after{display:none}
.nmenu .hd .hd-name.admin{margin-bottom:6px;padding:1px 5px;overflow:visible;text-overflow:clip}
.nmenu .hd .hd-name.admin::before{height:18px;bottom:5px;left:-5px;right:-5px;background-size:24px 48px;opacity:.9}
.nmenu .hd .hd-name.admin::after{top:4px;bottom:3px}
/* the 30-second turn clock on every active game card */
.turn-clock{position:relative;height:14px;margin:2px 10px 6px;background:#020005;border:1px solid #3d2a4d;border-radius:2px;overflow:hidden;box-shadow:inset 0 0 6px #000}
.turn-clock .tc-bar{position:absolute;left:0;top:0;bottom:0;background:linear-gradient(90deg,#4d2f6b,#a67ad1);transition:width .25s linear}
.turn-clock .tc-num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font:700 10px Cinzel,Georgia,serif;color:#e2c4ff;text-shadow:0 1px 0 #000}
.turn-clock.low .tc-bar{background:linear-gradient(90deg,#7a1f17,#e0402f)}
.turn-clock.low .tc-num{color:#fff;animation:tc-blink 1s steps(2,jump-none) infinite}
@keyframes tc-blink{from{opacity:1}to{opacity:.55}}
/* desktop bottom row: bigger icons with a word under each */
@media (min-width:501px){
  .status{flex-wrap:wrap;justify-content:flex-start;align-items:stretch;gap:5px;padding:5px 10px}
  .status #st{align-self:center}
  .status button.cell:not(.hidden){display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:54px;max-width:96px;padding:4px 6px;line-height:1}
  .status .btn-icon{font-size:19px;line-height:1}
  .status .popover-label{display:block;font:600 8px Cinzel,Georgia,serif;letter-spacing:.5px;text-transform:uppercase;white-space:normal;text-align:center;line-height:1.2;max-width:84px}
  .status .ava-thumb{width:20px;height:20px;font-size:15px}.status .ava-thumb img{width:20px;height:20px}
  .status .dmbtn[aria-pressed="true"]{text-decoration:none}
  .status .dmbtn[aria-pressed="true"] .popover-label{text-decoration:line-through}
  .status .rbadge{position:absolute;top:2px;right:4px}
  .status .reportsbtn{position:relative}
}
@media (max-width:500px){.status .ballotbtn,.status .leaderboardbtn,.status .notifbtn{padding:1px 6px}}
/* spin the wheel */
.rp-wheel{cursor:pointer;outline:none}
.rp-wheel:focus-visible{filter:drop-shadow(0 0 14px rgba(241,217,138,.7)) drop-shadow(0 6px 10px #000)}
.rp-wheel.spinning{animation:rp-spin-fast 4s cubic-bezier(.12,.75,.15,1) 1 !important} /* v128: 4 s to match the recorded ratchet */
@keyframes rp-spin-fast{to{transform:rotate(2520deg)}}
.rp-hint{margin-top:14px;font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--ash);opacity:.8}
.rp-hint-mobile{display:none}
@media (hover:none) and (pointer:coarse){.rp-hint-desktop{display:none}.rp-hint-mobile{display:inline}}
.rp-fortune{min-height:0;max-width:230px;margin:10px auto 0;padding:0 6px;font:italic 14px "IM Fell English",Georgia,serif;line-height:1.5;color:var(--gold-hi);text-align:center;
opacity:0;transform:translateY(6px);transition:opacity .6s ease,transform .6s ease;text-shadow:0 0 8px rgba(241,217,138,.35)}
.rp-fortune.show{opacity:1;transform:none}
.gc-root.mobile-roulette-open .rp-fortune{max-width:300px;font-size:17px}

/* ---------- v114: Hangman + Texas Hold'em cards ----------
   Both share the game-card chrome (.ttt-card rules above: header, status, action buttons). */
.hm-card,.hd-card{margin:8px 4px;padding:8px 10px;border:1px solid #7a4bb0;background:linear-gradient(180deg,#1a111f,#0d0510);box-shadow:0 0 0 1px #000,inset 0 0 18px #000}
.ttt-actions .btn.hm-resign,.ttt-actions .btn.hm-decline,.ttt-actions .btn.hm-cancel,.ttt-actions .btn.hd-decline,.ttt-actions .btn.hd-cancel,.ttt-actions .btn.hd-fold{color:var(--ash);border-color:#3d2a4d}
.ttt-actions .btn.hm-accept,.ttt-actions .btn.hd-accept,.ttt-actions .btn.hd-call{color:#cdeecd;border-color:var(--leaf)}
.ttt-actions .btn.hd-leave{color:var(--ash);border-color:#3d2a4d;font-size:10px}
.ttt-actions .btn.hd-leave.armed{color:#fff;border-color:var(--blood);background:linear-gradient(180deg,#b3261e,#5a120e)}
/* hangman */
.hm-table{display:flex;align-items:center;justify-content:center;gap:14px;margin:4px 0 6px}
.hm-gallows{width:60px;height:80px;flex:none;fill:var(--gold);shape-rendering:crispEdges;filter:drop-shadow(0 0 4px rgba(201,162,74,.35))}
.hm-gallows .hm-man{fill:#e2c4ff}
.hm-mid{display:flex;flex-direction:column;align-items:center;gap:5px;min-width:0}
.hm-word{display:flex;flex-wrap:wrap;justify-content:center;gap:4px}
.hm-ch{display:inline-flex;align-items:center;justify-content:center;width:20px;height:26px;font:700 17px Cinzel,Georgia,serif;color:var(--gold-hi);border-bottom:2px solid var(--gold-lo);text-shadow:0 1px 0 #000}
.hm-ch.blank{color:transparent}
.hm-tried{font:11px "IM Fell English",Georgia,serif;color:var(--ash);letter-spacing:1px;text-align:center}
.hm-miss{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:#c9a3e6}
.hm-keys{display:grid;grid-template-columns:repeat(9,1fr);gap:4px;margin:4px 0 6px}
.hm-key{height:26px;padding:0;font:700 12px Cinzel,Georgia,serif;color:#e2c4ff;background:linear-gradient(180deg,#3a2a48,#110918);border:1px solid #7a4bb0;border-radius:2px;cursor:pointer;box-shadow:0 1px 0 #000}
.hm-key:hover:not([disabled]),.hm-key:focus-visible:not([disabled]){color:var(--gold-hi);border-color:var(--gold);outline:none;box-shadow:0 0 8px rgba(241,217,138,.5)}
.hm-key[disabled]{opacity:.35;cursor:default}
.hm-key.used{opacity:.2;text-decoration:line-through}
.hm-solve-row{display:flex;gap:6px;margin-bottom:4px}
.hm-solve-in{flex:1;min-width:0;font:inherit;font-size:13px;color:var(--bone);padding:4px 8px;background:linear-gradient(180deg,#050207,#0e090e);border:1px solid #4d2f6b;outline:none;box-shadow:inset 0 0 12px #000}
.hm-solve-in:focus{box-shadow:inset 0 0 12px #000,0 0 0 1px #a67ad1}
.hm-solve-row .btn{min-width:0;height:28px;padding:0 12px;font-size:11px;color:#e2c4ff;border-color:#7a4bb0;background:linear-gradient(180deg,#3a2a48,#110918)}
@media (hover:none) and (pointer:coarse){.hm-keys{grid-template-columns:repeat(7,1fr)}.hm-key{height:34px;font-size:14px}.hm-solve-in{font-size:16px}}
/* hold'em: playing cards */
.pc{position:relative;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;width:34px;height:48px;border-radius:4px;background:linear-gradient(180deg,#fbf6e8,#e9dfc6);color:#1a1410;border:1px solid #6e5323;box-shadow:0 0 0 1px #000,0 2px 4px #000;font:700 15px Cinzel,Georgia,serif;line-height:1;flex:none}
.pc.red{color:#b3261e}
.pc .pc-s{font-size:14px;margin-top:1px}
.pc.sm{width:26px;height:36px;font-size:11px}.pc.sm .pc-s{font-size:10px}
.pc.back{background:repeating-linear-gradient(45deg,#110918 0 4px,#3a2a48 4px 8px);border-color:#7a4bb0}
.pc.back::after{content:"";position:absolute;inset:3px;border-radius:2px;border:1px solid rgba(226,196,255,.35)}
.pc.slot{background:none;border:1px dashed #3d2a4d;box-shadow:none}
.hd-seat{display:flex;align-items:center;gap:8px;font:12px "IM Fell English",Georgia,serif;color:var(--ash);margin:3px 0;min-height:36px}
.hd-seat.me{flex-direction:row}
.hd-pname{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--bone);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;display:flex;align-items:center;gap:5px}
.hd-btn{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;background:var(--gold-hi);color:#1a1410;font:700 9px Cinzel,Georgia,serif;box-shadow:0 0 0 1px #000;flex:none}
.hd-stack{font:700 12px Cinzel,Georgia,serif;color:var(--gold-hi);white-space:nowrap;text-shadow:0 0 6px rgba(241,217,138,.4)}
.hd-bet{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:20px;padding:0 6px;border-radius:10px;background:radial-gradient(circle at 40% 35%,#e0402f,#7a1f17);color:#fff;font:700 11px Cinzel,Georgia,serif;box-shadow:0 0 0 1px #000,0 0 6px rgba(224,64,47,.6)}
.hd-cards{display:flex;gap:4px;margin-left:auto}
.hd-board{display:flex;justify-content:center;gap:5px;margin:6px 0 4px;padding:6px;background:radial-gradient(ellipse at center,#173624,#031109);border:1px solid #2f5a34;border-radius:24px;box-shadow:inset 0 0 18px #000}
.hd-pot{text-align:center;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);margin-bottom:4px}
.hd-actions{flex-direction:column;align-items:stretch;gap:6px}
.hd-actions>.btn{width:100%}
.hd-fc{display:flex;gap:6px}
.hd-fc .btn{flex:1;min-width:0}
.hd-raise{display:flex;flex-direction:column;gap:4px}
.hd-presets{display:flex;gap:4px}
.hd-presets .btn{flex:1;min-width:0;height:24px;padding:0;font-size:10px;color:var(--ash);border-color:#3d2a4d;background:linear-gradient(180deg,#241831,#0e0918)}
.hd-raise-row{display:flex;gap:4px}
.hd-amt{width:64px;font:inherit;font-size:13px;color:var(--bone);padding:3px 6px;background:linear-gradient(180deg,#050207,#0e090e);border:1px solid #4d2f6b;outline:none;text-align:center}
.hd-raise-row .btn{flex:1;min-width:0;height:26px;font-size:11px;color:var(--gold-hi);border-color:var(--gold)}
@media (hover:none) and (pointer:coarse){.pc{width:40px;height:56px;font-size:17px}.pc.sm{width:28px;height:40px}.hd-amt{font-size:16px;width:76px}}

/* v116: five Popularity Contest tabs on a phone -- wrap into two even rows instead of running off the edge */
@media (max-width:500px){
  .lb-tabs{flex-wrap:wrap;gap:4px;padding:8px 8px 0}
  .lb-tabs .adm-tab{flex:1 1 30%;justify-content:center;padding:8px 4px;font-size:10px;letter-spacing:.5px;white-space:nowrap;border-radius:3px;border-bottom-color:var(--gold-lo)}
  .lb-tabs .adm-tab.active{border-bottom-color:var(--gold)}
}
/* v116: iPhone Safari swallows taps in the top ~40px (that is where the minimised address bar
   comes back), so on iOS every full-screen panel keeps its header and buttons clear of that zone. */
html.ios .gc-root.leaderboard-open .leaderboard-panel,html.ios .gc-root.admin-open .admin-panel,html.ios .gc-root.mobile-threads-open .threads-panel,html.ios .gc-root.mobile-roulette-open .roulette-panel{padding-top:env(safe-area-inset-top);box-sizing:border-box}
@media (max-width:500px){
  html.ios .dm-dock:not(.collapsed){top:calc(env(safe-area-inset-top) + 58px)}
  html.ios .gc-root.signed-on.mobile-threads-open .thread-toggle-fab{top:calc(env(safe-area-inset-top) + 49px) !important}
}

/* v118: on phones the DM toggle is pointless now that the Messages tray is its own pill, and
   Notifications lives in the ... menu again so "Change name" isn't squeezed. Desktop unchanged. */
@media (max-width:500px){#dmToggleBtn{display:none !important}}

/* ==================== v95: UX pass ====================
   1. Rounded corners on every pill-shaped element: reaction pills, badges, the level tag, the
      UNO/Hold'em chips, the Messages tray (collapsed pill AND the open tray), the refresh banner. */
.react-pill{border-radius:10px;padding:1px 8px}
.lvl{border-radius:5px;padding:0 4px}
.uno-badge{border-radius:9px}
.im-tab .badge,.rbadge{border-radius:9px}
.dm-dock{border-radius:12px;overflow:hidden}
.dm-dock.collapsed{border-radius:22px}
.dm-dock .dm-bar{border-radius:inherit}
.dm-dock.thread{border-radius:12px}
.update-banner{border-radius:10px}
.uno-pile,.turn-clock{border-radius:6px}
.users .list div .presence-dot{border-radius:50%}
/* 2. Reduced motion: stop the flames, the roulette wheel, the timer blink and the pulses when the
      system setting asks for it (also saves battery on older phones). Functional transitions stay. */
@media (prefers-reduced-motion:reduce){
  .nmt::before,.nmenu .hd .hd-name.admin::before,.users .list div.admin .nmt::before{animation:none !important}
  .rp-wheel,.rp-wheel.spinning{animation:none !important}
  .tc-num.low,.uno-pile.must,.dm-bar.flash,.im.shake,.dm-dock.shake{animation:none !important}
  *{scroll-behavior:auto !important}
}
/* 3. Keyboard focus: a visible gold ring on anything focusable, only for keyboard users
      (:focus-visible), so mouse/touch taps stay clean. */
button:focus-visible,[role=button]:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px}
.dm-bar:focus-visible,.im-tab:focus-visible{outline:2px solid #e2c4ff;outline-offset:-3px}
/* v121: day dividers in the room log and whispers */
.day-div{display:flex;align-items:center;gap:8px;margin:8px 4px 6px;font:italic 11px "IM Fell English",Georgia,serif;color:#7a6d5a;letter-spacing:.5px}
.day-div::before,.day-div::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,transparent,#362b1f,transparent)}
.im .ilog .day-div{color:#8a7a9c}
.im .ilog .day-div::before,.im .ilog .day-div::after{background:linear-gradient(90deg,transparent,#3d2a4d,transparent)}
/* v121: read-only lines inside an .nmenu bubble (level badge details) */
.nmenu .note{font-size:12px;line-height:1.5;color:var(--bone);padding:4px 10px;max-width:250px}
.nmenu .note:last-child{color:var(--ash);font-style:italic;font-size:11px;border-top:1px solid #2a2119;margin-top:4px;padding-top:7px}
.lvl{cursor:pointer}
/* v121: "who's inside" line on the sign-on screen */
.room-peek{font:italic 12px "IM Fell English",Georgia,serif;color:var(--ash);text-align:center;margin:2px 0 8px;line-height:1.5}
.room-peek b{color:var(--gold);font-style:normal}
/* v121: volume row inside the Sound menu */
.nmenu .note.vol-row{display:flex;align-items:center;gap:8px;font-style:normal;color:var(--bone);border-top:1px solid #2a2119;margin-top:4px;padding-top:8px;font-size:12px}
.nmenu .vol-row input[type=range]{flex:1;min-width:110px;accent-color:var(--gold);margin:0}
.nmenu .vol-row span{min-width:34px;text-align:right;color:var(--ash);font-variant-numeric:tabular-nums}
/* v121: connection state bar -- shows only while the realtime link is down */
.conn-bar{position:fixed;left:50%;top:6px;transform:translateX(-50%);z-index:96;display:none;align-items:center;gap:8px;padding:6px 14px;
font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi);background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);border-radius:14px;box-shadow:0 0 0 1px #000,0 6px 18px #000}
.conn-bar.show{display:flex}
.conn-bar .dot{width:8px;height:8px;border-radius:50%;background:#e0402f;box-shadow:0 0 6px #e0402f;animation:tc-blink 1s steps(2,jump-none) infinite}
.conn-bar.ok .dot{background:#39ff6a;box-shadow:0 0 6px #39ff6a;animation:none}
html.ios .conn-bar{top:calc(env(safe-area-inset-top) + 46px)}
/* v121: the phone's ⋯ menu is grouped -- Profile / Settings / Help -- so "things about me" and
   "things about the app" are never in one undifferentiated pile. Desktop flattens the popover
   into the bottom row (display:contents), where the headers stay hidden. */
.pop-hd{display:none}
@media (max-width:500px){
  #statusPopover{gap:4px;border-radius:10px}
  #statusPopover .pop-hd{display:block;font:700 9px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold-lo);padding:6px 4px 2px;border-top:1px solid #2a2119;margin-top:2px}
  #statusPopover .pop-hd:first-child{border-top:none;margin-top:0;padding-top:2px}
  #statusPopover .cell{padding:6px 8px;border-radius:6px}
}
@media (max-width:500px){
  /* real on/off switches beside Notifications and Sound in the ⋯ menu, driven by aria-pressed */
  #statusPopover .notifbtn,#statusPopover .soundbtn{position:relative;padding-right:52px}
  #statusPopover .notifbtn::after,#statusPopover .soundbtn::after{content:"OFF";position:absolute;right:8px;top:50%;transform:translateY(-50%);font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash);border:1px solid #3a3026;border-radius:9px;padding:2px 7px;background:#050200}
  #statusPopover .notifbtn[aria-pressed="true"]::after,#statusPopover .soundbtn[aria-pressed="true"]::after{content:"ON";color:#39ff6a;border-color:rgba(57,255,106,.5);box-shadow:0 0 6px rgba(57,255,106,.3)}
}
/* v121: "N new messages ↓" pill over the bottom edge of the room log */
.new-pill{position:fixed;z-index:30;transform:translate(-50%,0);font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#1a1410;background:linear-gradient(180deg,var(--gold-hi),var(--gold));border:1px solid #000;border-radius:14px;padding:5px 14px;cursor:pointer;box-shadow:0 0 0 1px var(--gold-lo),0 4px 12px #000,0 0 12px rgba(201,162,74,.5)}
.new-pill:hover{filter:brightness(1.08)}
.new-pill.hidden{display:none}
/* v121: first-run tips */
.tour{position:fixed;z-index:97;background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);border-radius:10px;outline:1px solid #000;box-shadow:0 0 0 1px #000,0 8px 24px #000,0 0 18px rgba(201,162,74,.25);padding:10px 12px;color:var(--bone);font-size:13px;line-height:1.5}
.tour-n{font:700 9px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);margin-bottom:4px}
.tour-b{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}
.tour-b .btn{height:26px;font-size:11px}
.tour-b .tour-skip{color:var(--ash);border-color:#3a3026}
.tour-hi{outline:2px solid var(--gold-hi) !important;outline-offset:2px;box-shadow:0 0 16px rgba(255,223,126,.55) !important;transition:box-shadow .2s}
/* v121: "/" command palette rows -- command on the left, what it does on the right */
.cmd-menu{min-width:240px;max-width:min(360px,calc(100vw - 12px));max-height:230px}
.cmd-menu button{display:flex;align-items:baseline;gap:10px}
.cmd-menu .cmd-c{flex:none;font:700 13px Georgia,serif;color:var(--gold);text-transform:none;letter-spacing:0} /* Georgia, not Cinzel: Cinzel has no lowercase, and commands are typed in lowercase */
.cmd-menu .cmd-c i{font:italic 11px "IM Fell English",Georgia,serif;color:var(--ash)}
.cmd-menu .cmd-d{flex:1;min-width:0;font-weight:normal;font-size:11px;color:var(--bone);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cmd-menu button.active .cmd-c{color:var(--gold-hi)}
/* v121: toasts (game challenges / your move / results) */
.toasts{position:fixed;right:10px;top:10px;z-index:94;display:flex;flex-direction:column;gap:8px;width:min(300px,calc(100vw - 20px));pointer-events:none}
.toast{pointer-events:auto;display:flex;align-items:flex-start;gap:8px;padding:9px 10px;cursor:pointer;color:var(--bone);
background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);border-radius:12px;outline:1px solid #000;
box-shadow:0 0 0 1px #000,0 8px 24px #000,0 0 14px rgba(201,162,74,.3);animation:toast-in .22s ease-out}
.toast.out{opacity:0;transform:translateY(-6px);transition:opacity .3s,transform .3s}
@keyframes toast-in{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.toast-i{font-size:20px;line-height:1;flex:none;margin-top:1px}
.toast-body{flex:1;min-width:0}
.toast-t{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold-hi);line-height:1.35}
.toast-s{font-size:11px;color:var(--ash);margin-top:2px;font-variant-numeric:tabular-nums}
.toast-b{display:flex;gap:6px;margin-top:7px}
.toast-b .btn{height:24px;font-size:10px;min-width:0;padding:0 10px}
.toast-x{flex:none;background:none;border:none;color:var(--ash);font-size:16px;line-height:1;cursor:pointer;padding:0 2px;margin:-2px -2px 0 0}
.toast-x:hover{color:var(--gold-hi)}
@media (max-width:500px){.toasts{left:10px;right:10px;width:auto;top:44px}} /* below the connection bar's slot */
html.ios .toasts{top:calc(env(safe-area-inset-top) + 82px)}
@media (prefers-reduced-motion:reduce){.toast{animation:none}}
/* v122: Log out button (same chrome as its neighbours) + remember-me row + logout dialog */
.status .logoutbtn{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);padding:1px 8px;cursor:pointer;border-radius:2px;flex:none}
.status .logoutbtn:hover{color:#e07a7a;border-color:#e07a7a}
.login label.remember-row{display:flex;align-items:center;justify-content:center;gap:7px;font:italic 12px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;color:var(--ash);margin:4px 0 6px;cursor:pointer;user-select:none;-webkit-user-select:none}
.remember-row input{accent-color:var(--gold);width:15px;height:15px;margin:0;cursor:pointer}
.logout-actions{flex-wrap:wrap}
.logout-actions #logoutGo{color:#e07a7a;border-color:#7a2f2a}
/* v134: avatars sat 5-6px below the centre of the name beside them (vertical-align:-6px hung them
   off the baseline). middle lines the picture up with the middle of the text in chat rows, whispers,
   the Online / Friends lists and thread posts alike. */
.ava,.ava-fallback,.users .list div .ava,.users .list div .ava-fallback{vertical-align:middle}
/* v134: long admin names in the Online / Friends lists ran off the panel (the row had to be
   overflow:visible for the flames). Clip the row again, but pad it so the flames -- which reach
   4px past the name -- still sit inside the row's own box and are not cut. */
.users .list div.admin{overflow:hidden;padding:2px;display:flex;align-items:center;gap:4px}
.users .list div.admin > *{flex:none}
.users .list div.admin .ava,.users .list div.admin .ava-fallback{margin-right:1px}
.users .list div.admin .nmt{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:4px;margin:-4px 0}
.users .list div.admin .nmt::before{left:0;right:0;bottom:7px}
.users .list div.admin .nmt::after{top:4px;bottom:4px}
/* v134: admin names in the threads board -- flames on posts and replies, and on the thread tiles
   (the tile title clips for its ellipsis, so the name carries its own padding for the flames). */
.tp-posts .tp-post b.who.admin .nmt{padding:0 3px}
.tp-op.admin{overflow:visible;padding-bottom:4px}
.tp-op.admin .nmt{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:top;padding:4px;margin:-4px 0}
.tp-op.admin .nmt::before{left:0;right:0;bottom:7px}
.tp-op.admin .nmt::after{top:4px;bottom:4px}

/* ==================== Prasta (Gilet) card, v136 ====================
   Three cards a side. Your own row is tappable during your draw: a picked card lifts and shows an
   ✕, and the Change button counts them. Reuses the Hold'em .pc playing cards. */
.pr-card{margin:6px 0 2px;padding:6px 8px 8px;background:linear-gradient(180deg,#1a111f,#0a060e);
border:2px double #7a4bb0;outline:1px solid #000;border-radius:10px;box-shadow:0 0 0 1px #000,0 3px 10px #000}
.pr-seat{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:3px 0}
.pr-seat .pr-who{font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#e2c4ff;min-width:52px}
.pr-seat.me .pr-who{color:var(--gold-hi)}
.pr-cards{display:flex;gap:4px;align-items:flex-end}
.pr-name{font:italic 11px "IM Fell English",Georgia,serif;color:var(--ash)}
.pr-pot{text-align:center;font:700 10px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold);
padding:3px 0;margin:2px 0;border-top:1px solid #3d2a4d;border-bottom:1px solid #3d2a4d}
.pr-c{position:relative;display:inline-block;transition:transform .12s ease}
.pr-c.pickable{cursor:pointer}
.pr-c.pickable:hover,.pr-c.pickable:focus-visible{transform:translateY(-3px);outline:none}
.pr-c.picked{transform:translateY(-6px)}
.pr-c.picked .pc{box-shadow:0 0 0 1px #000,0 0 0 2px var(--blood),0 3px 8px #000;filter:brightness(.72)}
.pr-x{position:absolute;top:-5px;right:-5px;width:15px;height:15px;line-height:14px;text-align:center;
font:700 9px Georgia,serif;color:#fff;background:var(--blood);border:1px solid #000;border-radius:50%;pointer-events:none}
@media (prefers-reduced-motion:reduce){.pr-c{transition:none}}

/* ==================== v104: the Threads button joins the header (desktop only) ====================
   Until now the Threads toggle was a self-contained bubble with its own double border, gradient
   fill and drop shadow, parked in the top-right corner well away from the title -- it read as a
   second, competing piece of chrome sitting beside the window rather than as part of it. On
   desktop it now moves INTO whichever title bar is on screen and drops its box entirely: just the
   glyph, in the same gold as the words next to it, one gap away from "Gypsy Chat 2000". The move
   is a real DOM move done by placeThreadBtn() in app.js -- .in-header is the class it adds -- so
   the button simply takes its place in the header's existing centred flex row and needs no
   hand-tuned offsets to stay put when the window is resized.

   Nothing here applies below 501px. On a phone the button is still the draggable, sweepable bubble
   it has always been, still parented to .gc-root, and none of these rules can reach it. */
@media (min-width:501px){
  /* Beats the position:fixed !important block further up the file on specificity (two classes to
     its one), which is why every property it overrides has to carry !important too. */
  .thread-toggle-fab.in-header,.roulette-toggle-fab.in-header{position:static !important;top:auto !important;right:auto !important;
  left:auto !important;bottom:auto !important;transform:none !important;
  width:26px;height:auto;flex:none;justify-content:center;padding:0;
  border:none;border-radius:0;background:none;box-shadow:none;
  font-size:18px;line-height:1;color:var(--gold-hi);opacity:.92;
  filter:drop-shadow(0 0 6px rgba(201,162,74,.5));transition:transform .15s ease,filter .15s ease,opacity .15s ease}
  .thread-toggle-fab.in-header.ready,.roulette-toggle-fab.in-header.ready{display:inline-flex}
  .thread-toggle-fab.in-header:hover,.thread-toggle-fab.in-header:focus-visible,
  .roulette-toggle-fab.in-header:hover,.roulette-toggle-fab.in-header:focus-visible{
  border:none;box-shadow:none;outline:none;opacity:1;
  transform:translateY(-1px) scale(1.14) !important;filter:drop-shadow(0 0 11px rgba(201,162,74,.95))}
  /* .open (threads showing, so the glyph is 💬 "back to chat") lost its meaning once the border it
     used to recolour is gone -- brightness is what marks it as the active state now. */
  .thread-toggle-fab.in-header.open,.roulette-toggle-fab.in-header.open{opacity:1;filter:drop-shadow(0 0 10px rgba(201,162,74,.9))}
  /* The title is flanked by a lantern on each side, so a glyph hung off one end pulls the whole
     centred row off-balance and the name stops being in the middle of its own bar. A blank flex
     item of the button's own width on the opposite side puts it back. Which side needs the blank
     depends on which buttons are in the bar, and markHeaderBtns() in app.js says so directly:
     .hb-left means Roulette is in (before the first lantern), .hb-right means Threads is in
     (after the last one). One of them alone gets a spacer opposite it; both together already
     balance each other and get none, which is the ordinary signed-in case. */
  .win > .title.hb-right:not(.hb-left)::before{content:"";flex:none;width:26px}
  .win > .title.hb-left:not(.hb-right)::after{content:"";flex:none;width:26px}
  .gc-root.signed-on .tp-list > .tp-hd::before{content:"";flex:none;width:22px}
  /* An open thread's header already carries the ← back arrow on the left, so the toggle on the
     right balances it on its own and wants no spacer. */
  .tp-hd .thread-toggle-fab.in-header{font-size:15px;width:22px}
}
@media (prefers-reduced-motion:reduce){.thread-toggle-fab.in-header,.roulette-toggle-fab.in-header{transition:none}}

/* ==================== v105: the roulette watermark stops being an overlay ====================
   .room-watermark (the roulette teaser's "made by" line -- the main room's footer is .room-footer,
   a different thing) was an absolute overlay pinned to the panel's bottom-right corner. In the
   1340px-and-wider gutter presentation that is still exactly right: the panel is a tall, narrow
   column with empty space below the wheel, nothing else is down there, and the Messages dock sits
   on the far side of the screen. So that case is left alone.

   The full-screen takeover below 1340px is where it broke, and it broke the same way twice. The
   panel goes inset:0, so "the panel's bottom-right corner" becomes the VIEWPORT's bottom-right
   corner -- which is precisely where the collapsed Messages pill lives. On a desktop window the
   pill covered the line outright; on a phone the two sat on top of each other. Corner-pinning any
   two things to the same corner from two different stacking contexts was never going to hold.

   So in the takeover it stops floating and becomes what it looks like it should have been all
   along: the last item in the panel's own centred column, directly under "Back to chat". The
   panel is already a centred flex column, so position:static is the whole fix -- the line lands
   under the button, moves with it, and cannot collide with anything pinned to a screen corner. */
@media (max-width:1339px){
  .gc-root.mobile-roulette-open .room-watermark{position:static;right:auto;bottom:auto;
  flex:none;margin-top:12px;text-align:center}
}

/* The other half of the same collision, on phones. The collapsed Messages pill sits at
   bottom:142px there, and the comment where that number is set says why: it is clearing the
   composer and the folded roster bar underneath it. Neither of those exists on the roulette page
   -- it is a full-screen takeover with nothing at its bottom edge at all -- so on that page the
   pill was floating 142px up for no reason, straight across the centred column it now shares with
   the watermark. Dropping it to the bottom corner on this one page clears the line and puts the
   pill somewhere that actually makes sense there. Deliberately not applied to the other takeovers:
   the threads board has a reply box along its bottom edge that the pill would land on top of.
   :not(.moved) leaves a pill the reader has dragged somewhere exactly where they put it. */
@media (max-width:500px){
  .gc-root.mobile-roulette-open .dm-dock.collapsed:not(.moved){bottom:6px}
  /* A little air under the centred column as well. On a 640px-tall phone with the longest
     fortune showing, the watermark's last line and the pill's top edge ended up one pixel
     apart -- technically clear, but one pixel is not a margin, it is a coincidence waiting to
     break the next time a fortune gets a word longer. The panel is centred, so padding at the
     bottom lifts the whole column by half of it. */
  .gc-root.mobile-roulette-open .roulette-panel{padding-bottom:40px}
}

/* iPhone: stop the reaction picker's emoji from being treated as selectable text.
   The picker is opened by a press-and-hold, and press-and-hold is also exactly the gesture iOS
   Safari uses to start a text selection and raise its callout bar. So the same finger that opened
   the picker would carry straight on into selecting the emoji underneath it: the character came up
   highlighted in blue, the selection handles appeared, and the tap that should have posted the
   reaction went to dismissing all that instead. touch-callout and user-select refuse the selection,
   tap-highlight-color removes the grey flash iOS paints over the button on touch, and
   touch-action:manipulation drops the 300 ms double-tap-to-zoom wait so a tap registers at once.
   The buttons carry real text (the emoji), so this has to be set on them, not just on the panel. */
.rpicker,.rpicker button{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;
-webkit-tap-highlight-color:transparent;touch-action:manipulation}

/* v107: the other half of the iPhone reaction problem. Stopping the PICKER from being selectable
   (v106, just above) was not enough, because the selection does not start on the picker -- it
   starts on the message you are pressing, before the picker even exists. Press and hold is how you
   react here, and it is also exactly how iOS Safari begins a text selection, so a hold on a message
   would raise the picker and select the message's text and the sender's name underneath it at the
   same time: blue highlight, selection handles, callout bar, all of it on top of the thing you were
   trying to react to.

   Touch devices only. On a desktop this never happens -- a selection there needs a drag, and a drag
   of more than ten pixels cancels the long press before it fires (see LONG_PRESS_SLOP in app.js) --
   and turning selection off with a mouse present would take away the ordinary ability to highlight
   and copy what somebody said. On a phone that ability was already gone, since the hold that would
   start a selection is spoken for. user-select inherits, so setting it on the row covers the name,
   the body text and the timestamp without naming them. Links keep their own callout, so a long
   press on a URL still offers Open and Copy Link rather than doing nothing. */
@media (hover:none) and (pointer:coarse){
  .log .m[data-mid],.tp-posts .tp-post{-webkit-touch-callout:none;-webkit-user-select:none;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}
  .log .m[data-mid] a,.tp-posts .tp-post a{-webkit-touch-callout:default;-webkit-user-select:auto;user-select:auto}
}

/* ==================== v108: boards, tags and the follow button ====================
   Two rows above the catalog. The board row wraps -- ten boards will not fit on one line at any
   width worth designing for, and a horizontal scroller hides the boards at the end from anyone who
   does not think to swipe. Wrapping shows all ten at once, which is the point of having them. */
.tp-boards{display:flex;flex-wrap:wrap;gap:4px;padding:6px 10px 0;flex:none}
.tp-board{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash);cursor:pointer;
background:linear-gradient(180deg,#1d150d,#0d0806);border:1px solid #3a3026;border-radius:3px;
padding:4px 8px;white-space:nowrap;transition:color .15s ease,border-color .15s ease}
.tp-board:hover,.tp-board:focus-visible{color:var(--gold-hi);border-color:var(--gold-lo);outline:none}
.tp-board.active{color:var(--gold);border-color:var(--gold);background:linear-gradient(180deg,#362b1f,#150f08);
box-shadow:inset 0 0 8px rgba(201,162,74,.25)}

/* Tag chips and the follow button share a row: the button belongs to whichever board is showing,
   and this is the row with space left on it. */
.tp-tagrow{display:flex;align-items:center;gap:8px;padding:6px 10px;flex:none;flex-wrap:wrap}
.tp-tags{display:flex;flex-wrap:wrap;gap:3px;flex:1 1 auto;min-width:0}
.tp-tag{font:italic 11px "IM Fell English",Georgia,serif;color:var(--ash);cursor:pointer;
background:none;border:1px solid transparent;border-radius:999px;padding:2px 9px;white-space:nowrap}
.tp-tag:hover,.tp-tag:focus-visible{color:var(--gold-hi);border-color:#3a3026;outline:none}
.tp-tag.active{color:var(--gold);border-color:var(--gold-lo);background:rgba(201,162,74,.1)}
/* build 282: the chips were 40x18 on a touch device, under WCAG 2.5.8 (AA)'s 24x24 -- on the debt
   list since the build 281 sweep. 2px of padding becomes 5px and the chip measures 24 exactly.
   Six pixels, one rule, and it clears the entry in BOTH places .tp-tag is used: the thread-board
   tag strip and the People sort/region rows.

   WHY NOT THE INVISIBLE ::after THAT FIXED THE WHISPER BUTTON IN 280. Because it cannot work here,
   measured rather than assumed. At <=500px `.tp-tags` is `flex-wrap:nowrap; overflow-x:auto`
   (line ~3415) -- a sideways-scrolling strip, not a wrapping row -- so a pseudo-element hanging
   below the chip is clipped by the scroll container and measures 18, not 24. Adding
   `overflow-y:visible` does not rescue it either: overflow-y computes back to `auto` on its own,
   because the spec does not allow one axis to be visible while the other is auto. Nothing can
   overhang a horizontally scrolling strip. Growing the chip is the only mechanism available. */
@media all{ .tp-tag{padding:5px 11px} }   /* build 286: unscoped from touch */

.tp-sub{flex:none;font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash);cursor:pointer;
background:linear-gradient(180deg,#1d150d,#0d0806);border:1px solid #3a3026;border-radius:999px;padding:4px 10px}
.tp-sub:hover,.tp-sub:focus-visible{color:var(--gold-hi);border-color:var(--gold-lo);outline:none}
.tp-sub.on{color:var(--gold);border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.3)}

/* The tag on a catalog tile, inline at the head of the meta line. It was pinned to the tile's
   top-right corner first, which put it straight on top of the poster's name and truncated it --
   the one thing a tile has to get across is who posted, so a label covering that is the wrong
   trade. Inline it cannot collide with anything and it is read in the same glance as the reply
   count. */
.tp-chip{display:inline-block;font:700 8px Cinzel,Georgia,serif;letter-spacing:.5px;
text-transform:uppercase;color:var(--gold);border:1px solid var(--gold-lo);
border-radius:999px;padding:0 5px;margin-right:2px;vertical-align:1px}

/* Board and tag on the posting form, above the textarea: you should choose where a post is going
   before you write it, not after. */
.tp-newmeta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.tp-newlbl{font:700 9px Cinzel,Georgia,serif;letter-spacing:1.5px;text-transform:uppercase;color:var(--ash)}
.tp-sel{font:inherit;font-size:12px;color:var(--bone);background:#050200;border:1px solid #3a3026;
border-radius:3px;padding:3px 6px;cursor:pointer;max-width:46%}
.tp-sel:focus-visible{border-color:var(--gold);outline:none}

@media (max-width:500px){
  .tp-boards{padding:5px 8px 0;gap:3px}
  .tp-board{font-size:9px;padding:4px 7px}
  .tp-tagrow{padding:5px 8px;gap:6px}
  .tp-sel{font-size:16px}  /* iOS zooms any field under 16px on focus; see the phone overhaul notes */
}

/* ==================== v109: replies ====================
   The quoted stub above a reply. Indented and hung off a left rule so the eye reads it as
   belonging to the message below it rather than as a message of its own -- the same shape Discord
   and Instagram settled on, for the same reason: a quote that looks like a post doubles the
   apparent traffic in the room. Small, dim, one line, clipped: it is a pointer, not a copy, and
   anyone who wants the whole thing taps it and is taken there. */
/* build 389: width is 100% less the left margin; plain 100% ran 14px past the line and the room log scrolled sideways */
.rq{display:block;width:calc(100% - 14px);text-align:left;font:italic 11px "IM Fell English",Georgia,serif;
color:var(--ash);background:none;border:none;border-left:2px solid var(--gold-lo);
padding:0 0 0 7px;margin:2px 0 1px 14px;cursor:pointer;
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;opacity:.75}
.rq:hover,.rq:focus-visible{color:var(--gold-hi);border-left-color:var(--gold);opacity:1;outline:none}
.rq b{font-style:normal;color:var(--gold);font-weight:700}
.rq-gone{opacity:.6}
/* The message you were taken to, marked just long enough to find it. A colour wash rather than a
   scroll-and-hope: on a busy log, landing near the right place is not the same as being shown
   which line it was. */
@keyframes rq-flash{0%{background:rgba(201,162,74,.34)}100%{background:transparent}}
.rq-flash{animation:rq-flash 1.6s ease-out 1}
@media (prefers-reduced-motion:reduce){.rq-flash{animation:none;outline:2px solid var(--gold);outline-offset:1px}}

/* The bar above the composer saying what you are about to answer. */
.reply-bar{display:flex;align-items:center;gap:7px;padding:4px 10px;flex:none;
background:linear-gradient(180deg,#1d150d,#100a06);border-top:1px solid var(--gold-lo);
font-size:11px;color:var(--ash);min-width:0}
.reply-bar.hidden{display:none}
.rb-icon{color:var(--gold);flex:none}
.rb-txt{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rb-txt b{color:var(--gold);font-weight:700}
.rb-x{flex:none;font:700 12px Georgia,serif;color:var(--ash);background:none;border:none;
cursor:pointer;padding:0 3px;line-height:1}
.rb-x:hover,.rb-x:focus-visible{color:var(--blood);outline:none}

/* Reply inside the long-press picker. The picker is a 4-wide grid of emoji; this spans the whole
   width above them and is deliberately not round or emoji-shaped, so it does not read as a tenth
   reaction sitting among the nine. */
.rpicker .rp-reply{grid-column:1 / -1;width:auto;height:26px;font:700 10px Cinzel,Georgia,serif;
letter-spacing:1px;color:var(--gold);background:linear-gradient(180deg,#281f15,#110c07);
border:1px solid var(--gold-lo);border-radius:3px;margin-bottom:2px}
.rpicker .rp-reply:hover,.rpicker .rp-reply:focus-visible{color:var(--gold-hi);border-color:var(--gold);
box-shadow:0 0 8px rgba(201,162,74,.5);outline:none}
@media (max-width:500px){.rq{font-size:12px;margin-left:10px;width:calc(100% - 10px)}.reply-bar{font-size:12px}}

/* ==================== v110: the reading at each hour ====================
   Parchment, not the room's dark stone. Red type on a near-black background is genuinely hard to
   read -- the contrast ratio is poor at every shade of red worth calling red -- and the request
   was for a well-contrasting highlight, so the panel inverts instead of tinting. It also happens
   to be what a red-letter Bible actually looks like, which is the right association for the thing
   it is. Eight times a day is rare enough that a bright panel reads as an event rather than
   noise. */
.m.scripture{display:block;margin:10px 4px;padding:9px 12px 7px;
background:linear-gradient(180deg,#f3e7cd,#e6d6b4);color:#2a2118;
border:2px double #8a6b32;outline:1px solid #000;border-radius:3px;
box-shadow:0 0 0 1px #000,0 3px 12px #000,inset 0 0 24px rgba(138,107,50,.18)}
.m.scripture .sc-hd{font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;
color:#6b4a18;margin-bottom:5px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.sc-bell{font-size:12px}
/* The hour's own commemoration, in the header but stepped back from the hour's name: it is the
   reason this passage and not another, so it belongs on screen, but it is a gloss, not a title. */
.sc-theme{font:italic 10px "IM Fell English",Georgia,serif;letter-spacing:.5px;text-transform:none;
color:#7d6236;opacity:.9}
.m.scripture .sc-body{font:15px/1.62 "IM Fell English",Georgia,serif;color:#2a2118}
/* The words of Christ. Deep red on parchment, the way a red-letter edition sets them -- and only
   these: the evangelist's "Then Jesus said" stays black, because it is not Him speaking. */
.sc-red{color:#9c1c14}
.m.scripture .sc-ref{margin-top:6px;font:700 9px Cinzel,Georgia,serif;letter-spacing:1.5px;
color:#6b4a18;text-align:right;opacity:.85}
@media (max-width:500px){
  .m.scripture{margin:8px 2px;padding:8px 10px 6px}
  .m.scripture .sc-body{font-size:15px;line-height:1.6}
}
/* The NKJV permission notice. Required to appear wherever the text is quoted, so it lives in the
   ⋯ menu under the version number rather than in the room, where it would be chrome competing
   with the readings themselves. */
.popover-nkjv{padding:4px 10px 8px;font:9px Georgia,serif;line-height:1.45;color:var(--ash);
opacity:.6;max-width:260px}

/* ==================== v111: voice notes ====================
   The recording bar sits where the reply bar does, above the composer, and only exists while a
   recording is running. Deep red rather than the room's gold: recording is a state you must never
   be in without knowing it, and gold would read as ordinary chrome. */
.vn-bar{display:flex;align-items:center;gap:8px;padding:5px 10px;flex:none;
background:linear-gradient(180deg,#240d0a,#110503);border-top:1px solid var(--blood);
font-size:11px;color:#e8c8c4}
.vn-bar.hidden{display:none}
.vn-dot{width:9px;height:9px;flex:none;border-radius:50%;background:var(--blood);
box-shadow:0 0 7px rgba(155,27,27,.9);animation:vn-pulse 1.1s ease-in-out infinite}
@keyframes vn-pulse{0%,100%{opacity:1}50%{opacity:.25}}
@media (prefers-reduced-motion:reduce){.vn-dot{animation:none}}
.vn-time{font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:#fff;min-width:34px}
.vn-hint{flex:1 1 auto;font-style:italic;opacity:.75;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vn-cancel,.vn-send{flex:none;font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;cursor:pointer;
background:none;border:1px solid #6b2a26;border-radius:3px;color:#e8c8c4;padding:3px 8px}
.vn-cancel:hover,.vn-cancel:focus-visible{color:#fff;border-color:var(--blood);outline:none}
.vn-send{border-color:var(--gold-lo);color:var(--gold)}
.vn-send:hover,.vn-send:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
/* The mic while armed: the button itself becomes the stop control, so there is never a moment
   where the thing that started the recording is not also the thing that ends it. */
.icomp .mic.on{color:#fff;border-color:var(--blood);background:linear-gradient(180deg,#4a1a18,#240503);
box-shadow:0 0 8px rgba(155,27,27,.7)}

/* A sent voice note. A pill, not a full audio element: the browser's default player is 300px of
   grey chrome that would look like a foreign object in here, and all it needs to offer is play,
   pause and how long it runs. */
.vn{display:inline-flex;align-items:center;gap:7px;vertical-align:middle;
padding:3px 10px 3px 4px;border:1px solid #7a4bb0;border-radius:999px;
background:linear-gradient(180deg,#1d1124,#0d0510)}
.vn-play{width:22px;height:22px;flex:none;padding:0;cursor:pointer;font-size:10px;line-height:1;
color:#e2c4ff;background:#3a2550;border:1px solid #7a4bb0;border-radius:50%}
.vn-play:hover,.vn-play:focus-visible{color:#fff;border-color:#b98cff;box-shadow:0 0 7px rgba(150,90,220,.6);outline:none}
.vn-play:disabled{opacity:.5;cursor:default}
.vn-len{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:#c6a6e8}
.vn-gone{font-style:italic;font-size:10px;color:var(--ash);opacity:.7}
.vn audio{display:none} /* playback is driven entirely by the pill's own button */
@media (max-width:500px){.vn-bar{font-size:12px}.vn-play{width:26px;height:26px}}

/* ==================== v112: shared threads and people ====================
   A share is a card, not a link: a bare URL in a whisper tells you nothing about what is on the
   other end, and the whole point of passing something on is that the person can see what it is
   before deciding to open it. */
.sh{display:flex;align-items:stretch;gap:8px;width:100%;max-width:300px;text-align:left;cursor:pointer;
margin:3px 0;padding:6px;background:linear-gradient(180deg,#1d1124,#0d0510);
border:1px solid #7a4bb0;border-radius:8px;color:inherit;font:inherit}
.sh:hover,.sh:focus-visible{border-color:#b98cff;box-shadow:0 0 9px rgba(150,90,220,.45);outline:none}
.sh-body{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto}
.sh-kind{font:700 8px Cinzel,Georgia,serif;letter-spacing:1.5px;text-transform:uppercase;color:#a983d8}
.sh-op{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold);
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sh-op.admin{color:var(--admin)}
.sh-txt{font:italic 11px "IM Fell English",Georgia,serif;color:var(--bone);opacity:.85;
display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.sh-meta{font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash)}
.sh-thumb{width:44px;height:44px;flex:none;object-fit:cover;border:1px solid #3a3026;border-radius:4px}
.sh-load{font-style:italic;color:var(--ash);opacity:.7;padding:4px}
/* A share whose target is gone is a plain line, not a button: there is nothing to open. */
.sh-gone{display:inline-block;cursor:default;font-style:italic;font-size:11px;color:var(--ash);
opacity:.75;border:none;background:none;padding:2px 0;max-width:none}
.sh-user .ava-menu{width:40px;height:40px;flex:none}
/* Waiting on the lookup, not missing. Styled like the card it is about to become rather than like
   the "gone" line, so a card that resolves in 200ms does not flash an error first. */
.sh-pending{display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;
border:1px solid #4a3560;border-radius:8px;background:linear-gradient(180deg,#180f21,#0a030f);cursor:default}

/* Share button in an open thread's header. */
.tp-share{font:700 13px Cinzel,Georgia,serif;color:var(--gold);background:none;
border:1px solid var(--gold-lo);width:24px;height:22px;line-height:18px;cursor:pointer;padding:0;flex:none}
.tp-share:hover,.tp-share:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}

/* Who to send it to. Friends first, because sharing is nearly always with somebody you already
   talk to, and a list that opens on people you know beats one sorted by who happens to be on. */
.pick-modal{width:min(320px,92vw)}
.pick-list{max-height:min(46vh,320px);overflow:auto;margin:6px 0;display:flex;flex-direction:column;gap:2px}
.pick-row{display:flex;align-items:center;gap:8px;width:100%;text-align:left;cursor:pointer;
padding:5px 7px;background:none;border:1px solid transparent;border-radius:4px;color:var(--bone);font:inherit}
.pick-row:hover,.pick-row:focus-visible{border-color:var(--gold-lo);background:rgba(201,162,74,.08);outline:none}
.pick-nm{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold)}
.pick-nm.admin{color:var(--admin)}
.pick-tag{flex:none;font:700 8px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;
color:var(--ash);border:1px solid #3a3026;border-radius:999px;padding:1px 5px}
.pick-dot{width:7px;height:7px;flex:none;border-radius:50%;background:#4caf50;box-shadow:0 0 5px rgba(76,175,80,.8)}
.pick-empty{padding:16px 8px;text-align:center;font-style:italic;font-size:12px;color:var(--ash)}
.pick-cancel{width:100%}
@media (max-width:500px){.sh{max-width:100%}.pick-row{padding:8px 7px}}

/* ---------- v114: group chats ----------
   The multi-select picker is the single-select one with a tick and a Done button: same rows, same
   avatars, same friend tag, so choosing four people looks like choosing one, four times. */
.pick-actions{display:flex;gap:6px}
.pick-actions .btn{flex:1 1 0}
.pick-actions .pick-cancel{width:auto}
.pick-check{flex:none;width:16px;text-align:center;font-size:12px;color:var(--gold);opacity:0;transition:opacity .12s ease}
.pick-row.picked{border-color:var(--gold);background:rgba(201,162,74,.14)}
.pick-row.picked .pick-check{opacity:1}
.pick-done:disabled{opacity:.45;cursor:default}
/* A group has no avatar of its own; the two-figure glyph stands in for one, at the same size so
   the inbox rows stay on the same grid as the whispers above and below them. */
.im-group .wava,.im-tab .tava{line-height:1}
.im-group .bar .gmembers{font-size:14px}
/* A group's composer has no games or mic button yet -- they are hidden, not removed, because the
   rest of ensureWin wires them up by selector and a missing node throws. display:none takes them
   out of the grid, but the named-area template still reserves their columns, so the group case
   gets its own template rather than two empty gaps beside the emoji button. */
.im.im-group .icomp{grid-template-columns:auto auto 1fr auto}
@media (min-width:501px){
  .im.im-group .icomp{grid-template-columns:auto auto 1fr;grid-template-areas:"ta ta send" "emo media ."}
}
@media (max-width:500px){
  .im.im-group .icomp{grid-template-columns:auto 1fr auto}
}

/* ---------- v116: Battleship (build 167) ----------
   Two grids in one whisper card: the enemy's waters full width (tap a square to fire when the
   frame glows gold) and your own fleet as a small chart beside the ships-left rows. Cells are
   plain divs in a 10x10 CSS grid, square by aspect-ratio. A ship is drawn from its cells: a
   rounded hull whose inner ends go flat and reach 1px into the gap, so it reads as one piece. */
.bs-card{margin:8px 4px;padding:8px 10px;border:1px solid #7a4bb0;background:linear-gradient(180deg,#1a111f,#0d0510);box-shadow:0 0 0 1px #000,inset 0 0 18px #000}
.bs-label{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap;font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:#9fb6c9;text-transform:uppercase;margin:2px 0 4px;text-shadow:0 1px 0 #000}
.bs-grid{display:grid;grid-template-columns:repeat(10,1fr);grid-template-rows:repeat(10,1fr);gap:1px;width:100%;max-width:min(340px,100%);aspect-ratio:1;margin:0 auto 6px;padding:1px;
  background:#122534;border:1px solid #3b5569;border-radius:4px;box-shadow:inset 0 0 12px #000,0 0 0 1px #000;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.bs-cell{position:relative;background:#000d18;min-width:0;min-height:0}
.bs-cell.bs-sh{background:linear-gradient(180deg,#8994a0,#5d6773);border-radius:40%}
.bs-cell.bs-sh.bs-l{border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-1px}
.bs-cell.bs-sh.bs-r{border-top-right-radius:0;border-bottom-right-radius:0}
.bs-cell.bs-sh.bs-u{border-top-left-radius:0;border-top-right-radius:0;margin-top:-1px}
.bs-cell.bs-sh.bs-d{border-bottom-left-radius:0;border-bottom-right-radius:0}
.bs-cell.bs-sh.bs-sunk{background:linear-gradient(180deg,#6b2019,#390500)}
.bs-cell.bs-sh.bs-ghost{background:rgba(137,148,160,.3)}
.bs-cell.bs-hit::after{content:'';position:absolute;inset:16%;border-radius:50%;background:radial-gradient(circle,#ffe39a 0,#f07a2c 45%,#b3261e 72%,transparent 74%);box-shadow:0 0 6px rgba(240,122,44,.75)}
.bs-cell.bs-hit.bs-sunk::after{inset:28%;background:radial-gradient(circle,#ff9a7a 0,#b3261e 62%,transparent 64%);box-shadow:none;opacity:.85}
.bs-cell.bs-miss::after{content:'';position:absolute;inset:36%;border-radius:50%;background:#7f99b0;opacity:.8}
.bs-cell.bs-last{box-shadow:inset 0 0 0 2px var(--gold-hi);z-index:1}
.bs-enemy.bs-myturn{border-color:var(--gold);box-shadow:inset 0 0 12px #000,0 0 0 1px #000,0 0 10px rgba(201,162,74,.45)}
.bs-cell.bs-open{cursor:crosshair}
@media (hover:hover){.bs-cell.bs-open:hover{background:#18364d;box-shadow:inset 0 0 0 1px var(--gold)}}
.bs-cell.bs-aim{background:#241500;animation:bs-aim .45s ease-in-out infinite alternate}
@keyframes bs-aim{from{box-shadow:inset 0 0 0 1px var(--gold)}to{box-shadow:inset 0 0 0 3px var(--gold-hi)}}
.bs-place{touch-action:none;cursor:grab}
.bs-place .bs-cell.bs-from{opacity:.3}
.bs-place .bs-cell.bs-pv{background:linear-gradient(180deg,#9cc79c,#4f7a4f);border-radius:3px;margin:0}
.bs-place .bs-cell.bs-pv.bs-bad{background:linear-gradient(180deg,#d4786b,#7a1f17)}
.bs-place.bs-nope{animation:bs-nope .3s}
@keyframes bs-nope{25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
.bs-tools{display:flex;justify-content:center;gap:6px;margin:0 0 6px}
.bs-tools .btn{min-width:0;height:26px;padding:0 12px;font-size:11px;color:#e2c4ff;border-color:#7a4bb0;background:linear-gradient(180deg,#3a2a48,#110918)}
.bs-tools .btn.bs-ready{color:#cdeecd;border-color:var(--leaf)}
.bs-sub{display:flex;gap:10px;align-items:flex-start;margin:0 0 4px}
.bs-sub .bs-mini{flex:none;width:34%;max-width:120px;min-width:84px;margin:0}
.bs-side{flex:1;min-width:0}
.bs-side .uno-last{text-align:left;margin:4px 0 0}
.bs-hulls{display:inline-flex;flex-wrap:wrap;gap:4px;align-items:center}
.bs-hull{position:relative;display:inline-flex;gap:1px}
.bs-hull i{display:block;width:5px;height:6px;background:#8994a0;border-radius:1px}
.bs-hull.bs-sunk i{background:#6b2019}
.bs-hull.bs-sunk::after{content:'';position:absolute;left:-1px;right:-1px;top:50%;height:1px;background:#e0402f}
.ttt-actions .btn.bs-resign,.ttt-actions .btn.bs-decline,.ttt-actions .btn.bs-cancel{color:var(--ash);border-color:#3d2a4d}
.ttt-actions .btn.bs-accept{color:#cdeecd;border-color:var(--leaf)}
.ttt-actions .btn.bs-resign.armed{color:#fff;border-color:var(--blood);background:linear-gradient(180deg,#b3261e,#5a120e)}
@media (hover:none) and (pointer:coarse){.bs-tools .btn{height:34px}}
@media (prefers-reduced-motion:reduce){.bs-cell.bs-aim,.bs-place.bs-nope{animation:none}}
@media (max-width:500px){.lb-tabs .adm-tab{flex-basis:22%}} /* seven game tabs: four on the first row, three on the second */

/* ==================== v118 (build 169): the Game Room ====================
   Tables for up to four players and four watchers (renderGameRoom in app.js). The page is the same
   .gc-root.<state>-open takeover as the Popularity Contest. Its button lives in the title bar on a
   desktop (placeGameRoomBtn moves it there, beside Roulette) and floats as a bubble on a phone,
   above the Roulette and Threads bubbles. */
.gameroom-toggle-fab{display:none;position:fixed;right:12px;top:50%;bottom:auto;transform:translateY(calc(-50% - 81px));z-index:55;
width:46px;height:46px;padding:0;align-items:center;justify-content:center;font-size:21px;line-height:1;cursor:pointer;color:var(--gold-hi);
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);border-radius:10px;
box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35);touch-action:none;transition:left .22s ease,top .22s ease,opacity .18s ease}
.gameroom-toggle-fab.ready{display:flex}
.gameroom-toggle-fab:hover,.gameroom-toggle-fab:focus-visible{border-color:var(--gold);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 16px rgba(201,162,74,.7);outline:none}
.gameroom-toggle-fab.fab-dragging{transition:none;box-shadow:0 0 0 1px #000,0 6px 20px #000,0 0 20px rgba(201,162,74,.9)}
.gameroom-toggle-fab.fab-docked{opacity:.5}
.gameroom-toggle-fab.fab-docked:hover,.gameroom-toggle-fab.fab-docked:focus-visible{opacity:1}
/* something is waiting in there: an invite, your turn, or table chat you haven't seen */
.gameroom-toggle-fab.news::after{content:"";position:absolute;top:3px;right:3px;width:10px;height:10px;border-radius:50%;background:var(--blood);
box-shadow:0 0 0 1px #000,0 0 8px rgba(179,38,30,.9);pointer-events:none}
@media (max-width:500px){.gameroom-toggle-fab{right:8px}}
@media (min-width:501px){
  .gameroom-toggle-fab.in-header{position:relative !important;top:auto !important;right:auto !important;left:auto !important;bottom:auto !important;
  transform:none !important;width:26px;height:auto;flex:none;justify-content:center;padding:0;border:none;border-radius:0;background:none;box-shadow:none;
  font-size:18px;line-height:1;opacity:.92;filter:drop-shadow(0 0 6px rgba(201,162,74,.5));transition:transform .15s ease,filter .15s ease,opacity .15s ease}
  .gameroom-toggle-fab.in-header.ready{display:inline-flex}
  .gameroom-toggle-fab.in-header:hover,.gameroom-toggle-fab.in-header:focus-visible{border:none;box-shadow:none;outline:none;opacity:1;
  transform:translateY(-1px) scale(1.14) !important;filter:drop-shadow(0 0 11px rgba(201,162,74,.95))}
  .gameroom-toggle-fab.in-header.news::after{top:-3px;right:-1px;width:8px;height:8px}
  /* The title's balance with three glyphs: Roulette and the Game Room on the left of the name, Threads
     on its right, so the right side gets one glyph's width of blank (see markHeaderBtns). */
  .win > .title.hb-gr.hb-left.hb-right::after{content:"";flex:none;width:26px}
  .win > .title.hb-gr.hb-left:not(.hb-right)::after{content:"";flex:none;width:52px}
  .win > .title.hb-gr.hb-right:not(.hb-left)::before{content:none}
}
@media (prefers-reduced-motion:reduce){.gameroom-toggle-fab,.gameroom-toggle-fab.in-header{transition:none}}

.gameroom-panel{display:none;flex-direction:column;background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8}
.gc-root.gameroom-open .win{display:none}
.gc-root.gameroom-open .gameroom-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;height:100%;border-width:0;border-radius:0;z-index:40}
.gc-root.gameroom-open .thread-toggle-fab,.gc-root.gameroom-open .roulette-toggle-fab,.gc-root.gameroom-open .gameroom-toggle-fab,
.gc-root.leaderboard-open .gameroom-toggle-fab,.gc-root.admin-open .gameroom-toggle-fab{display:none !important}
@media (max-width:500px){.gc-root.dm-open .gameroom-toggle-fab{display:none !important}}
html.ios .gc-root.gameroom-open .gameroom-panel{padding-top:env(safe-area-inset-top);box-sizing:border-box}
.gr-body{flex:1;min-height:0;overflow-y:auto;width:100%;max-width:1000px;margin:0 auto;padding:12px 14px 18px;box-sizing:border-box;scrollbar-color:var(--gold-lo) #0f0d0b}
.gr-note{margin:0 0 10px;padding:7px 10px;border:1px solid var(--gold-lo);background:rgba(201,162,74,.08);color:var(--gold-hi);font-size:13px;text-align:center}

/* the list */
.gr-open{border:1px solid var(--gold-lo);background:rgba(0,0,0,.25);padding:10px 12px 12px;margin-bottom:16px}
.gr-open-hd,.gr-list-hd{font:700 12px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold);text-transform:uppercase;margin:0 0 8px}
.gr-open-row{display:flex;gap:10px;flex-wrap:wrap}
.gr-newtable{flex:1 1 180px;display:grid;grid-template-columns:auto 1fr;column-gap:10px;align-items:center;text-align:left;padding:10px 12px;cursor:pointer;
color:var(--bone);font:13px "IM Fell English",Georgia,serif;background:radial-gradient(ellipse at 30% 30%,#24553a,#072b15 75%);border:1px solid #6e5323;
border-radius:8px;box-shadow:0 0 0 1px #000,inset 0 0 16px rgba(0,0,0,.8)}
.gr-newtable .gr-nt-i{grid-row:1 / span 2;font-size:28px;line-height:1}
.gr-newtable .gr-nt-n{font:700 14px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi)}
.gr-newtable .gr-nt-s{font-size:12px;color:#b9c8b4}
.gr-newtable:hover,.gr-newtable:focus-visible{border-color:var(--gold-hi);box-shadow:0 0 0 1px #000,inset 0 0 16px rgba(0,0,0,.8),0 0 14px rgba(241,217,138,.45);outline:none}
.gr-newtable[disabled]{cursor:default;opacity:.45;filter:saturate(.3);box-shadow:0 0 0 1px #000}
.gr-row{border:1px solid var(--gold-lo);background:rgba(0,0,0,.25);padding:8px 10px;margin-bottom:8px}
.gr-row.invited{border-color:var(--gold-hi);box-shadow:0 0 12px rgba(241,217,138,.3)}
.gr-row-hd{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:4px}
.gr-row-g{font:700 13px Cinzel,Georgia,serif;color:var(--gold-hi);letter-spacing:.5px}
.gr-row-host{color:var(--bone)}
.gr-row-st{margin-left:auto;font-size:12px;color:var(--ash);font-style:italic}
.gr-row-st.live{color:#8fd08f}
.gr-row-who{font-size:13px;color:var(--bone);line-height:1.6}
.gr-row-lbl{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--ash);text-transform:uppercase;margin-right:4px}
.gr-row-who i,.gr-watch i{color:#5f5648}
.gr-btns{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end;align-items:center;margin-top:6px}
.gr-btns .btn,.gr-watch .btn,.gr-acts .btn,.gr-thd .btn,.gr-seat .btn{height:28px;min-width:0;padding:0 12px;font-size:11px}
.gr-btns .btn.gr-close{color:#e07a7a;border-color:#7a2a2a}
.gr-full{font-size:12px;color:var(--ash);font-style:italic}
.gr-empty{padding:18px 8px;text-align:center;color:#5f5648;font-style:italic}
.gr-invites{margin-bottom:12px}
.gr-invite{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:space-between;padding:8px 10px;margin-bottom:6px;border:1px solid var(--gold);
background:rgba(201,162,74,.1);color:var(--bone)}
.gr-invite b{color:var(--gold-hi)}
.gr-invite .gr-btns{margin-top:0}

/* a table */
.gr-table{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
@media (min-width:900px){.gr-table{grid-template-columns:minmax(0,1fr) 300px;align-items:start}}
.gr-thd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.gr-thd-t{flex:1;min-width:0;font:700 14px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold-hi)}
.gr-thd-r{color:var(--ash);font-weight:400}
.gr-thd .gr-btns{margin-top:0}
.gr-thd .btn.gr-leave.armed{color:#fff;border-color:var(--blood);background:linear-gradient(180deg,#b3261e,#5a120e)}
.gr-seats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-bottom:10px}
@media (max-width:560px){.gr-seats{grid-template-columns:repeat(2,minmax(0,1fr))}}
.gr-seat{min-height:72px;min-width:0;border:1px solid var(--gold-lo);background:rgba(0,0,0,.3);padding:6px 8px;display:flex;flex-direction:column;gap:4px;border-radius:6px}
.gr-seat.me{border-color:#8a6d33;background:rgba(201,162,74,.07)}
.gr-seat.turn{border-color:var(--gold-hi);box-shadow:0 0 0 1px var(--gold-hi),0 0 14px rgba(241,217,138,.55)}
.gr-seat.done{opacity:.85}
.gr-seat.empty{border-style:dashed;align-items:center;justify-content:center;background:rgba(0,0,0,.15)}
.gr-seat-n{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:#5f5648;text-transform:uppercase}
.gr-seat-e{font-size:12px;color:#5f5648;font-style:italic}
.gr-seat-hd{display:flex;align-items:center;gap:4px;min-width:0}
.gr-seat-nm{font:700 12px Cinzel,Georgia,serif;color:var(--bone);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.gr-seat.turn .gr-seat-nm{color:var(--gold-hi)}
.gr-host{flex:none;font-size:12px}
.gr-you{flex:none;font-size:11px;color:var(--ash);font-style:italic}
.gr-seat-cards{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.gr-ct{font:700 13px Cinzel,Georgia,serif;color:var(--bone)}
.gr-seat-warn{font-size:11px;color:#ffb14a}
.gr-seat-place,.gr-seat-wait{font-size:12px;color:var(--ash)}
.gr-medal{font-size:16px}
.gr-xp{color:#8fd08f;font-weight:700}
.gr-gone{color:#c98a7a;font-style:italic}
.gr-felt{position:relative;border:2px solid #6e5323;border-radius:16px;padding:12px 12px 10px;margin-bottom:10px;
background:radial-gradient(ellipse at 50% 40%,#215638 0%,#09361c 58%,#001d0c 100%);box-shadow:0 0 0 1px #000,inset 0 0 34px #000,0 4px 14px #000}
.gr-piles{display:flex;align-items:center;justify-content:center;gap:26px;margin:2px 0 6px}
.gr-dir{font-size:28px;line-height:1;color:var(--gold-hi);text-shadow:0 0 8px rgba(241,217,138,.6)}
.gr-turn{text-align:center;font-size:14px;color:var(--bone);margin-bottom:4px}
.gr-turn b{color:var(--gold-hi)}
.gr-felt .turn-clock{margin:4px 16% 6px;border-color:#2f5b3d}
.gr-felt .turn-clock .tc-bar{background:linear-gradient(90deg,#6e5323,#e6c56a)}
.gr-felt .turn-clock .tc-num{color:#fff3cf}
.gr-felt .turn-clock.low .tc-bar{background:linear-gradient(90deg,#7a1f17,#e0402f)}
.gr-felt .uno-last{color:#c9d8c4}
.gr-felt .uno-pile{color:#c9d8c4}
.gr-wait{text-align:center;color:#c9d8c4;font-style:italic;padding:8px 0}
.gr-dealrow{display:flex;justify-content:center;padding:6px 0}
.gr-dealrow .btn.gr-deal{height:34px;padding:0 24px;font-size:13px;color:#1a1208;text-shadow:none;background:linear-gradient(180deg,#f1d98a,#a8812e);border-color:#f1d98a}
.gr-dealrow .btn.gr-deal:hover{color:#000;box-shadow:inset 0 1px 0 rgba(255,255,255,.4),0 0 0 1px #000,0 0 14px rgba(241,217,138,.7)}
.gr-rules{max-width:460px;margin:6px auto 0;text-align:center;font-size:12px;line-height:1.5;color:#9fb49c}
.gr-results{max-width:380px;margin:0 auto 8px;border:1px solid rgba(241,217,138,.35);background:rgba(0,0,0,.28);padding:6px 10px 4px;border-radius:8px}
.gr-results-hd{font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);text-transform:uppercase;text-align:center;margin-bottom:4px}
.gr-res{display:flex;align-items:center;gap:8px;padding:2px 0;font-size:13px}
.gr-res-p{flex:none;width:34px;text-align:center;color:var(--ash)}
.gr-res-n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--bone)}
.gr-res.me .gr-res-n{color:var(--gold-hi)}
.gr-res-x{flex:none;font-size:12px;color:var(--ash)}
.gr-res-x.xp{color:#8fd08f;font-weight:700}
.gr-results .uno-last{margin-top:4px}
.gr-mine{margin-bottom:10px}
.gr-mine .uno-hand{margin:0;padding:10px 6px 8px;border:1px solid var(--gold-lo);background:rgba(0,0,0,.25);border-radius:8px}
.gr-acts{display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap;margin-top:8px}
.gr-acts .btn.gr-uno{color:#fff;border-color:var(--blood);background:linear-gradient(180deg,#b3261e,#5a120e);font-weight:700;letter-spacing:1px}
.gr-acts .btn.gr-catch{color:var(--gold-hi);border-color:var(--gold)}
.gr-acts .btn.gr-nopick{color:var(--ash)}
.gr-pick{font-size:13px;color:var(--bone)}
.gr-outnote{text-align:center;color:var(--bone);font-style:italic;padding:6px 0}
.gr-watch{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;font-size:13px;color:var(--bone);padding:8px 2px 2px;border-top:1px solid rgba(110,83,35,.5)}
.gr-nm.me{color:var(--gold-hi)}
.gr-hint{font-size:12px;color:var(--ash);font-style:italic}
.gr-chat{display:flex;flex-direction:column;min-height:0;border:1px solid var(--gold-lo);background:rgba(0,0,0,.25)}
@media (min-width:900px){.gr-chat{position:sticky;top:0;height:min(640px,calc(100vh - 90px))}}
.gr-chat-hd{flex:none;font:700 11px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold);text-transform:uppercase;padding:7px 10px;border-bottom:1px solid var(--gold-lo)}
.gr-chatlog{flex:1;min-height:150px;max-height:300px;overflow-y:auto;padding:6px 10px;line-height:1.45;font-size:13px;word-wrap:break-word;scrollbar-color:var(--gold-lo) #0f0d0b}
@media (min-width:900px){.gr-chatlog{max-height:none}}
.gr-line{margin-bottom:2px}
.gr-line b.who{font-weight:normal;font-family:Cinzel,Georgia,serif;font-size:12px;letter-spacing:.5px;cursor:pointer;color:var(--them)}
.gr-line.me b.who{color:var(--me)}
.gr-line b.who.admin{color:var(--admin)}
.gr-line b.who:hover,.gr-line b.who:focus-visible{text-decoration:underline;outline:none}
.gr-line.sys{color:var(--sys);font-style:italic}
.gr-line .t{color:#5f5648;font-size:11px;margin-right:6px}
.gr-line img.gif{display:block;max-width:180px;max-height:140px;margin-top:2px}
.gr-chatform{flex:none;display:flex;gap:6px;padding:6px;border-top:1px solid var(--gold-lo)}
.gr-chatin{flex:1;min-width:0;height:32px;padding:0 8px;color:var(--bone);font:14px "IM Fell English",Georgia,serif}
.gr-chatform .btn{height:32px;min-width:0}
@media (hover:none) and (pointer:coarse){.gr-chatin{font-size:16px}.gr-btns .btn,.gr-watch .btn,.gr-acts .btn,.gr-thd .btn,.gr-seat .btn{height:34px}}
/* the announcement in the main chat */
.log .m.gr-announce{color:var(--gold-hi);font-style:normal}
.log .m.gr-announce .gr-an-who{font-family:Cinzel,Georgia,serif;font-size:12px}
.gr-announce-join{margin-left:6px;height:22px;padding:0 10px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#1a1208;cursor:pointer;
background:linear-gradient(180deg,#f1d98a,#a8812e);border:1px solid #f1d98a;border-radius:4px;box-shadow:0 0 0 1px #000}
.gr-announce-join:hover,.gr-announce-join:focus-visible{box-shadow:0 0 0 1px #000,0 0 10px rgba(241,217,138,.7);outline:none}
/* Hold'em at the tables (v170): seats with stacks, bets and cards; the board on the felt; my two
   cards and the betting buttons under it. Reuses the .pc playing cards and the .hd-* chips from the
   heads-up game in whispers. */
.gr-row-stakes{font-size:12px;color:var(--gold)}
.gr-list-hd{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}
.gr-list-hd .btn.gr-bjnew{height:24px;padding:0 10px;font-size:10px;letter-spacing:.5px;text-transform:none} /* build 383 */
@media (hover:none) and (pointer:coarse){.gr-list-hd .btn.gr-bjnew{height:32px}}
.gr-seat.hd{gap:3px}
.gr-seat.folded{opacity:.55}
.gr-seat.turn.folded{opacity:1}
.gr-seat-hd .hd-btn{margin-right:1px}
.gr-hd-line{display:flex;align-items:center;gap:5px;min-height:20px}
.gr-hd-pos{flex:none;display:inline-flex;align-items:center;height:15px;padding:0 4px;border-radius:3px;border:1px solid var(--gold-lo);color:var(--gold);font:700 9px Cinzel,Georgia,serif;letter-spacing:.5px}
.gr-hd-line .hd-bet{margin-left:auto;flex:none}
.gr-hd-cards{display:flex;align-items:center;gap:3px;flex-wrap:wrap;min-height:36px}
.gr-hd-note{font-size:11px;color:var(--ash);font-style:italic;margin-left:3px}
.gr-hd-note.won{color:#8fd08f;font-weight:700;font-style:normal}
.gr-hd-note.allin{color:#ffb14a;font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;font-style:normal}
.pc.dim{opacity:.5}
.gr-felt .hd-board{max-width:300px;margin:2px auto 8px;gap:6px;background:rgba(0,0,0,.22);border-color:rgba(241,217,138,.28)}
.gr-felt .hd-board .pc{width:42px;height:60px;font-size:18px}
.gr-felt .hd-board .pc .pc-s{font-size:16px}
.gr-felt .hd-board .pc.slot{border-color:rgba(241,217,138,.28)}
.gr-hd-pot{text-align:center;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi);margin-bottom:4px;text-shadow:0 0 6px rgba(241,217,138,.35)}
.gr-hd-result{max-width:440px;margin:0 auto 4px;text-align:center}
.gr-hd-res-t{font-size:14px;line-height:1.45;color:#fff3cf}
.gr-hd-cd{margin-top:4px;font-size:12px;font-style:italic;color:#9fb49c}
.gr-hd-me{display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap;padding:10px;border:1px solid var(--gold-lo);background:rgba(0,0,0,.25);border-radius:8px}
.gr-hd-hole{display:flex;gap:6px;flex:none}
.gr-hd-hole .pc{width:46px;height:64px;font-size:19px}
.gr-hd-hole .pc .pc-s{font-size:17px}
.gr-hd-hole.folded{opacity:.45;filter:grayscale(.6)}
.gr-hd-acts{display:flex;align-items:center;justify-content:center;gap:6px;flex-wrap:wrap;min-width:0}
.gr-hd-acts .btn{height:30px;min-width:0;padding:0 12px;font-size:11px}
.gr-hd-acts .btn.gr-hd-fold{color:var(--ash)}
.gr-hd-acts .btn.gr-hd-call{color:#cdeecd;border-color:var(--leaf)}
.gr-hd-acts .btn.gr-hd-raise-btn{color:var(--gold-hi);border-color:var(--gold)}
.gr-hd-acts .gr-hint{text-align:center}
.gr-hd-raise{display:flex;align-items:center;justify-content:center;gap:4px;flex-wrap:wrap}
.gr-hd-presets{display:flex;gap:4px}
.gr-hd-acts .gr-hd-presets .btn{height:26px;padding:0 8px;font-size:10px;color:var(--ash)}
.gr-hd-in{width:64px;height:30px;box-sizing:border-box;padding:0 6px;font:14px "IM Fell English",Georgia,serif;color:var(--bone);text-align:center;
background:linear-gradient(180deg,#050200,#110d08);border:1px solid var(--gold-lo);outline:none;-moz-appearance:textfield;appearance:textfield}
.gr-hd-in::-webkit-outer-spin-button,.gr-hd-in::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.gr-hd-in:focus{border-color:var(--gold)}
@media (max-width:560px){.gr-felt .hd-board .pc{width:36px;height:52px;font-size:16px}.gr-felt .hd-board .pc .pc-s{font-size:14px}.gr-hd-hole .pc{width:42px;height:58px}}

/* build 379: a blackjack table -- the house above a row of five; on a phone an arc (1 and 5 beside the house, 2-3-4 below) */
.gr-felt.bj{border-radius:120px 120px 22px 22px;padding:14px 12px 10px}
.gr-felt.bj::before{content:"";position:absolute;inset:8px;border-radius:112px 112px 16px 16px;border:1px dashed rgba(232,211,162,.22);pointer-events:none}
.gr-felt.bj > *{position:relative}
.bj-rule{text-align:center;font:500 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:rgba(232,211,162,.55);margin:2px 0 8px}
.bj-table{display:flex;flex-direction:column;gap:14px}
.bj-dealer{display:flex;flex-direction:column;align-items:center;gap:6px}
.bj-dl-name{font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:var(--gold-hi);display:flex;align-items:center;gap:8px}
.bj-hand{display:flex;gap:5px;justify-content:center}
.bj-tot{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:18px;padding:0 5px;border-radius:9px;background:#0e0918;border:1px solid #4d2f6b;color:#e2c4ff;font:700 10px Cinzel,Georgia,serif;flex:none}
.bj-tot.bust{border-color:#7a1f17;color:#ffb3ab;background:#2a0b08}.bj-tot.bj{border-color:var(--gold);color:var(--gold-hi);background:#2a1f0a}
.bj-tot.side{margin-left:4px}
.bj-seats{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}
.bj-seat{background:rgba(0,0,0,.35);border:1px solid rgba(232,211,162,.18);border-radius:10px;padding:8px 6px;display:flex;flex-direction:column;align-items:center;gap:6px;min-height:118px;min-width:0}
.bj-seat.me{border-color:var(--gold);box-shadow:0 0 0 1px #000,0 0 14px rgba(196,154,82,.25)}
.bj-seat.turn{border-color:var(--gold-hi);box-shadow:0 0 0 1px var(--gold-hi),0 0 14px rgba(241,217,138,.55)}
.bj-seat.gone{opacity:.6}
.bj-seat.open{justify-content:center;border-style:dashed;color:var(--ash);font:500 11px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;gap:4px}
.bj-open-s{color:var(--gold);font-size:10px}
.bj-seat .btn.bj-sitbtn{height:28px;padding:0 14px;font-size:11px}
@media (hover:none) and (pointer:coarse){.bj-seat .btn.bj-sitbtn{height:40px}button.bj-chip.big{width:42px;height:42px}}
.bj-name{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--bone);display:flex;align-items:center;gap:6px;max-width:100%;min-width:0}
.bj-name b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.bj-seat.me .bj-name b{color:var(--gold-hi)}
.bj-h{display:flex;align-items:center;justify-content:center}
.bj-h.active{outline:1px solid var(--gold-hi);outline-offset:3px;border-radius:4px}
.bj-h.done{opacity:.7}
.bj-bet{display:inline-flex;align-items:center;gap:4px;font:700 11px Cinzel,Georgia,serif;color:#fff}
.bj-dbl{color:var(--gold-hi);font-size:10px}
.bj-chip{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:radial-gradient(circle at 40% 35%,#e0402f,#7a1f17);box-shadow:0 0 0 2px #fff inset,0 0 0 1px #000;font:700 9px Cinzel,Georgia,serif;color:#fff;flex:none}
.bj-chip.g{background:radial-gradient(circle at 40% 35%,#e8d3a2,#8a6a2a);color:#1a1410}
.bj-chip.b{background:radial-gradient(circle at 40% 35%,#4d7fd6,#1b3a7a)}
.bj-chip.e{background:radial-gradient(circle at 40% 35%,#4fb06a,#1d5a2e)}
.bj-chip.k{background:radial-gradient(circle at 40% 35%,#3a3a3a,#050505);box-shadow:0 0 0 2px var(--gold-hi) inset,0 0 0 1px #000}
.bj-res{font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;text-align:center;margin-top:auto}
.bj-res.bj-won{color:var(--gold-hi);text-shadow:0 0 8px rgba(241,217,138,.5)}.bj-res.bj-lost{color:#c9776e}.bj-res.bj-pushed{color:var(--bone)}.bj-res.bj-wait{color:var(--ash);font-weight:500}
.bj-sub{text-align:center;font-size:12px;color:#9fb49c;margin:2px 0 4px}
.bj-result{text-align:center;margin:4px 0}
.gr-felt.bj .gr-rules{max-width:520px}
/* build 380: motion -- cards slide in as they are dealt, the hole card flips, a bust shakes; winners get the Hold'em glow and chips */
@keyframes bj-in{from{opacity:0;transform:translate(0,-60px) rotate(-9deg) scale(.92)}60%{opacity:1}to{opacity:1;transform:none}}
.bj-hand .pc.bj-in{animation:bj-in .5s cubic-bezier(.2,.8,.2,1) both}
@keyframes bj-held{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.bj-held{animation:bj-held .3s ease both}
.bj-dealer .pc.bj-flip{animation:uno-flip .9s cubic-bezier(.3,.7,.3,1)}
.bj-seat.gr-winner{animation:gr-winner 3s ease-out;border-color:var(--gold-hi)!important}
.bj-seat.bj-bust{animation:gcshake .5s cubic-bezier(.36,.07,.19,.97) both}
@media (prefers-reduced-motion:reduce){.bj-hand .pc.bj-in,.bj-dealer .pc.bj-flip,.bj-seat.bj-bust,.bj-held{animation:none!important}.bj-seat.gr-winner{animation:none;box-shadow:0 0 0 2px #fff3d6,0 0 18px 4px rgba(255,210,120,.6)}}
/* my actions */
.bj-acts{display:flex;gap:8px;margin:2px 0 0}
.bj-acts .btn.bj-act{flex:1;min-width:0;height:44px;padding:0;border-radius:6px;font-size:13px;letter-spacing:1px;text-transform:uppercase}
.bj-acts .btn.bj-act.hit{border-color:var(--leaf);color:#c9f0c9;background:linear-gradient(180deg,#1d4a2e,#0a2414)}
.bj-acts .btn.bj-act.stand{border-color:#b3261e;color:#ffd6d1;background:linear-gradient(180deg,#7a1f17,#3a0c08)}
.bj-acts .btn.bj-act[disabled]{opacity:.45}
.bj-betrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font:500 11px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:var(--ash);padding:4px 0}
.bj-purse{font-weight:700;color:var(--gold-hi);text-transform:none;letter-spacing:0}
.bj-chips{display:flex;gap:6px;margin-left:auto}
button.bj-chip.big{width:36px;height:36px;font-size:11px;border:0;cursor:pointer;padding:0}
button.bj-chip.big:hover{filter:brightness(1.15)}
button.bj-chip.big[disabled]{opacity:.35;cursor:default;filter:none}
@media (max-width:560px){
.gr-felt.bj{padding:10px 6px 8px;border-radius:70px 70px 18px 18px}
.bj-table{display:grid;grid-template-columns:1fr 1.25fr 1fr;grid-template-rows:auto auto;gap:6px;align-items:start}
.bj-dealer{grid-column:2;grid-row:1;padding-top:2px}
.bj-seats{display:contents}
.bj-seat{padding:6px 4px;min-height:96px;gap:4px}
.bj-seat.s1{grid-column:1;grid-row:1}.bj-seat.s5{grid-column:3;grid-row:1}.bj-seat.s2{grid-column:1;grid-row:2}.bj-seat.s3{grid-column:2;grid-row:2}.bj-seat.s4{grid-column:3;grid-row:2}
.bj-seat:not(.me) .pc.sm{width:26px;height:36px;font-size:11px;border-radius:3px}.bj-seat:not(.me) .pc.sm .pc-s{font-size:10px;margin-top:1px}
.bj-seat.me .pc.sm{width:36px;height:50px;font-size:15px}.bj-seat.me .pc.sm .pc-s{font-size:13px}
.bj-dealer .pc{width:34px;height:48px;font-size:14px}.bj-dealer .pc .pc-s{font-size:12px}
.bj-hand{gap:3px}
.bj-name{font-size:10px;letter-spacing:0;gap:4px}.bj-tot{min-width:18px;height:16px;font-size:9px}
.bj-seat.me .bj-name{font-size:12px}
.bj-res{font-size:9px;letter-spacing:.5px}.bj-seat.me .bj-res{font-size:11px}
.bj-bet{font-size:10px}.bj-chip{width:18px;height:18px;font-size:8px}.bj-seat.me .bj-chip{width:22px;height:22px;font-size:9px}
.bj-dl-name{font-size:10px;letter-spacing:.5px;white-space:nowrap;gap:5px}.bj-rule{font-size:8px;letter-spacing:1px;margin-bottom:6px}
.bj-seat.open{font-size:9px;min-height:96px}
.bj-acts .btn.bj-act{height:46px;font-size:12px}
.bj-chips{margin-left:0;width:100%;justify-content:space-between}button.bj-chip.big{width:40px;height:40px}
}
@media (hover:none) and (pointer:coarse){.gr-hd-acts .btn{height:36px}.gr-hd-acts .gr-hd-presets .btn{height:32px;padding:0 10px}.gr-hd-in{height:36px;width:72px;font-size:16px}}
/* v172: pixel art on the page buttons (public/icons/ui-*.png, drawn at 4x their pixel grid so the browser only ever
   scales them down): a thread spool for Threads, a poker table for the Game Room, and a red Romani wagon wheel
   (sixteen spokes, as on the flag) for Roulette, which turns slowly. Each button glows in its icon's colour. */
.fab-ico{display:block;flex:none;pointer-events:none;-webkit-user-drag:none;-webkit-user-select:none;user-select:none}
.thread-toggle-fab .ico-spool{width:32px;height:32px}
.roulette-toggle-fab .ico-wheel{width:30px;height:30px}
.gameroom-toggle-fab .ico-table{width:35px;height:auto}
.thread-toggle-fab:not(.in-header) .ico-spool{filter:drop-shadow(0 0 4px rgba(179,107,255,.5))}
.roulette-toggle-fab:not(.in-header) .ico-wheel{filter:drop-shadow(0 0 4px rgba(227,38,27,.6))}
.gameroom-toggle-fab:not(.in-header) .ico-table{filter:drop-shadow(0 1px 2px #000)}
@media (prefers-reduced-motion:no-preference){.ico-wheel{animation:ico-spin 9s linear infinite}}
@keyframes ico-spin{to{transform:rotate(360deg)}}
@media (min-width:501px){
  .thread-toggle-fab.in-header .ico-spool{width:24px;height:24px}
  .roulette-toggle-fab.in-header .ico-wheel{width:22px;height:22px}
  .gameroom-toggle-fab.in-header .ico-table{width:27px;height:auto}
  .thread-toggle-fab.in-header{filter:drop-shadow(0 0 5px rgba(179,107,255,.5))}
  .thread-toggle-fab.in-header:hover,.thread-toggle-fab.in-header:focus-visible{filter:drop-shadow(0 0 9px rgba(179,107,255,.95))}
  .thread-toggle-fab.in-header.open{filter:drop-shadow(0 0 10px rgba(201,162,74,.9))}
  .roulette-toggle-fab.in-header{filter:drop-shadow(0 0 5px rgba(227,38,27,.5))}
  .roulette-toggle-fab.in-header:hover,.roulette-toggle-fab.in-header:focus-visible,.roulette-toggle-fab.in-header.open{filter:drop-shadow(0 0 9px rgba(227,38,27,.9))}
  .gameroom-toggle-fab.in-header{filter:drop-shadow(0 0 5px rgba(201,162,74,.45))}
}
.tp-hd .ico-table{display:inline-block;width:27px;height:auto;vertical-align:-4px;margin-right:7px}
.toast-i .ico-table{width:27px;height:auto;margin-top:3px}
/* the envelope (Messages) and the light bulb (Suggestions): the bottom bar, the Messages bar, the box's title.
   A faint gold halo keeps their black outlines from sinking into the dark wood. */
.px-ico{display:inline-block;vertical-align:middle;-webkit-user-drag:none;-webkit-user-select:none;user-select:none;filter:drop-shadow(0 0 2px rgba(241,217,138,.35))}
.status .btn-icon .px-ico{height:18px;width:auto}
@media (min-width:501px){.status .btn-icon .px-ico{height:21px}}
#statusPopover .btn-icon .px-ico{height:19px;margin:0 4px} /* about an emoji's width, so the labels line up */
.dm-bar .dm-bar-ico .px-ico{height:16px;width:auto;vertical-align:-3px}
.modal-hd .px-ico{height:22px;width:auto;vertical-align:-4px;margin-right:8px}
/* the suggestion box: problems show inside it; the admin tab shows pictures bigger and plays videos in place */
.idea-err{margin-top:10px;font-size:12px;line-height:1.4;color:#ff8f7a}
.report-row .rr-media{gap:8px}
.rr-media .rr-att{width:84px;height:84px}
.rr-media .rr-video{display:block;width:260px;max-width:100%;max-height:220px;background:#000000;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000}

/* v175: the first-hour package -- a region tag beside names, a wave button on a system line, Quick
   seat at the top of the Game Room, and the region pick on the sign-on screen */
.rtag{font-size:9px;font-style:normal;letter-spacing:.5px;text-transform:uppercase;color:#8f8371;border:1px solid #3a3128;border-radius:3px;padding:0 3px;margin-left:4px;vertical-align:1px;white-space:nowrap}
.nmenu .hd .rtag{margin-left:0}
.log .sys .sys-act{font:700 11px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold);background:rgba(0,0,0,.35);border:1px solid var(--gold-lo);border-radius:4px;padding:1px 8px;margin-left:6px;cursor:pointer;font-style:normal;vertical-align:baseline}
.log .sys .sys-act:hover,.log .sys .sys-act:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
.log .sys .sys-act:disabled{opacity:.45;cursor:default}
.log .sys b.who{font-style:normal;color:var(--them);cursor:pointer}
.gr-quick{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 12px;padding:8px 10px;border:1px solid var(--gold-lo);background:rgba(201,162,74,.06)}
.gr-quick .gr-quickseat{height:32px;font-size:13px;color:var(--gold-hi);border-color:var(--gold);box-shadow:0 0 0 1px #000,0 0 10px rgba(241,217,138,.35)}
.gr-quick .gr-quick-s{font-size:12px;color:var(--ash);font-style:italic}
.login select.sunk{font:inherit;color:var(--bone);width:240px;padding:5px 6px;display:block;margin:0 auto 10px;outline:none;border-radius:0}
.login select.sunk:focus{box-shadow:inset 0 0 18px #000,0 0 0 1px var(--gold)}
.login select.sunk option{background:#0e0906;color:var(--bone)}
/* v123: the player card -- an Xbox-360-style gamercard at the top of the name menu (build 179) */
.nmenu{min-width:250px;max-width:300px}
.nmenu .pcard{margin:-4px -4px 4px;padding:0 0 8px;background:linear-gradient(180deg,#110a06,#050100);border-bottom:2px double var(--gold-lo)}
.nmenu .pc-name{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:7px 10px;font:700 13px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);background:linear-gradient(90deg,rgba(201,162,74,.22),rgba(201,162,74,.04));border-bottom:1px solid var(--gold-lo);text-shadow:0 1px 0 #000}
.nmenu .pc-name .nmt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.nmenu .pc-name.hd{flex-wrap:nowrap;margin-bottom:0}
.nmenu .pc-name .hd-name{min-width:0;max-width:none;overflow:hidden;text-overflow:ellipsis}
.nmenu .pc-name .hd-name.admin{margin-bottom:0;padding:1px 5px;overflow:visible}
.nmenu .pc-role{flex:none;font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:#0f0c09;background:var(--gold);padding:2px 6px;border-radius:2px}
.nmenu .pc-role.friend{background:var(--leaf);color:#e9f5e9}
.nmenu .pc-row{display:flex;gap:10px;padding:9px 10px 4px;align-items:stretch}
.nmenu .ava-card{width:64px;height:64px;font-size:26px;flex:none;margin:0;border:3px solid var(--gold-lo);border-radius:3px;box-shadow:0 0 0 1px #000,inset 0 0 12px #000}
.nmenu .pc-lines{display:flex;flex-direction:column;justify-content:center;gap:4px;min-width:0;flex:1;font-size:12px;color:var(--bone)}
.nmenu .pc-line{display:flex;align-items:center;gap:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.nmenu .pc-xp .lvl{margin:0;flex:none}
.nmenu .pc-xpn{font-variant-numeric:tabular-nums;color:var(--gold-hi)}
.nmenu .pc-purse{font-size:10px;color:#9ad19a;margin-left:6px;padding:0 6px;border:1px solid #2f5a34;border-radius:8px;white-space:nowrap} /* v139: always shown, labelled */
.nmenu .pc-bar{position:relative;height:6px;background:#000000;border:1px solid #3a3026;border-radius:2px;overflow:hidden;box-shadow:inset 0 0 4px #000}
.nmenu .pc-bar i{position:absolute;left:0;top:0;bottom:0;background:linear-gradient(90deg,#8a6a2a,var(--gold-hi));box-shadow:0 0 6px rgba(241,217,138,.5)}
.nmenu .pc-status .pc-dot{width:8px;height:8px;border-radius:50%;background:#362b1f;flex:none;box-shadow:0 0 0 1px #000}
.nmenu .pc-status.st-online .pc-dot{background:var(--leaf);box-shadow:0 0 6px rgba(90,161,90,.9)}
.nmenu .pc-status.st-away .pc-dot{background:var(--gold);box-shadow:0 0 5px rgba(201,162,74,.7)}
.nmenu .pc-status.st-busy .pc-dot{background:var(--blood);box-shadow:0 0 5px rgba(179,38,30,.7)}
.nmenu .pc-status.st-idle .pc-dot{background:#5f6b7a}
.nmenu .pc-stmsg{color:var(--ash);font-style:italic;overflow:hidden;text-overflow:ellipsis}
.nmenu .pc-dim{color:#5f5648;font-style:italic}
.nmenu .pc-bio{margin:6px 10px 0;padding:6px 8px;font:italic 12px/1.45 "IM Fell English",Georgia,serif;color:var(--bone);background:rgba(0,0,0,.35);border:1px solid #2a2119;border-radius:2px;max-height:66px;overflow:hidden;white-space:pre-wrap;word-break:break-word}
.nmenu .acts{display:grid;grid-template-columns:1fr 1fr;gap:2px 4px}
.nmenu .acts button{font-size:12px;padding:5px 7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:500px){.nmenu{max-width:calc(100vw - 12px)}}
/* v124: the Black Ball Pit (build 181) -- vote cards, the fishbowl strip, the climb */
.log .pit-card{border:1px solid #3d2a4d;background:rgba(20,8,28,.55);padding:6px 8px;margin:4px 0;border-radius:3px}
.log .pit-card .pit-body{margin-top:4px;display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;font-style:normal}
.log .pit-tally .yes{color:#9ad19a}.log .pit-tally .no{color:#e07a7a}
.log .pit-clock{font:700 12px Cinzel,Georgia,serif;color:#e2c4ff;font-variant-numeric:tabular-nums}
.pit-dim{color:var(--ash);font-style:italic}
.sys-act.pit-yes{border-color:#3d6b3d;color:#9ad19a}.sys-act.pit-no{border-color:#7a2a2a;color:#e07a7a}
.pit-bowl{position:sticky;top:0;z-index:3;display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;padding:5px 10px;margin:0 0 6px;background:linear-gradient(180deg,#0a0014,#000006);border:1px solid #3d2a4d;box-shadow:inset 0 0 14px #000;font-size:12px;color:var(--bone)}
.pit-bowl .pb-title{font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#c9a3e6}
.pit-bowl .pb-one{display:inline-flex;align-items:center;gap:5px;padding:2px 7px;border:1px solid #3d2a4d;border-radius:12px;background:rgba(0,0,0,.35)}
.pit-bowl .pb-one.me{border-color:#a67ad1;box-shadow:0 0 8px rgba(166,122,209,.35)}
.pit-bowl .pb-clock{font-variant-numeric:tabular-nums;color:#e2c4ff}
.pit-bowl .pb-note{color:var(--ash);font-style:italic}
.pit-bowl .sys-act{margin:0}
.pit-climb-box{max-width:320px}
.pc-wall{position:relative;height:240px;margin:10px auto;width:90px;background:repeating-linear-gradient(180deg,#241711 0 18px,#140a06 18px 20px);border:2px solid #3a3026;border-radius:3px;box-shadow:inset 0 0 20px #000;overflow:hidden}
.pc-hold{position:absolute;left:0;right:0;height:14%;background:rgba(90,161,90,.35);border-top:1px solid #9ad19a;border-bottom:1px solid #9ad19a;transition:top .15s}
.pc-marker{position:absolute;left:50%;width:26px;height:26px;margin-left:-13px;border-radius:50%;background:radial-gradient(circle at 35% 35%,#f1d98a,#8a6a2a);box-shadow:0 0 8px rgba(241,217,138,.6);animation:pc-slide 1.4s ease-in-out infinite alternate}
@keyframes pc-slide{from{top:2%}to{top:88%}}
.pc-row{display:flex;justify-content:space-between;font:700 13px Cinzel,Georgia,serif;color:var(--gold);margin:4px 2px}
.pc-hint{font-size:11px;color:var(--ash);line-height:1.4;margin:4px 0 8px}
.pc-btns{display:flex;gap:8px;justify-content:center}
.pc-btns .pc-grab{font-size:16px;padding:10px 26px}
@media (prefers-reduced-motion:reduce){.pc-marker{animation-duration:2.2s}}

/* v126: the aquarium (build 184) -- a square under the Ballot Box, wide desktops only, same gutter geometry */
.pit-tank{position:fixed;left:calc(50% + 394px);top:calc(max(calc(50vh - 9px),360px) + 16px);width:260px;height:260px;display:none;flex-direction:column;
background:linear-gradient(180deg,#00111f 0%,#000610 60%,#000002 100%);border:3px double var(--gold-lo);outline:1px solid #000;
box-shadow:0 0 0 2px var(--gold-lo),0 0 0 3px #000,0 0 24px #000,inset 0 0 40px rgba(0,0,0,.8),inset 0 -30px 40px rgba(20,60,90,.25);overflow:hidden;z-index:8}
@media (min-width:1340px){.pit-tank{display:flex}}
.pit-tank.hidden{display:none !important}
.gc-root.thread-open .pit-tank{opacity:.28;filter:saturate(.4)}
.pit-tank .pt-title{position:absolute;top:6px;left:0;right:0;text-align:center;font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;color:#c9a3e6;text-shadow:0 1px 0 #000;opacity:.85;pointer-events:none}
.pit-tank .pt-water{position:absolute;inset:0}
.pit-tank .pt-water::before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(100deg,rgba(120,180,220,.05) 0 2px,transparent 2px 28px);animation:pt-shimmer 9s linear infinite;pointer-events:none}
@keyframes pt-shimmer{from{background-position:0 0}to{background-position:280px 0}}
.pit-tank .pt-bubbles{position:absolute;inset:0;pointer-events:none}
.pit-tank .pt-air{position:absolute;bottom:-10px;width:6px;height:6px;border-radius:50%;border:1px solid rgba(180,220,255,.5);animation:pt-rise linear infinite}
@keyframes pt-rise{from{transform:translateY(0);opacity:.8}to{transform:translateY(-270px);opacity:0}}
.pit-tank .pt-empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font:italic 12px "IM Fell English",Georgia,serif;color:#5f7a8a;pointer-events:none}
.pit-tank.has-fish .pt-empty{display:none}
.pit-tank .pt-fish{position:absolute;left:0;top:0;width:44px;text-align:center;will-change:transform;cursor:pointer}
.pit-tank .pt-fish .ava,.pit-tank .pt-fish .ava-fallback{display:flex;align-items:center;justify-content:center;width:36px;height:36px;margin:0 auto;border-radius:50%;border:2px solid var(--gold-lo);box-shadow:0 0 10px rgba(0,0,0,.8),0 0 6px rgba(160,200,240,.25);background:#241910;color:var(--gold);font:700 16px Cinzel,Georgia,serif;object-fit:cover;overflow:hidden}
.pit-tank .pt-fish .pt-name{display:block;margin-top:2px;font:700 9px Cinzel,Georgia,serif;letter-spacing:.5px;color:#e2c4ff;text-shadow:0 1px 0 #000,0 0 4px #000;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pit-tank .pt-fish .pt-say{position:absolute;left:46px;top:2px;width:max-content;max-width:150px;padding:4px 7px;font:12px/1.3 "IM Fell English",Georgia,serif;color:#0f0c09;background:#f1e6c8;border:1px solid #8a6a2a;border-radius:8px 8px 8px 2px;text-align:left;box-shadow:0 2px 6px #000;opacity:0;transform:translateY(4px);transition:opacity .25s,transform .25s;pointer-events:none;word-break:break-word}
.pit-tank .pt-fish.talking .pt-say{opacity:1;transform:none}
.pit-tank .pt-fish.left .pt-say{left:auto;right:46px;border-radius:8px 8px 2px 8px}

/* ==================== v127 (build 185): the phone MENU pill ====================
   Below 501px the Game Room, Roulette and Threads bubbles no longer float about on their own --
   three bubbles plus the Messages pill was a crowd. They live in one pill, twinned with the
   Messages pill, that slides out into a scrolling strip of buttons when tapped. The buttons are
   the same three nodes (placeThreadBtn / placeRouletteBtn / placeGameRoomBtn park them in
   #fabItems on a phone, .in-tray), so every handler on them rides along unchanged. Desktop is
   untouched: the buttons still go into the title bar and the tray never shows. */
.fab-tray{display:none}
@media (max-width:500px){
  .fab-tray{position:fixed;right:6px;top:50%;transform:translateY(-50%);z-index:55;display:flex;align-items:center;max-width:calc(100vw - 12px);
  background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);outline:1px solid #000;border-radius:26px;
  box-shadow:0 0 0 1px #000,0 6px 18px #000,0 0 12px rgba(201,162,74,.35);overflow:hidden;transition:left .22s ease,right .22s ease,top .22s ease,opacity .18s ease}
  .fab-tray:not(:has(.ready)){display:none}                    /* nothing to offer yet (sign-on screen before Roulette is ready) */
  .fab-tray.moved{left:var(--tray-x);top:var(--tray-y);right:auto;transform:none}
  /* build 295: WHICHEVER EDGE THE KNOB IS ON IS THE EDGE THE PILL IS PINNED BY, so the knob cannot
     move when the strip grows or shrinks. Undragged the pill is `right:6px` and this was already
     true; the moment it is dragged it became `left:...`, and then opening grew the box rightwards
     and took the button with it -- measured at 249px of travel on a middle-parked pill, every open
     and every close. The button ran away from the thumb that had just pressed it.
     Parked right: pinned right, knob last, strip grows leftwards.
     Parked left:  pinned left, knob FIRST (row-reverse), strip grows rightwards -- because pinning
     a left-parked pill by its right edge is worse, not better: the strip then opens off the side of
     the screen (measured -117px) and the icons are simply not there.
     Docked is left alone deliberately: a docked pill never opens -- a tap un-docks it first -- so
     its geometry is a closed-position question and the existing maths still owns it. */
  .fab-tray.moved:not(.tray-onleft):not(.tray-docked){left:auto;right:var(--tray-r)}
  .fab-tray.tray-onleft{flex-direction:row-reverse}
  .fab-tray.tray-onleft .ft-items{justify-content:flex-end}
  /* build 295: REMOVED -- `.fab-tray:not(.collapsed).moved{left:auto;right:6px}`, which sent a
     dragged pill to the right edge of the screen every time it opened and back to where you parked
     it every time it closed. `left` cannot animate to or from `auto`, so it did not slide, it
     teleported: the open jumped right, the close jumped back, and the width animated underneath.
     That is the "it collapses from the right" the owner saw, and it predates this week's work.
     It existed for a good reason -- opening in place could run the strip off the side of the screen
     -- and the mirror above is the answer to that reason: the pill now opens AWAY from the edge it
     is parked on, so it opens in place and stays on screen.

     Except it cannot, and the geometry says so plainly: an OPEN tray is 343px wide on a 360px
     screen. There is no horizontal position available to it other than hard against one edge or the
     other -- which is what the old rule had worked out. So the pill DOES travel when it opens. What
     changes is that it now travels deliberately and visibly rather than teleporting, and it goes to
     the NEARER edge, so it stays on the side the owner parked it on. `left` and `right` are lengths
     at both ends of that move so they interpolate; the old rule animated to `auto`, which cannot,
     which is why it jumped. */
  .fab-tray:not(.collapsed).moved:not(.tray-onleft){right:6px;left:auto}
  .fab-tray:not(.collapsed).moved.tray-onleft{left:6px;right:auto}
  .fab-tray.tray-docked{opacity:.55}
  .fab-tray.tray-dragging{transition:none}
  .ft-knob{display:flex;align-items:center;gap:7px;height:42px;padding:0 14px 0 12px;border:none;background:none;cursor:pointer;touch-action:none;position:relative;
  font:700 12px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold-hi);text-shadow:0 0 8px rgba(201,162,74,.5),0 1px 0 #000;user-select:none;-webkit-user-select:none}
  .ft-knob:focus-visible{outline:2px solid var(--gold-hi);outline-offset:-4px;border-radius:22px}
  .ft-knob .ft-ico{font-size:17px;line-height:1;transition:transform .2s ease}
  .fab-tray:not(.collapsed) .ft-knob .ft-ico{transform:rotate(90deg)}
  /* something waiting inside (the Game Room's red dot) shows on the closed pill too */
  .fab-tray.collapsed:has(.news) .ft-knob::after{content:"";position:absolute;top:7px;right:8px;width:9px;height:9px;border-radius:50%;background:var(--blood);
  box-shadow:0 0 0 1px #000,0 0 8px rgba(179,38,30,.9);pointer-events:none}
  /* build 292 wrapped this row so eight icons could fit; build 294 UNWRAPPED IT AGAIN and shrank
     the icons instead. Wrapping cost two bugs in two days: a closed pill 366px tall (293), and an
     open transition that reflowed on every frame because an animating max-width re-wraps the row at
     every intermediate width -- it visibly stacked vertically and then sorted itself out sideways.
     A row that cannot wrap cannot do either. The icons below 375px are 32px so all eight fit. */
  /* build 297: BACK TO flex-start, deliberately this time, and for the opposite reason.
     A flex row inside a shrinking box is pinned to one edge and clipped at the other. The strip's
     right edge is the one standing still (it sits against the knob); its LEFT edge is the one that
     travels. 295 pinned the row to the still edge, so the icons did not move at all and were eaten
     where they sat -- correct in the sense that the far ones went first, and wrong in the sense the
     owner put best: they "poof out of existence". Pinning to the TRAVELLING edge makes the whole row
     ride along with the closing pill and tuck under the knob, which is what a drawer does.
     The cost, chosen with eyes open: the icons nearest the knob now go first. That is inherent --
     a row that travels has to disappear into something -- and it is why 295 went the other way.
     Mirrored below: when the pill is parked on the left the knob is the left-hand element, so the
     travelling edge is the RIGHT one and the pin flips with it. */
  .ft-items{display:flex;align-items:center;justify-content:flex-start;gap:6px;padding:0;max-width:0;opacity:0;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;
  transition:max-width .25s ease,opacity .2s ease,padding .25s ease}
  .ft-items::-webkit-scrollbar{display:none}
  .fab-tray:not(.collapsed) .ft-items{max-width:calc(100vw - 118px);opacity:1;padding:0 2px 0 8px}
  /* build 293: A COLLAPSED STRIP MUST NOT BE ABLE TO CONTRIBUTE HEIGHT. The tray closes by
     animating .ft-items to max-width:0 -- which was safe for as long as that row could not wrap.
     Build 292 added flex-wrap so eight icons could share the open tray, and a WRAPPING flex row
     0px wide puts every child on a line of its own: the closed pill grew to 99 x 366, a slab down
     half the side of the screen, filled with icons at opacity:0 so there was nothing in it to see.
     max-height with overflow:hidden is deliberately belt and braces -- it pins the closed height so
     the next person to touch the wrapping rules cannot bring the slab back. The padding goes too,
     or it would still measure a few px.

     build 298: the clamp was `max-height:0`, AND THAT IS WHAT MADE THE ICONS VANISH IN ONE FRAME.
     max-height is not in the transition list, so the instant `.collapsed` landed the strip's height
     went to zero and every icon was clipped away 33ms in -- before the width animation had moved at
     all. What then played out over 200ms was an EMPTY pill shrinking. Every attempt to animate how
     the icons leave (297's drawer and dissolve) was therefore animating nothing: they were already
     gone. Caught from a video the owner recorded, frames 124 and 125, one frame apart.
     44px is one row's worth. Since 294 removed flex-wrap this row cannot stack, so a one-row
     ceiling still forbids the slab while leaving the icons on screen to be animated. */
  .fab-tray.collapsed .ft-items{max-height:44px;overflow:hidden;padding-top:0;padding-bottom:0}
  /* build 297: and a soft edge WHERE THEY LEAVE, so they dissolve into the knob instead of meeting
     a hard cut at it. Masked only while collapsing -- an always-on mask would leave the icon
     nearest the knob permanently half-faded while the menu sits open. The gradient is on the knob
     side, which is the right edge normally and the left edge when the pill is parked left. */
  .fab-tray.collapsed .ft-items{-webkit-mask-image:linear-gradient(90deg,#000 0 calc(100% - 20px),transparent);mask-image:linear-gradient(90deg,#000 0 calc(100% - 20px),transparent)}
  .fab-tray.collapsed.tray-onleft .ft-items{-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 20px);mask-image:linear-gradient(90deg,transparent 0,#000 20px)}
  .fab-tray .in-tray{position:relative !important;top:auto !important;right:auto !important;left:auto !important;bottom:auto !important;transform:none !important; /* relative, not static: the Game Room dot is an absolutely-placed ::after */
  width:40px;height:40px;flex:none;border-radius:10px;opacity:1 !important;touch-action:auto;transition:none;display:none}
  .fab-tray .in-tray.ready{display:flex}
  /* build 292: the scroll and the trophy ride here below 375px. Everything else in the tray is a
     purpose-built .fab button; these two are .cell chips borrowed out of the header, so they need
     the tray's 40px box drawn for them and the text label -- which the header hides -- kept hidden. */
  .fab-tray .cell.in-tray.ready{display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;color:var(--gold-hi);
  background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
  .fab-tray .cell.in-tray .btn-icon{font-size:20px;line-height:1}
  .fab-tray .cell.in-tray .popover-label{display:none}
  /* build 294: eight icons on ONE row below 375px. The strip is 296px there and eight 40px icons
     with 6px gaps want 362, so the icons come down to 32 and the gaps to 4: 8x32 + 7x4 = 284. The
     visible box shrinks but the TARGET does not -- ::before carries a 36 x 44 hit area underneath.
     36 and not 44 across on purpose: the icon pitch is 36 (32 + the 4 gap), and a 44-wide target on
     a 36 pitch overlaps its neighbours and starts stealing their taps, which is a worse bug than a
     small icon. ::after is spoken for here -- it draws the Game Room's dot. */
  @media (max-width:374px){
    .fab-tray .in-tray{width:32px;height:32px}
    .ft-items{gap:4px}
    .fab-tray .in-tray::before{content:"";position:absolute;left:50%;top:50%;width:36px;height:44px;transform:translate(-50%,-50%);border-radius:10px}
    /* and the strip has to stop clipping it. `overflow-x:auto` forces overflow-y back to auto no
       matter what you write, so the 44px target was being cut to the 32px icon -- measured 35x31.
       Nothing needs to scroll here any more now the row cannot wrap and 284px of icons sit in a
       296px strip, so the whole thing goes visible and the target is real. The CLOSED rule above
       still sets overflow:hidden, which is what keeps the pill shut. */
    .fab-tray:not(.collapsed) .ft-items{overflow:visible}
  }
  /* the takeover pages hide the bubbles; they hide the tray the same way */
  .gc-root.gameroom-open .fab-tray,.gc-root.leaderboard-open .fab-tray,.gc-root.admin-open .fab-tray,.gc-root.mobile-roulette-open .fab-tray,
  .gc-root.mobile-threads-open .fab-tray,.gc-root.dm-open .fab-tray,.gc-root.pit-open .fab-tray{display:none !important}
}
@media (prefers-reduced-motion:reduce){.fab-tray,.ft-items,.ft-knob .ft-ico{transition:none !important}}

/* ==================== v128 (build 186): the Pit on a phone (the button; the page itself is the v129 block below) ====================
   The 8-ball in the MENU pill (below 501px only -- the tank has its own gutter from 1340px up and
   nothing in between asked for it) opens #pitTank as a full-screen page: the same aside, the same
   fish, just the whole screen of water and a "Back to chat" bar along the top. */
.pit-toggle-fab{display:none}
.pit-toggle-fab .ico-8ball{width:34px;height:34px;image-rendering:pixelated;filter:drop-shadow(0 0 4px rgba(200,220,255,.35))}
.fab-tray .pit-toggle-fab.in-tray.ready{display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;color:var(--gold-hi);
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
.pit-tank .pt-back{display:none}

/* ==================== v129 (build 187): the Pit's own room ====================
   The Pit page (.gc-root.pit-open) is now for every width, not just phones: the aquarium on top,
   its own log under it, a composer along the bottom that only the pitted can use. Nothing said in
   the pit is written into the main log any more (pitSaid in app.js). Desktop gets the 8-ball in
   the title bar beside Roulette and the Game Room; the 260px gutter tank stays and opens the page
   on a click. */
.gc-root.pit-open .win{display:none}
.gc-root.pit-open .pit-tank{display:flex !important;position:fixed;inset:0;left:0;top:0;width:100%;height:100%;border-width:0;border-radius:0;z-index:40;opacity:1;filter:none;
flex-direction:column;background:linear-gradient(180deg,var(--stone-2),var(--stone))}
.gc-root.pit-open .pit-tank .pt-water{position:relative;inset:auto;flex:none;height:min(46vh,420px);width:100%;overflow:hidden;
background:radial-gradient(ellipse at 50% 20%,#0e2b39,#00080f 70%);border-bottom:3px double var(--gold-lo);box-shadow:inset 0 -20px 30px #000}
.gc-root.pit-open .pit-tank .pt-title{top:8px;bottom:auto;font-size:12px;z-index:2}
.gc-root.pit-open .pit-tank .pt-empty{position:absolute;inset:0;height:min(46vh,420px);font-size:14px}
.gc-root.pit-open .pit-tank .pt-air{animation-name:pt-rise-tall}
@keyframes pt-rise-tall{from{transform:translateY(0);opacity:.8}to{transform:translateY(-110vh);opacity:0}}
.gc-root.pit-open .pit-tank .pt-fish{width:56px}
.gc-root.pit-open .pit-tank .pt-fish .ava,.gc-root.pit-open .pit-tank .pt-fish .ava-fallback{width:46px;height:46px;font-size:19px}
.gc-root.pit-open .pit-tank .pt-fish .pt-name{font-size:10px}
.gc-root.pit-open .pit-tank .pt-fish .pt-say{left:58px;max-width:190px;font-size:13px}
.gc-root.pit-open .pit-tank .pt-fish.left .pt-say{left:auto;right:58px}
.gc-root.pit-open .pit-tank .pt-back{display:block;position:absolute;top:8px;left:8px;z-index:3;padding:7px 12px;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi);
background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);border-radius:18px;box-shadow:0 0 0 1px #000,0 4px 12px #000;cursor:pointer}
html.ios .gc-root.pit-open .pit-tank .pt-back{top:calc(env(safe-area-inset-top) + 8px)}
html.ios .gc-root.pit-open .pit-tank .pt-title{top:calc(env(safe-area-inset-top) + 8px)}
.gc-root.pit-open .fab-tray,.gc-root.pit-open .dm-dock,.gc-root.pit-open .thread-toggle-fab,.gc-root.pit-open .roulette-toggle-fab,.gc-root.pit-open .gameroom-toggle-fab{display:none !important}
/* the room under the water */
.pit-tank .pt-room{display:none}
.gc-root.pit-open .pit-tank .pt-room{display:flex;flex-direction:column;flex:1;min-height:0;width:100%;max-width:760px;margin:0 auto;box-sizing:border-box;order:2}
.gc-root.pit-open .pit-tank .pt-water{order:1} /* the markup has the room before the water; the page wants water on top */
.pt-log{flex:1;min-height:0;overflow-y:auto;padding:10px 12px;font-size:14px;line-height:1.5;scrollbar-color:var(--gold-lo) #0f0d0b}
.pt-line{margin:2px 0;color:var(--bone);word-break:break-word}
.pt-line .t{font:italic 11px "IM Fell English",Georgia,serif;color:#7a6d5a;margin-right:6px}
.pt-line .ava,.pt-line .ava-fallback{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-right:5px;border-radius:50%;vertical-align:-4px;object-fit:cover;font:700 10px Cinzel,Georgia,serif;background:#241910;color:var(--gold);border:1px solid var(--gold-lo)}
.pt-line b.who{color:#e2c4ff;cursor:pointer}
.pt-line.me b.who{color:var(--gold-hi)}
.pt-hello,.pt-note{margin:6px 0;font:italic 12px "IM Fell English",Georgia,serif;color:#8a8070;text-align:center}
.pt-comp{display:flex;gap:6px;padding:8px 10px;border-top:2px solid var(--gold-lo);background:#0a0602;flex:none}
.pt-comp input{flex:1;min-width:0;padding:8px 10px;font:14px "IM Fell English",Georgia,serif;color:var(--bone);background:#050200;border:1px solid #3a3026;border-radius:6px}
.pt-comp input:disabled{color:#6a6050;font-style:italic}
.pt-comp .btn:disabled{opacity:.45;cursor:default}
/* desktop: the 8-ball in the title bar, styled like the Game Room's table there */
@media (min-width:501px){
  .pit-toggle-fab.in-header{display:inline-flex;position:relative !important;top:auto !important;right:auto !important;left:auto !important;bottom:auto !important;
  transform:none !important;width:26px;height:auto;flex:none;align-items:center;justify-content:center;padding:0;border:none;border-radius:0;background:none;box-shadow:none;
  cursor:pointer;opacity:.92;filter:drop-shadow(0 0 6px rgba(160,200,240,.45));transition:transform .15s ease,filter .15s ease,opacity .15s ease}
  .pit-toggle-fab.in-header .ico-8ball{width:22px;height:22px}
  .pit-toggle-fab.in-header:hover,.pit-toggle-fab.in-header:focus-visible{opacity:1;outline:none;transform:translateY(-1px) scale(1.14) !important;filter:drop-shadow(0 0 11px rgba(160,200,240,.95))}
  /* balance: the 8-ball joins Roulette and the table on the left of the name */
  .win > .title.hb-pit.hb-gr.hb-left.hb-right::after{content:"";flex:none;width:52px}
  .win > .title.hb-pit.hb-gr.hb-left:not(.hb-right)::after{content:"";flex:none;width:78px}
  .pit-tank:not(.hidden){cursor:pointer}
  .gc-root:not(.pit-open) .pit-tank:not(.hidden):hover .pt-title::after{content:" \2014 enter";opacity:.8}
}

/* v130 (build 188): the strip in the main log opens the Black Ball Pit page -- the title is a button
   and the strip itself is clickable anywhere that isn't a name or a button */
.pit-bowl{cursor:pointer}
.pit-bowl .pb-title{background:none;border:none;padding:0;cursor:pointer;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#c9a3e6;text-shadow:0 0 6px rgba(200,150,255,.35)}
.pit-bowl .pb-title:hover,.pit-bowl .pb-title:focus-visible,.pit-bowl:hover .pb-title{color:#fff;text-shadow:0 0 8px rgba(200,150,255,.8);outline:none}

/* v131 (build 189): the gutters end where the chat window ends. The window's height is whatever
   its content comes to, so app.js measures it (syncGutterHeights: a ResizeObserver on .win writes
   --win-bottom, the window's bottom edge in viewport px, onto .gc-root). The roulette teaser on
   the left was running to the bottom of the screen; the Black Ball Pit tank on the right stopped
   short of the window's footer. Both now finish on the same line as the window. */
@media (min-width:1340px){
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel{bottom:auto;height:calc(var(--win-bottom, calc(100vh - 6px)) - 6px);box-sizing:border-box} /* build 352: not the full Roulette page (it stopped ~70px short) */
  .gc-root.signed-on:not(.pit-open) .pit-tank{height:max(200px,calc(var(--win-bottom, 100vh) - (max(calc(50vh - 9px),360px) + 16px)))}
}

/* ==================== v132 (build 190): the streamlining ====================
   1. Desktop bottom row: five things -- you, Messages, Popularity Contest, Notifications, ⚙ -- and
      the rest behind the gear. #statusPopover was display:contents on desktop (its buttons rendered
      inline); it is a real menu now, opened by the same #moreBtn that is "..." on phones and "⚙" here.
   2. Phones: no bottom bar. The Ballot Box, the Popularity Contest and "..." sit at the right end
      of the title bar; the "..." menu begins with your name and status dot (placeStatusBits, app.js).
   3. The left gutter: the roulette teaser at half height with the Popularity Contest's top five
      under it, until Roulette ships and takes the column back.
   4. The MENU pill waits until you're in; the NKJV notice lives in the About bubble (the watermark
      line) rather than under the toolbar. */
.more-gear{display:none}
.status{position:relative}
@media (min-width:501px){
  #moreBtn{display:inline-flex}
  .more-dots{display:none}.more-gear{display:inline;font-size:19px;line-height:1}
  .status .morebtn{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);border-radius:2px;cursor:pointer}
  .status .morebtn:hover,.status .morebtn[aria-expanded="true"]{color:var(--gold-hi);border-color:var(--gold)}
  .status .morebtn::after{content:"Settings";display:block;font:600 8px Cinzel,Georgia,serif;letter-spacing:.5px;text-transform:uppercase;margin-top:3px}
  #statusPopover{display:none;flex-direction:column;gap:2px;position:absolute;right:8px;bottom:calc(100% - 4px);z-index:48;min-width:210px;padding:6px;
  background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);outline:1px solid #000;border-radius:8px;box-shadow:0 0 0 1px #000,0 6px 18px #000}
  #statusPopover.open{display:flex}
  #statusPopover .cell{width:100%;display:flex !important;flex-direction:row !important;align-items:center;justify-content:flex-start !important;gap:8px;text-align:left;min-width:0;max-width:none;padding:6px 8px;border:none;border-radius:6px}
  #statusPopover .cell:hover{background:rgba(201,162,74,.08)}
  #statusPopover .popover-label{display:inline;font:12px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;max-width:none}
  #statusPopover .btn-icon{font-size:16px;width:22px;text-align:center}
  /* what lives elsewhere on desktop: status, picture and save are on your card; notifications is in the row */
  #statusPopover .statusbtn,#statusPopover .avabtn,#statusPopover .mypagebtn,#statusPopover .savebtn,#statusPopover .pop-hd,#statusPopover .pop-me,#statusPopover .popover-version,#statusPopover .popover-nkjv{display:none !important}
  #statusPopover .soundbtn{order:1}#statusPopover .whisperbtn{order:2}
  #statusPopover .ideabtn{order:4}#statusPopover .bugbtn{order:5}#statusPopover .reportsbtn{order:6}
  #statusPopover .logoutbtn{order:9;margin-top:4px;border-top:1px solid #2a2119;border-radius:0 0 6px 6px;padding-top:8px}
  #statusPopover .ideabtn{margin-top:4px;border-top:1px solid #2a2119;border-radius:0;padding-top:8px}
  #statusPopover .reportsbtn .rbadge{position:static;margin-left:auto}
  #statusPopover .notifbtn,#statusPopover .soundbtn{padding-right:8px}
  /* you */
  .status .mebtn{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);padding:1px 8px;cursor:pointer;border-radius:2px;flex:none;position:relative}
  .status .mebtn:hover{color:var(--gold-hi);border-color:var(--gold)}
  .status .mebtn .ava-thumb{width:22px;height:22px;border-radius:50%;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;font:700 12px Cinzel,Georgia,serif;color:var(--gold);background:#241910;border:1px solid var(--gold-lo)}
  .status .mebtn .ava-thumb img{width:22px;height:22px;object-fit:cover}
  .status .mebtn .popover-label{max-width:84px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap !important}
  .status .statusbtn{display:none !important}
  .title-tools{display:none}
}
/* phones: the bottom bar folds into the title bar */
@media (max-width:500px){
  .gc-root.tools-up .status{display:none}
  .win > .title{position:relative}
  .gc-root.tools-up .win > .title{justify-content:flex-start;padding-right:96px}
  .title-tools{position:absolute;right:6px;top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:4px;z-index:16}
  .title-tools .cell{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);border-radius:6px;padding:2px 5px;cursor:pointer;line-height:1;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px}
  .title-tools .cell .btn-icon{font-size:15px;line-height:1}
  .title-tools .cell .popover-label{display:none}
  .title-tools #moreBtn{font-size:16px}
  .title-tools #statusPopover{position:absolute;top:34px;bottom:auto;right:0;left:auto;width:auto;min-width:210px;max-width:calc(100vw - 20px)}
  .title-tools #statusPopover .cell{width:100%;height:auto;border:none;justify-content:flex-start}
  .title-tools #statusPopover .cell .popover-label{display:inline}
  .title-tools #statusPopover .cell .btn-icon{font-size:16px;width:22px;text-align:center}
  #statusPopover .pop-me{display:flex;align-items:center;gap:8px;padding:4px 8px 6px;border-bottom:1px solid #2a2119;margin-bottom:2px}
  #statusPopover .pop-me #st{font:700 13px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold-hi);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #statusPopover .pop-me .statusbtn{width:auto;flex:none;border:1px solid var(--gold-lo) !important;border-radius:12px;padding:2px 8px}
  #statusPopover .pop-me .statusbtn .popover-label{display:none}
  .gc-root.tools-up .win > .title .name{font-size:17px;letter-spacing:1px}
  /* build 291: BOTH lanterns go on a phone, not just the second. The header is six tools plus a
     purse -- about 200pt of a 414pt row -- and "Gypsy Chat 2000" in Cinzel is 168. With the lantern
     and its 12px gap taking 27, the name had 162 to live in and truncated to "Gypsy Chat 2…".
     Dropping it leaves 189 and the name fits whole at its full 17px, which is the point: the
     lantern is decoration, the name is the brand. Owner picked this over shrinking the type or
     abbreviating to "GC 2K". ~20pt of slack remains at 414pt, so a seventh tool would squeeze it
     again -- it would ellipsis rather than slide under the purse, which is the graceful failure,
     but it is slack, not comfort. The desktop header keeps both lanterns.

     build 292: scoped to `.signed-on`. Signed out there are no tools to speak of, so the login
     screen has room for the lanterns and gets them back -- owner's call, and the right one: the
     lantern is the first thing a new arrival sees, and that is the screen with nothing else on it.
     They still go once you are in the room, where the six tools need the width. */
  .gc-root.tools-up.signed-on .win > .title .lantern{display:none}
  .gc-root:not(.signed-on) .fab-tray{display:none !important}
}
/* the left gutter: a smaller wheel, the top five beneath */
@media (min-width:1340px){
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel{justify-content:flex-start;padding-top:16px;padding-bottom:12px}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .rp-eyebrow{margin-bottom:6px}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .rp-title{font-size:20px}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .rp-rule{margin:10px 0}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .rp-blurb{display:none}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .rp-wheel{width:104px;height:104px;margin-top:6px}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .rp-hint{margin-top:6px}
  .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel .room-watermark{margin-top:auto}
  /* build 352: the gutter's small-wheel rules above left the full Roulette page with a 104px wheel and no blurb */
}
.rp-top5{width:100%;margin-top:14px;padding-top:10px;border-top:1px solid #2a2119;text-align:left}
/* v133: on the full-screen roulette page (phones and under 1340px) the list stretched across the whole screen --
   rank and name at one edge, the level at the other. Same 260px column as the gutter there, centred. */
.gc-root.mobile-roulette-open .rp-top5{width:100%;max-width:260px;margin-left:auto;margin-right:auto}
.rp-top5.hidden{display:none}
.rp-top5-hd{display:block;width:100%;background:none;border:none;padding:0 0 6px;cursor:pointer;font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);text-align:center}
.rp-top5-hd:hover{color:var(--gold-hi)}
.rp-top5-list{display:flex;flex-direction:column;gap:3px}
.rp-top5-row{display:flex;align-items:center;gap:6px;width:100%;background:none;border:1px solid transparent;border-radius:6px;padding:3px 6px;cursor:pointer;color:var(--bone);font:13px "IM Fell English",Georgia,serif;text-align:left}
.rp-top5-row:hover,.rp-top5-row:focus-visible{border-color:var(--gold-lo);background:rgba(201,162,74,.06);outline:none}
.rp-top5-rank{width:20px;flex:none;text-align:center;font-size:12px;color:var(--ash)}
.rp-top5-row .ava,.rp-top5-row .ava-fallback{width:20px;height:20px;border-radius:50%;flex:none;display:inline-flex;align-items:center;justify-content:center;font:700 10px Cinzel,Georgia,serif;background:#241910;color:var(--gold);border:1px solid var(--gold-lo);object-fit:cover;overflow:hidden}
.rp-top5-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rp-top5-name.admin{color:#ffa64d}
.rp-top5-empty{font:italic 12px "IM Fell English",Georgia,serif;color:var(--ash);text-align:center;padding:6px}
.room-watermark[role="button"]{cursor:pointer;pointer-events:auto}
@media (min-width:501px){.gc-root.signed-on .status #st{display:none}} /* your name is on the You button now */
.room-watermark[role="button"]:hover{color:var(--gold-hi)}

/* ==================== v134 (build 192): profile pages ====================
   .gc-root.profile-open is the same full-screen takeover as the Game Room. The page is a 760px
   column: a header band (the person's header image, or the theme's own), the card's facts, a
   row of actions, the bio, a stats strip, Top Friends, the wall. Two looks to start -- parchment
   (the room's own) and midnight -- as CSS variables the theme classes redefine; --pf-accent is the
   person's accent colour, used for the band and the rules. */
.profile-panel{display:none;flex-direction:column;overflow:hidden;z-index:8;
--pf-bg:linear-gradient(180deg,var(--stone-2),var(--stone));--pf-ink:var(--bone);--pf-dim:#8a8070;--pf-gold:var(--gold);--pf-gold-hi:var(--gold-hi);--pf-line:#3a3026;--pf-card:#14100d;--pf-band:linear-gradient(135deg,#3a2c1a,#1a1410 60%,#2a1f14)}
.profile-panel.pf-theme-midnight{--pf-bg:linear-gradient(180deg,#0e1424,#070a14);--pf-ink:#d9dde8;--pf-dim:#7d859c;--pf-gold:#b8c2dc;--pf-gold-hi:#f1f4ff;--pf-line:#252d45;--pf-card:#0b0f1c;--pf-band:linear-gradient(135deg,#1c2748,#0a0f22 60%,#141b36)}
.gc-root.profile-open .win{display:none}
.gc-root.profile-open .profile-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;height:100%;border-width:0;border-radius:0;z-index:40;background:var(--pf-bg);color:var(--pf-ink)}
.gc-root.profile-open .fab-tray,.gc-root.profile-open .dm-dock,.gc-root.profile-open .thread-toggle-fab,.gc-root.profile-open .roulette-toggle-fab,.gc-root.profile-open .gameroom-toggle-fab,.gc-root.profile-open .pit-toggle-fab{display:none !important}
html.ios .gc-root.profile-open .profile-panel{padding-top:env(safe-area-inset-top);box-sizing:border-box}
.profile-panel .tp-hd{position:relative;color:var(--pf-gold)}
.pf-share{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:1px solid var(--pf-line);border-radius:6px;color:var(--pf-gold);font-size:14px;width:30px;height:26px;cursor:pointer}
.pf-share:hover{color:var(--pf-gold-hi);border-color:var(--pf-gold)}
.pf-body{flex:1;min-height:0;overflow-y:auto;width:100%;max-width:760px;margin:0 auto;box-sizing:border-box;padding:0 0 24px;scrollbar-color:var(--pf-line) #0f0d0b}
.pf-empty{padding:40px 16px;text-align:center;font:italic 14px "IM Fell English",Georgia,serif;color:var(--pf-dim)}
.pf-empty-sm{padding:10px 4px;font:italic 12px "IM Fell English",Georgia,serif;color:var(--pf-dim)}
.pf-band{height:120px;background:var(--pf-band);background-size:cover;background-position:center;border-bottom:3px double var(--pf-line);box-shadow:inset 0 -30px 40px rgba(0,0,0,.5)}
.profile-panel[style*="--pf-accent: #"] .pf-band{box-shadow:inset 0 -30px 40px rgba(0,0,0,.5),inset 0 -4px 0 var(--pf-accent)}
.pf-head{display:flex;gap:14px;align-items:flex-start;padding:0 16px;margin-top:-36px}
.pf-ava{width:88px;height:88px;flex:none;border-radius:14px;border:3px solid var(--pf-gold);box-shadow:0 0 0 1px #000,0 6px 18px #000;object-fit:cover;background:var(--pf-card);display:flex;align-items:center;justify-content:center;font:700 34px Cinzel,Georgia,serif;color:var(--pf-gold);overflow:hidden}
.pf-lines{flex:1;min-width:0;padding-top:40px}
.pf-name{font:700 20px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--pf-gold-hi);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pf-name .pc-role{font-size:10px}
.pf-sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:4px;font-size:13px;color:var(--pf-ink)}
.pf-fam{background:none;border:1px solid var(--pf-line);border-radius:10px;padding:1px 8px;color:var(--pf-gold);font:12px "IM Fell English",Georgia,serif;cursor:pointer}
.pf-fam:hover{border-color:var(--pf-gold);color:var(--pf-gold-hi)}
.pf-status{margin-top:4px;font:italic 13px "IM Fell English",Georgia,serif;color:var(--pf-ink);opacity:.9}
.pf-meta{margin-top:4px;font-size:12px;color:var(--pf-dim)}
.pf-song{display:inline-block;margin-top:6px;padding:3px 10px;border:1px solid var(--pf-gold);border-radius:14px;color:var(--pf-gold-hi);font:12px "IM Fell English",Georgia,serif;text-decoration:none;background:rgba(0,0,0,.25)}
.pf-song:hover{background:rgba(201,162,74,.12)}
.pf-acts{display:flex;flex-wrap:wrap;gap:6px;padding:12px 16px 0}
.pf-acts .btn{font-size:12px;padding:5px 12px}
.pf-acts .pf-danger{color:#e07a7a;border-color:#7a2a2a}
.pf-bio{margin:12px 16px 0;padding:10px 12px;background:var(--pf-card);border:1px solid var(--pf-line);border-radius:8px;font-size:14px;line-height:1.5;color:var(--pf-ink);white-space:pre-wrap;word-break:break-word}
.pf-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin:12px 16px 0}
.pf-stat{background:var(--pf-card);border:1px solid var(--pf-line);border-radius:8px;padding:6px 4px;text-align:center}
.pf-stat b{display:block;font:700 15px Cinzel,Georgia,serif;color:var(--pf-gold-hi)}
.pf-stat span{display:block;font:600 8px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:var(--pf-dim);margin-top:2px}
.pf-sec{margin:16px 16px 0}
.pf-sec-hd{font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--pf-gold);padding-bottom:6px;border-bottom:1px solid var(--pf-line);margin-bottom:8px}
.pf-tfs{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.pf-tf{display:flex;flex-direction:column;align-items:center;gap:4px;background:var(--pf-card);border:1px solid var(--pf-line);border-radius:8px;padding:8px 4px;cursor:pointer;color:var(--pf-ink);font:12px "IM Fell English",Georgia,serif}
.pf-tf:hover{border-color:var(--pf-gold)}
.pf-tf span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-tf-ava{width:44px;height:44px;border-radius:50%;border:2px solid var(--pf-gold);object-fit:cover;display:flex;align-items:center;justify-content:center;font:700 18px Cinzel,Georgia,serif;color:var(--pf-gold);background:#000000;overflow:hidden}
.pf-comp{display:flex;gap:6px;align-items:flex-end;margin-bottom:10px}
.pf-comp textarea{flex:1;min-width:0;resize:none;padding:8px 10px;font:14px "IM Fell English",Georgia,serif;color:var(--pf-ink);background:var(--pf-card);border:1px solid var(--pf-line);border-radius:8px}
.pf-comp .btn{font-size:12px;padding:7px 14px}
.pf-post{display:flex;gap:8px;padding:8px 0;border-bottom:1px solid var(--pf-line)}
.pf-post-ava{width:30px;height:30px;border-radius:50%;flex:none;object-fit:cover;display:inline-flex;align-items:center;justify-content:center;font:700 13px Cinzel,Georgia,serif;color:var(--pf-gold);background:var(--pf-card);border:1px solid var(--pf-line);overflow:hidden}
.pf-post-body{flex:1;min-width:0}
.pf-post-hd{display:flex;align-items:center;gap:8px}
.pf-post-hd b.who{color:var(--pf-gold-hi);cursor:pointer;font:700 13px Cinzel,Georgia,serif}
.pf-post-hd .t{font:italic 11px "IM Fell English",Georgia,serif;color:var(--pf-dim);flex:1}
.pf-x{background:none;border:none;color:var(--pf-dim);cursor:pointer;font-size:12px;padding:2px 4px;opacity:.6}
.pf-x:hover{opacity:1;color:#e07a7a}
.pf-post-txt{font-size:14px;line-height:1.45;color:var(--pf-ink);white-space:pre-wrap;word-break:break-word;margin-top:2px}
@media (max-width:500px){
  .pf-band{height:96px}
  .pf-head{gap:10px}
  .pf-ava{width:72px;height:72px;font-size:28px}
  .pf-lines{padding-top:30px}
  .pf-name{font-size:17px}
  .pf-stats{grid-template-columns:repeat(4,1fr);gap:4px}
  .pf-stat b{font-size:13px}
}

/* ==================== v135 (build 193): the page editor ==================== */
.pf-edit{max-width:520px;max-height:calc(100vh - 32px);display:flex;flex-direction:column;text-align:left}
.pfe-body{flex:1;min-height:0;overflow-y:auto;padding-right:4px;scrollbar-color:var(--gold-lo) #0f0d0b}
.pfe-lbl{display:block;font:700 10px Cinzel,Georgia,serif;letter-spacing:1.5px;text-transform:uppercase;color:var(--gold);margin:10px 0 5px}
.pfe-dim{font:italic 11px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;color:var(--ash)}
.pfe-row input[type=text],.pfe-row input[type=url],.pfe-row textarea,.pfe-row select{width:100%;box-sizing:border-box;padding:7px 9px;margin-bottom:5px;font:14px "IM Fell English",Georgia,serif;color:var(--bone);background:#050200;border:1px solid #3a3026;border-radius:6px}
.pfe-row textarea{resize:vertical}
.pfe-row select{width:auto;min-width:70px;margin-bottom:0}
.pfe-inline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pfe-chk{font:13px "IM Fell English",Georgia,serif;color:var(--bone);display:inline-flex;align-items:center;gap:6px}
.pfe-banner{height:110px;border:1px solid #3a3026;border-radius:8px;background:linear-gradient(135deg,#362611,#110a06 60%,#24170a);background-size:cover;background-position:center;display:flex;align-items:flex-end;justify-content:flex-end;gap:6px;padding:8px;box-shadow:inset 0 -30px 40px rgba(0,0,0,.5)}
.pfe-sm{font-size:11px;padding:4px 10px;min-width:0}
.pfe-themes{display:flex;gap:8px}
.pfe-theme{flex:1;display:flex;align-items:center;justify-content:center;height:44px;border:2px solid #3a3026;border-radius:8px;cursor:pointer;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px}
.pfe-theme input{display:none}
.pfe-theme.on{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.4)}
.pfe-theme-parchment{background:linear-gradient(180deg,var(--stone-2),var(--stone));color:var(--gold)}
.pfe-theme-midnight{background:linear-gradient(180deg,#030a1d,#00000a);color:#d9dde8}
#pfeAccent{width:44px;height:30px;padding:0;border:1px solid #3a3026;border-radius:6px;background:none;cursor:pointer}
.pfe-friends{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;max-height:190px;overflow-y:auto}
.pfe-fr{position:relative;display:flex;flex-direction:column;align-items:center;gap:3px;background:#0a0602;border:1px solid #3a3026;border-radius:8px;padding:6px 3px;cursor:pointer;color:var(--bone);font:11px "IM Fell English",Georgia,serif}
.pfe-fr .ava,.pfe-fr .ava-fallback{width:32px;height:32px;border-radius:50%;object-fit:cover;display:inline-flex;align-items:center;justify-content:center;font:700 14px Cinzel,Georgia,serif;color:var(--gold);background:#000000;border:1px solid var(--gold-lo);overflow:hidden}
.pfe-fr-name{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pfe-fr.on{border-color:var(--gold);background:rgba(201,162,74,.08)}
.pfe-fr-n{position:absolute;top:2px;right:4px;font:700 11px Cinzel,Georgia,serif;color:var(--gold-hi)}
.pfe-btns{display:flex;justify-content:flex-end;gap:8px;padding-top:12px;margin-top:8px;border-top:1px solid #3a3026;flex:none}
.pfe-save{color:var(--gold-hi);border-color:var(--gold)}
@media (max-width:500px){.pf-edit{max-width:100%;max-height:calc(100dvh - 24px)}.pfe-friends{grid-template-columns:repeat(3,1fr)}}

/* ==================== v136 (build 194): profile pills and gifts ====================
   A link to a page on this site (…/#u/Name) is drawn as a pill in the room, whispers and walls:
   avatar, name, "'s page ›". Tapping it opens the page here. */
.pf-pill{display:inline-flex;align-items:center;gap:5px;vertical-align:-3px;margin:1px 2px;padding:2px 9px 2px 3px;background:linear-gradient(180deg,#24190f,#0e0906);border:1px solid var(--gold-lo);border-radius:14px;color:var(--bone);font:12px "IM Fell English",Georgia,serif;cursor:pointer;line-height:1.3}
.pf-pill b{font:700 11px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold-hi)}
.pf-pill:hover,.pf-pill:focus-visible{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.4);outline:none}
.pf-pill-ava{width:18px;height:18px;border-radius:50%;object-fit:cover;display:inline-flex;align-items:center;justify-content:center;font:700 9px Cinzel,Georgia,serif;color:var(--gold);background:#000000;border:1px solid var(--gold-lo);overflow:hidden;flex:none}
.im .ilog .pf-pill{background:linear-gradient(180deg,#2c1e36,#110918);border-color:#7a4bb0}
.im .ilog .pf-pill b{color:#e2c4ff}

/* ==================== v137 (build 195): Home and the bell ====================
   Home is the same takeover as the Game Room; the bell is a small popover under its button. The
   two buttons go where the 8-ball goes: the title bar on desktop (right of the name, with the
   spool -- three glyphs a side now, so the title needs no spacer), the MENU pill on phones. */
.home-toggle-fab,.bell-toggle-fab{display:none;position:relative}
.fab-tray .home-toggle-fab.in-tray.ready,.fab-tray .bell-toggle-fab.in-tray.ready{display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;font-size:20px;line-height:1;
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
.bell-toggle-fab .rbadge{position:absolute;top:-4px;right:-4px;font-size:9px;padding:1px 5px;pointer-events:none}
.bell-toggle-fab.news{color:var(--gold-hi)}
@media (min-width:501px){
  .home-toggle-fab.in-header,.bell-toggle-fab.in-header{display:inline-flex;position:relative !important;top:auto !important;right:auto !important;left:auto !important;bottom:auto !important;transform:none !important;
  width:26px;height:auto;flex:none;align-items:center;justify-content:center;padding:0;border:none;border-radius:0;background:none;box-shadow:none;cursor:pointer;font-size:18px;line-height:1;opacity:.92;
  filter:drop-shadow(0 0 6px rgba(201,162,74,.45));transition:transform .15s ease,filter .15s ease,opacity .15s ease}
  .home-toggle-fab.in-header:hover,.bell-toggle-fab.in-header:hover,.home-toggle-fab.in-header:focus-visible,.bell-toggle-fab.in-header:focus-visible{opacity:1;outline:none;transform:translateY(-1px) scale(1.14) !important;filter:drop-shadow(0 0 11px rgba(201,162,74,.95))}
  .home-toggle-fab.in-header.open{filter:drop-shadow(0 0 10px rgba(201,162,74,.9))}
  .bell-toggle-fab.in-header .rbadge{top:-6px;right:-8px}
  /* balance: roulette / 8-ball / table on the left, spool / home / bell on the right -- no spacer */
  .win > .title.hb-pit.hb-gr.hb-left.hb-right.hb-home.hb-bell::after{content:none}
  .win > .title.hb-pit.hb-gr.hb-left.hb-right.hb-home:not(.hb-bell)::after{content:"";flex:none;width:26px}
}
.home-panel{display:none;flex-direction:column;background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8}
.gc-root.home-open .win{display:none}
.gc-root.home-open .home-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;height:100%;border-width:0;border-radius:0;z-index:40}
.gc-root.home-open .fab-tray,.gc-root.home-open .dm-dock,.gc-root.home-open .thread-toggle-fab,.gc-root.home-open .roulette-toggle-fab,.gc-root.home-open .gameroom-toggle-fab,.gc-root.home-open .pit-toggle-fab{display:none !important}
html.ios .gc-root.home-open .home-panel{padding-top:env(safe-area-inset-top);box-sizing:border-box}
.home-panel .tp-hd{position:relative}
.hm-filter{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:1px solid var(--gold-lo);border-radius:12px;color:var(--gold);font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;padding:3px 10px;cursor:pointer}
.hm-filter[aria-pressed="true"]{color:#1a1410;background:linear-gradient(180deg,var(--gold-hi),var(--gold));border-color:var(--gold)}
.hm-body{flex:1;min-height:0;overflow-y:auto;width:100%;max-width:760px;margin:0 auto;box-sizing:border-box;padding:8px 14px 24px;scrollbar-color:var(--gold-lo) #0f0d0b}
.hm-sec{margin-top:12px}
.hm-sec-hd{font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);padding-bottom:6px;border-bottom:1px solid #3a3026;margin-bottom:4px}
.hm-row{display:flex;gap:10px;align-items:flex-start;padding:8px 6px;border-bottom:1px solid #2a2119;cursor:pointer;border-radius:6px}
.hm-row:hover{background:rgba(201,162,74,.06)}
.hm-row.unread{background:rgba(201,162,74,.08);box-shadow:inset 3px 0 0 var(--gold)}
.hm-ava{width:30px;height:30px;border-radius:50%;flex:none;object-fit:cover;display:inline-flex;align-items:center;justify-content:center;font:700 13px Cinzel,Georgia,serif;color:var(--gold);background:#0a0602;border:1px solid var(--gold-lo);overflow:hidden}
.hm-txt{flex:1;min-width:0;font-size:14px;line-height:1.45;color:var(--bone);word-break:break-word}
.hm-txt b.who{color:var(--gold-hi);cursor:pointer;font:700 13px Cinzel,Georgia,serif}
.hm-txt .t{display:block;font:italic 11px "IM Fell English",Georgia,serif;color:#7a6d5a;margin-top:1px}
.hm-empty{padding:30px 10px;text-align:center;font:italic 13px "IM Fell English",Georgia,serif;color:var(--ash);line-height:1.6}
.bell-pop{position:fixed;z-index:62;width:min(360px,calc(100vw - 12px));max-height:min(70vh,520px);display:flex;flex-direction:column;background:linear-gradient(180deg,#24190f,#0e0906);border:2px double var(--gold-lo);outline:1px solid #000;border-radius:10px;box-shadow:0 0 0 1px #000,0 8px 24px #000}
.bell-pop.hidden{display:none}
.bell-hd{font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);padding:8px 12px 6px;border-bottom:1px solid #3a3026}
.bell-list{overflow-y:auto;padding:4px 8px 8px;scrollbar-color:var(--gold-lo) #0f0d0b}
.bell-list .hm-row{padding:7px 4px}
.bell-list .hm-txt{font-size:13px}
/* the profile banner: the accent bar is the band's bottom edge now, and the picture stops at it
   (it was showing through the double rule under the bar) */
.pf-band{background-clip:padding-box}
.profile-panel[style*="--pf-accent: #"] .pf-band{border-bottom:4px solid var(--pf-accent);box-shadow:inset 0 -30px 40px rgba(0,0,0,.5)}

/* ==================== v138 (build 196): the embedded player ==================== */
button.pf-song{cursor:pointer;font:12px "IM Fell English",Georgia,serif}
button.pf-song:hover{background:rgba(201,162,74,.18)}
.pf-song.hidden{display:none}
.pf-player{display:none;margin-top:8px}
.pf-player.on{display:block}
.pf-player iframe{width:100%;max-width:420px;border:1px solid var(--pf-line);border-radius:10px;background:#000000;display:block}
.pf-player-row{display:flex;align-items:center;gap:12px;margin-top:4px;font:12px "IM Fell English",Georgia,serif}
.pf-player-row a{color:var(--pf-gold)}
.pf-player-x{background:none;border:1px solid var(--pf-line);border-radius:10px;color:var(--pf-dim);font:11px Cinzel,Georgia,serif;padding:2px 9px;cursor:pointer}
.pf-player-x:hover{color:var(--pf-gold-hi);border-color:var(--pf-gold)}

/* ==================== v140 (build 198): the purse economy ==================== */
.hm-errands{margin-bottom:14px}
.hm-errands .er-count{float:right;font:600 11px Georgia,serif;letter-spacing:0;text-transform:none;color:var(--ash)}
.er-row{display:flex;align-items:center;gap:8px;padding:5px 2px;border-bottom:1px dashed #3a3026;font-size:14px}
.er-row:last-of-type{border-bottom:0}
.er-row.done{color:var(--ash)}
.er-row.done .er-title{text-decoration:line-through}
.er-tick{width:16px;text-align:center;color:var(--gold)}
.er-title{flex:1}
.er-prog{font-size:12px;color:var(--ash)}
.er-pay{font-size:12px;color:var(--gold);white-space:nowrap}
.er-note{font-size:11px;color:var(--ash);font-style:italic;margin-top:4px}
.pit-bowl .pb-bets{display:inline-flex;gap:8px;align-items:center;margin-left:6px}
.pit-bowl .pb-pools{font-size:12px;color:var(--ash)}
.pit-bowl .pb-mine{font-size:12px;color:var(--gold);font-style:italic}
.pit-bowl .pb-bet{padding:1px 7px}

/* ==================== v141 (build 199): Phase 3, photos ==================== */
.pf-ph-count{float:right;font:italic 12px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;color:var(--pf-dim)}
.pf-albums{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.pf-chip{font:12px "IM Fell English",Georgia,serif;color:var(--pf-ink);background:var(--pf-card);border:1px solid var(--pf-line);border-radius:14px;padding:3px 10px;cursor:pointer}
.pf-chip span{color:var(--pf-dim);font-size:11px}
.pf-chip.on{border-color:var(--pf-accent,var(--pf-gold));color:var(--pf-accent,var(--pf-gold));font-weight:700}
.pf-chip-new{border-style:dashed}
.pf-ph-tools{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px;align-items:center}
.pf-ph-tools .btn,.pf-add{height:28px;line-height:28px;display:inline-flex;align-items:center;font-size:11px;min-width:0}
.pf-add{cursor:pointer}
.pf-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}
@media (min-width:600px){.pf-grid{grid-template-columns:repeat(4,1fr)}}
.pf-th{position:relative;padding:0;border:1px solid var(--pf-line);border-radius:6px;overflow:hidden;background:var(--pf-card);cursor:pointer;aspect-ratio:1/1}
.pf-th img{width:100%;height:100%;object-fit:cover;display:block}
.pf-th-likes,.pf-th-today{position:absolute;right:4px;bottom:4px;font:11px Georgia,serif;color:#fff;background:rgba(0,0,0,.55);border-radius:10px;padding:1px 6px}
.pf-th-today{left:4px;right:auto;top:4px;bottom:auto;background:var(--pf-accent,#c9a24a);color:#111;font-weight:700}
.pf-lb{position:fixed;inset:0;z-index:59;background:rgba(0,0,0,.92);display:flex;flex-direction:column;color:#eee;outline:0}
.pf-lb-top{display:flex;align-items:center;gap:10px;padding:8px 12px;font:12px Georgia,serif;color:#bbb}
.pf-lb-owner{flex:1;text-align:center;color:#ddd}
.pf-lb-x{background:none;border:0;color:#ddd;font-size:20px;cursor:pointer;padding:2px 8px}
.pf-lb-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;position:relative}
.pf-lb-stage img{max-width:100%;max-height:100%;object-fit:contain}
.pf-lb-nav{position:absolute;top:50%;transform:translateY(-50%);background:rgba(0,0,0,.45);border:1px solid #444;color:#eee;font-size:30px;line-height:1;width:44px;height:64px;cursor:pointer;border-radius:6px}
.pf-lb-nav.prev{left:8px}.pf-lb-nav.next{right:8px}
.pf-lb-bar{padding:8px 12px 12px;display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between}
.pf-lb-cap{flex:1;min-width:200px;font:14px "IM Fell English",Georgia,serif}
.pf-lb-t{display:block;font-size:11px;color:#999;margin-top:2px}
.pf-lb-acts{display:flex;flex-wrap:wrap;gap:6px}
.pf-lb-acts .btn{height:28px;line-height:28px;font-size:11px;min-width:0;padding:0 10px;background:#110c08;border:1px solid #3a3026}
.pf-lb-acts .pf-like.on{color:#e0505a;border-color:#e0505a}
.hm-thumb{width:44px;height:44px;object-fit:cover;border-radius:6px;border:1px solid #3a3026;flex:none}

/* ==================== v142 (build 200): My page on phones, the picture from your page ==================== */
.fab-tray .mypage-toggle-fab.in-tray{display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;font-size:20px;line-height:1;overflow:hidden;
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
.mypage-toggle-fab .mp-ava{width:100%;height:100%;object-fit:cover;border-radius:inherit}
.pf-ava-btn{position:relative;padding:0;border:0;background:none;cursor:pointer;flex:none;border-radius:14px}
.pf-ava-cam{position:absolute;right:-4px;bottom:-4px;font-size:14px;background:var(--pf-card);border:1px solid var(--pf-gold);border-radius:50%;width:24px;height:24px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #000}

/* ==================== v143 (build 201): the Pictures board ==================== */
.tp-thumb-wrap{position:relative;display:block}
.tp-more{position:absolute;right:4px;top:4px;font:700 11px Georgia,serif;color:#fff;background:rgba(0,0,0,.6);border-radius:10px;padding:1px 6px;pointer-events:none}
.tp-photos{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:6px 0}
.tp-photo{position:relative;width:64px;height:64px;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000;overflow:hidden}
.tp-photo img{width:100%;height:100%;object-fit:cover;display:block}
.tp-photo .tp-img-remove{position:absolute;right:2px;top:2px}
.tp-photos-n{font:italic 11px "IM Fell English",Georgia,serif;color:var(--ash)}
.tp-pics{display:grid;gap:4px;margin-top:6px;max-width:520px}
.tp-pics.n1{grid-template-columns:1fr}
.tp-pics.n2,.tp-pics.n4{grid-template-columns:1fr 1fr}
.tp-pics.n3,.tp-pics.n5,.tp-pics.n6{grid-template-columns:repeat(3,1fr)}
.tp-pic{padding:0;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000;background:#000000;cursor:zoom-in;overflow:hidden;aspect-ratio:4/3}
.tp-pics.n1 .tp-pic{aspect-ratio:auto;max-height:420px}
.tp-pic img{width:100%;height:100%;object-fit:cover;display:block}
.tp-pics.n1 .tp-pic img{object-fit:contain}

/* ==================== v144 (build 202): captions before a photo goes up ==================== */
.ph-review-box{max-width:520px;max-height:90vh;display:flex;flex-direction:column}
.ph-review-list{overflow:auto;flex:1;min-height:0;margin:8px 0;display:flex;flex-direction:column;gap:8px}
.ph-rv{display:flex;gap:8px;align-items:center}
.ph-rv img{width:64px;height:64px;object-fit:cover;flex:none;border:1px solid var(--gold-lo);box-shadow:0 0 0 1px #000}
.ph-rv-r{flex:1;display:flex;gap:6px;align-items:center;min-width:0}
.ph-rv-cap{flex:1;min-width:0;height:32px}
.ph-rv-x{background:none;border:1px solid var(--gold-lo);color:var(--ash);border-radius:50%;width:26px;height:26px;cursor:pointer;flex:none}
.tp-photo-cap{position:absolute;left:0;right:0;bottom:0;font:10px Georgia,serif;color:#fff;background:rgba(0,0,0,.6);padding:1px 3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ==================== v145 (build 203): no XP figure on the card ==================== */
.nmenu .pc-xp .pc-purse{margin-left:4px}

/* ==================== v146 (build 204): the phone's ⚙ menu ==================== */
@media (max-width:500px){
  #statusPopover .avabtn{display:none !important}                       /* the picture is changed from your page */
  #statusPopover .cell .popover-label{font:14px "IM Fell English",Georgia,serif;color:var(--gold);letter-spacing:.2px}
  #statusPopover .cell{padding:8px 8px}
  .title-tools #statusPopover{min-width:240px}
  body:has(#statusPopover.open) .fab-tray{display:none}                 /* the MENU pill steps aside while the menu is open */
  #statusPopover .pop-hd{font-size:10px}
}

/* ==================== v147 (build 205): the page rearranged; like and comment in place ==================== */
.ph-review{color:var(--bone);font:14px "IM Fell English",Georgia,serif}
.ph-rv-cap,.ph-review input{color:var(--bone)}
.ph-rv-cap::placeholder{color:#8a7d6a}
.pf-cols{display:flex;flex-direction:column}
.pf-rail{order:-1}
.pf-main{min-width:0}
@media (min-width:900px){
  .pf-body{max-width:1040px}
  .pf-cols{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:0 8px;align-items:start}
  .pf-rail{order:0;position:sticky;top:0}
  .pf-rail .pf-stats{grid-template-columns:repeat(2,1fr)}
  .pf-rail .pf-tfs{grid-template-columns:repeat(2,1fr)}
}
.pf-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}
@media (min-width:600px){.pf-grid{grid-template-columns:repeat(3,1fr)}}
.pf-card{display:flex;flex-direction:column;background:var(--pf-card);border:1px solid var(--pf-line);border-radius:8px;overflow:hidden;min-width:0}
.pf-card .pf-th{border:0;border-radius:0;aspect-ratio:1/1}
.pf-card-r{padding:6px 8px 8px;display:flex;flex-direction:column;gap:4px;min-width:0}
.pf-card-cap{font:13px "IM Fell English",Georgia,serif;color:var(--pf-ink);line-height:1.3;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.pf-card-acts{display:flex;gap:6px}
.pf-ca{font:12px Georgia,serif;color:var(--pf-dim);background:none;border:1px solid var(--pf-line);border-radius:12px;padding:2px 9px;cursor:pointer}
.pf-ca.on{color:var(--pf-accent,var(--pf-gold));border-color:var(--pf-accent,var(--pf-gold))}
.pf-ca[data-plike].on{color:#e0505a;border-color:#e0505a}
.pf-card.open{grid-column:1/-1;flex-direction:row;align-items:flex-start}
.pf-card.open .pf-th{width:38%;flex:none;aspect-ratio:1/1;align-self:flex-start}
.pf-card.open .pf-card-r{flex:1}
.pf-card.open .pf-card-cap{-webkit-line-clamp:unset}
.pf-cmts{margin-top:6px;border-top:1px dashed var(--pf-line);padding-top:6px;display:flex;flex-direction:column;gap:5px;max-height:320px;overflow:auto}
.pf-cmt{font:13px "IM Fell English",Georgia,serif;color:var(--pf-ink);line-height:1.35}
.pf-cmt .who{cursor:pointer;color:var(--pf-gold)}
.pf-cmt-t{display:block;font-size:11px;color:var(--pf-dim)}
.pf-cmt-x{background:none;border:0;color:var(--pf-dim);font:inherit;cursor:pointer;padding:0;text-decoration:underline}
.pf-cmt-form{display:flex;gap:6px;margin-top:4px}
.pf-cmt-form input{flex:1;min-width:0;height:30px;color:var(--pf-ink)}
.pf-cmt-form .btn{height:30px;line-height:30px;min-width:0;padding:0 10px;font-size:11px}
@media (max-width:500px){.pf-card.open{flex-direction:column}.pf-card.open .pf-th{width:100%}}

/* ==================== v148 (build 206): crop before it goes up ==================== */
.ph-crop{color:var(--bone);font:14px "IM Fell English",Georgia,serif}
.ph-crop-box{max-width:540px;width:100%}
.ph-crop-shapes{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 8px}
.ph-crop-shapes .pf-chip{color:var(--bone);background:#110c08;border-color:var(--gold-lo)}
.ph-crop-shapes .pf-chip.on{color:var(--gold);border-color:var(--gold)}
.ph-crop-stage{display:flex;justify-content:center;margin:4px 0}
.ph-crop-cv{display:block;border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 0 0 9999px rgba(0,0,0,.35);cursor:grab;touch-action:none;max-width:100%}
.ph-crop-cv:active{cursor:grabbing}
.ph-crop-zoom{display:flex;align-items:center;gap:8px;margin:10px 0 2px;color:var(--gold)}
.ph-crop-zoom input{flex:1;accent-color:var(--gold)}
.ph-crop-hint{font-size:11px;color:var(--ash);text-align:center;margin-bottom:6px}
.ph-rv-crop{background:none;border:1px solid var(--gold-lo);color:var(--gold);border-radius:50%;width:26px;height:26px;cursor:pointer;flex:none}

/* ==================== v150 (build 208): Phase 4, events and notices ==================== */
.hap-panel{display:none;flex-direction:column;background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8}
.gc-root.hap-open .win{display:none}
.gc-root.hap-open .hap-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;height:100%;border-width:0;border-radius:0;z-index:40}
.gc-root.hap-open .fab-tray,.gc-root.hap-open .dm-dock,.gc-root.hap-open .thread-toggle-fab,.gc-root.hap-open .roulette-toggle-fab,.gc-root.hap-open .gameroom-toggle-fab,.gc-root.hap-open .pit-toggle-fab{display:none !important}
html.ios .gc-root.hap-open .hap-panel{padding-top:env(safe-area-inset-top);box-sizing:border-box}
.hap-toggle-fab{display:none;position:relative}
.fab-tray .hap-toggle-fab.in-tray.ready{display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;font-size:20px;line-height:1;
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
@media (min-width:501px){
  .hap-toggle-fab.in-header{display:inline-flex;position:relative !important;top:auto !important;right:auto !important;left:auto !important;bottom:auto !important;transform:none !important;
  width:26px;height:auto;flex:none;align-items:center;justify-content:center;padding:0;border:none;border-radius:0;background:none;box-shadow:none;cursor:pointer;font-size:18px;line-height:1;opacity:.92;
  filter:drop-shadow(0 0 6px rgba(201,162,74,.45));transition:transform .15s ease,filter .15s ease,opacity .15s ease}
  .hap-toggle-fab.in-header:hover,.hap-toggle-fab.in-header:focus-visible{opacity:1;outline:none;transform:translateY(-1px) scale(1.14) !important;filter:drop-shadow(0 0 11px rgba(201,162,74,.9))}
  .hap-toggle-fab.in-header.open{filter:drop-shadow(0 0 10px rgba(201,162,74,.9))}
  /* four glyphs on the right now: a 26px spacer on the left keeps the name centred */
  .win > .title.hb-pit.hb-gr.hb-left.hb-right.hb-home.hb-bell.hb-hap::before{content:"";flex:none;width:26px}
}
.hp-top{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;margin:4px 0 10px}
.hp-monthnav{display:flex;align-items:center;gap:6px}
.hp-month{font:700 15px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);min-width:150px;text-align:center}
.hp-nav{min-width:0;padding:0 10px;height:28px;line-height:28px;font-size:16px}
.hp-region{height:30px;color:var(--bone);font:13px "IM Fell English",Georgia,serif;padding:0 8px}
.hp-new{height:30px;line-height:30px;min-width:0;padding:0 12px}
.hp-cal{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;margin-bottom:12px}
.hp-dow{text-align:center;font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-lo);padding:2px 0}
.hp-day{position:relative;text-align:center;font:12px Georgia,serif;color:var(--ash);padding:6px 0;border:1px solid #2a2119;border-radius:4px;background:#0a0602}
.hp-day.empty{border-color:transparent;background:none}
.hp-day.today{color:var(--gold);border-color:var(--gold-lo)}
.hp-day.has{color:var(--bone);cursor:pointer}
.hp-day.has i{position:absolute;left:50%;bottom:3px;width:5px;height:5px;margin-left:-2px;border-radius:50%;background:var(--gold)}
.hp-card{display:flex;gap:10px;align-items:center;width:100%;text-align:left;padding:8px;margin-bottom:6px;background:linear-gradient(180deg,#170f09,#0c0703);border:1px solid #3a3026;border-radius:8px;color:var(--bone);cursor:pointer;font:inherit}
.hp-card:hover{border-color:var(--gold-lo)}
.hp-card.flash{border-color:var(--gold);box-shadow:0 0 10px rgba(201,162,74,.5)}
.hp-date{flex:none;width:44px;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#050100;border:1px solid var(--gold-lo);border-radius:6px;padding:4px 0}
.hp-date b{font:700 18px Cinzel,Georgia,serif;color:var(--gold);line-height:1}
.hp-date span{font:10px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:var(--ash)}
.hp-date.hp-nk{font-size:22px}
.hp-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.hp-title{font:700 15px "IM Fell English",Georgia,serif;color:var(--bone)}
.hp-sub{font-size:12px;color:var(--ash);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hp-mine{font-size:11px;color:#9ad19a}
.hp-thumb{width:56px;height:56px;object-fit:cover;border-radius:6px;border:1px solid #3a3026;flex:none}
.hp-cover{width:100%;max-height:260px;object-fit:cover;border-radius:8px;border:1px solid #3a3026;margin-bottom:10px}
.hp-head{margin-bottom:8px}
.hp-kind{font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold-lo)}
.hp-h2{font:700 22px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);margin:4px 0 6px}
.hp-when{font-size:14px;color:var(--bone);margin-top:2px}
.hp-hostline{font-size:13px;color:var(--ash);margin-top:6px}
.hp-hostline .who{color:var(--gold);cursor:pointer}
.hp-body{margin:8px 0 0}
.hp-rsvp{display:flex;flex-wrap:wrap;gap:6px;margin:12px 0}
.hp-rsvp .btn.on{color:#1a1410;background:linear-gradient(180deg,var(--gold-hi),var(--gold));border-color:var(--gold)}
.hp-rsvp .hp-clear{opacity:.8}
.hp-people .hp-person.maybe{opacity:.65}
.hp-host-tools{display:flex;gap:6px}
.hp-post{padding:6px 0;border-bottom:1px dashed #3a3026;font:14px "IM Fell English",Georgia,serif;color:var(--bone);line-height:1.4}
.hp-post .who{color:var(--gold);cursor:pointer}
.hp-post .pf-cmt-t{color:var(--ash)}
.hp-post .pf-cmt-x{color:var(--ash)}
.hp-form{max-width:460px;width:100%;max-height:92vh;overflow:auto}
.hp-form .pfe-lbl{display:block;margin:10px 0 3px}
.hp-form input.sunk,.hp-form select.sunk,.hp-form textarea.sunk{width:100%;box-sizing:border-box;color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:6px 8px}
.hp-form input[type=datetime-local]{color-scheme:dark}
.hp-kinds{display:flex;gap:6px;margin:6px 0 2px}
.hp-kinds .pf-chip{color:var(--bone);background:#110c08;border-color:var(--gold-lo)}
.hp-kinds .pf-chip.on{color:var(--gold);border-color:var(--gold)}
.hp-cover-row{display:flex;gap:8px;align-items:center;margin-top:10px}
.hp-cover-row .btn{min-width:0;height:28px;line-height:28px;font-size:11px}
.hap-panel{--pf-card:#1a1512;--pf-line:#3a3026;--pf-ink:var(--bone);--pf-gold:var(--gold);--pf-dim:var(--ash);--pf-accent:var(--gold)}
.hp-wall .pf-comp{display:flex;gap:6px;align-items:flex-end;margin-bottom:8px}
.hp-wall .pf-comp textarea{flex:1;min-width:0;background:linear-gradient(180deg,#050200,#0e0906);border:1px solid var(--gold-lo);color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:6px 8px;border-radius:4px;resize:vertical}
.hp-wall .pf-comp .btn{height:32px;line-height:32px;min-width:0;padding:0 12px}

/* ==================== v151 (build 209): Phase 5, circles ==================== */
.circ-panel{display:none;flex-direction:column;background:linear-gradient(180deg,var(--stone-2),var(--stone));overflow:hidden;z-index:8;
--pf-card:#1a1512;--pf-line:#3a3026;--pf-ink:var(--bone);--pf-gold:var(--gold);--pf-dim:var(--ash);--pf-accent:var(--gold)}
.gc-root.circ-open .win{display:none}
.gc-root.circ-open .circ-panel{display:flex !important;position:fixed;inset:0;width:100%;max-width:100%;height:100%;border-width:0;border-radius:0;z-index:40}
.gc-root.circ-open .fab-tray,.gc-root.circ-open .dm-dock,.gc-root.circ-open .thread-toggle-fab,.gc-root.circ-open .roulette-toggle-fab,.gc-root.circ-open .gameroom-toggle-fab,.gc-root.circ-open .pit-toggle-fab{display:none !important}
html.ios .gc-root.circ-open .circ-panel{padding-top:env(safe-area-inset-top);box-sizing:border-box}
.circ-toggle-fab{display:none;position:relative}
.fab-tray .circ-toggle-fab.in-tray.ready{display:flex;align-items:center;justify-content:center;padding:0;cursor:pointer;font-size:20px;line-height:1;
background:linear-gradient(160deg,#362b1f,#110c07 70%);border:2px solid var(--gold-lo);box-shadow:0 0 0 1px #000,0 4px 16px #000,0 0 10px rgba(201,162,74,.35)}
@media (min-width:501px){
  .circ-toggle-fab.in-header{display:inline-flex;position:relative !important;top:auto !important;right:auto !important;left:auto !important;bottom:auto !important;transform:none !important;
  width:26px;height:auto;flex:none;align-items:center;justify-content:center;padding:0;border:none;border-radius:0;background:none;box-shadow:none;cursor:pointer;font-size:18px;line-height:1;opacity:.92;
  filter:drop-shadow(0 0 6px rgba(201,162,74,.45));transition:transform .15s ease,filter .15s ease,opacity .15s ease}
  .circ-toggle-fab.in-header:hover,.circ-toggle-fab.in-header:focus-visible{opacity:1;outline:none;transform:translateY(-1px) scale(1.14) !important;filter:drop-shadow(0 0 11px rgba(201,162,74,.9))}
  .circ-toggle-fab.in-header.open{filter:drop-shadow(0 0 10px rgba(201,162,74,.9))}
  .win > .title.hb-pit.hb-gr.hb-left.hb-right.hb-home.hb-bell.hb-hap.hb-circ::before{content:"";flex:none;width:52px}
}
.cc-q{flex:1;min-width:140px;height:30px;color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:0 8px}
.cc-kinds{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.cc-kinds .pf-chip,.cc-tabs .pf-chip{color:var(--bone);background:#110c08;border-color:var(--gold-lo)}
.cc-kinds .pf-chip.on,.cc-tabs .pf-chip.on{color:var(--gold);border-color:var(--gold);font-weight:700}
.cc-card{display:flex;gap:10px;align-items:center;width:100%;text-align:left;padding:8px;margin-bottom:6px;background:linear-gradient(180deg,#170f09,#0c0703);border:1px solid #3a3026;border-radius:8px;color:var(--bone);cursor:pointer;font:inherit}
.cc-card:hover{border-color:var(--gold-lo)}
.cc-cover{flex:none;width:64px;height:48px;object-fit:cover;border-radius:6px;border:1px solid #3a3026}
.cc-glyph{display:flex;align-items:center;justify-content:center;font-size:24px;background:#050100}
.cc-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cc-name{font:700 15px "IM Fell English",Georgia,serif;color:var(--bone)}
.cc-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--gold);box-shadow:0 0 6px var(--gold);vertical-align:middle}
.cc-sub{font-size:12px;color:var(--ash)}
.cc-about{font-size:12px;color:var(--bone);opacity:.85;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.cc-req{font-size:11px;color:#e6b85c}
.cc-status{font-size:11px;color:#9ad19a}
.cc-inv{display:flex;flex-direction:column;gap:4px;margin-bottom:8px}
.cc-inv .cc-card{margin-bottom:0}
.cc-inv-acts{display:flex;gap:6px;margin-left:auto}
.cc-inv-acts .btn{height:26px;line-height:26px;min-width:0;padding:0 10px;font-size:11px}
.cc-join{color:#1a1410 !important;background:linear-gradient(180deg,var(--gold-hi),var(--gold)) !important;border-color:var(--gold) !important}
.cc-tabs{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 10px}
.cc-badge{display:inline-block;min-width:16px;padding:0 4px;border-radius:8px;background:#b33;color:#fff;font:700 10px Georgia,serif;text-align:center}
.cc-room{height:min(52vh,460px);overflow-y:auto;padding:6px 8px;background:#050100;border:1px solid #3a3026;border-radius:6px;line-height:1.45;font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.cc-line{padding:2px 0;word-wrap:break-word}
.cc-line .t{font-size:11px;color:var(--ash);margin-right:6px}
.cc-line .who{color:var(--gold);cursor:pointer}
.cc-x{opacity:0;transition:opacity .15s}
.cc-line:hover .cc-x{opacity:1}
@media (hover:none){.cc-x{opacity:.6}}
.cc-say{display:flex;gap:6px;margin-top:6px}
.cc-say input{flex:1;min-width:0;height:34px;color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:0 8px}
.cc-say .btn{height:34px;line-height:34px;min-width:0;padding:0 14px}
.circ-panel .pf-comp{display:flex;gap:6px;align-items:flex-end;margin-bottom:8px}
.circ-panel .pf-comp textarea{flex:1;min-width:0;background:linear-gradient(180deg,#050200,#0e0906);border:1px solid var(--gold-lo);color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:6px 8px;border-radius:4px;resize:vertical}
.circ-panel .pf-comp .btn{height:32px;line-height:32px;min-width:0;padding:0 12px}
.cc-reqrow{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:6px 0;border-bottom:1px dashed #3a3026;font-size:14px}
.cc-reqrow .who{color:var(--gold);cursor:pointer}
.cc-note{color:var(--ash);font-style:italic}
.cc-members{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:6px}
.cc-mem{display:flex;align-items:center;gap:6px;padding:5px 8px;background:#110c08;border:1px solid #3a3026;border-radius:6px;min-width:0}
.cc-mem .who{display:flex;align-items:center;gap:6px;min-width:0;flex:1;cursor:pointer;color:var(--bone);font-weight:400}
.cc-mem .nmt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cc-ava{width:28px;height:28px;border-radius:50%;flex:none;object-fit:cover;display:flex;align-items:center;justify-content:center;font:700 12px Cinzel,Georgia,serif;color:var(--gold);background:#050100;border:1px solid var(--gold-lo)}
.cc-role{font-size:10px;padding:0 5px;border-radius:8px;border:1px solid var(--gold-lo);color:var(--gold);white-space:nowrap}
.cc-role.own{background:rgba(201,162,74,.15)}
.cc-doors{display:flex;flex-direction:column;gap:6px}
.cc-door{display:flex;flex-direction:column;gap:2px;padding:7px 10px;border:1px solid #3a3026;border-radius:6px;background:#110c08;cursor:pointer;position:relative}
.cc-door input{position:absolute;opacity:0;pointer-events:none}
.cc-door b{font:700 13px "IM Fell English",Georgia,serif;color:var(--bone)}
.cc-door span{font-size:12px;color:var(--ash)}
.cc-door.on{border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.3)}
.cc-door.on b{color:var(--gold)}
.cc-cap{margin-top:8px}
.pf-circles{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-top:4px}
.pf-circ-lbl{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:var(--pf-dim,var(--ash))}
.pf-circ{font:12px "IM Fell English",Georgia,serif;color:var(--pf-ink,var(--bone));background:var(--pf-card,#110c08);border:1px solid var(--pf-line,#3a3026);border-radius:12px;padding:1px 8px;cursor:pointer}
.pf-circ:hover{border-color:var(--pf-gold,var(--gold))}

/* ==================== v152 (build 210): phone header bell, Pit page title, Pit visitors ==================== */
.title-tools .bell-toggle-fab{display:none}
@media (max-width:500px){
  .title-tools .bell-toggle-fab.in-title.ready{display:inline-flex;align-items:center;justify-content:center;position:relative;width:26px;height:26px;padding:0;font-size:14px;line-height:1;color:var(--ash);background:none;border:1px solid var(--gold-lo);border-radius:6px;cursor:pointer;box-shadow:none}
  .title-tools .bell-toggle-fab.in-title.news{color:var(--gold-hi);border-color:var(--gold)}
  .title-tools .bell-toggle-fab.in-title .rbadge{top:-6px;right:-7px}
  .gc-root.tools-up.signed-on .win > .title{padding-right:126px}
}
.gc-root.pit-open .pit-tank .pt-title{display:none}
.pt-line.visit b.who{color:#cdbb95}
.pt-line.visit b.who::after{content:" 👀";font-size:11px}

/* ==================== v153 (build 211): status colours everywhere ==================== */
.sdot{font-size:1.05em;line-height:1}
.sdot[data-status="online"],.statusbtn[data-status="online"] .btn-icon{color:#3fbf5a}
.sdot[data-status="away"],.statusbtn[data-status="away"] .btn-icon{color:#e8c33a}
.sdot[data-status="busy"],.statusbtn[data-status="busy"] .btn-icon{color:#e0453f}
.sdot[data-status="idle"],.statusbtn[data-status="idle"] .btn-icon{color:#8a929c}
.sdot-on{color:var(--gold-hi);font-size:.9em}
#statusPopover .pop-me .statusbtn[data-status="online"]{border-color:#2f5a34 !important}
#statusPopover .pop-me .statusbtn[data-status="away"]{border-color:#7a6424 !important}
#statusPopover .pop-me .statusbtn[data-status="busy"]{border-color:#7a2a2a !important}
.mebtn .me-sdot{position:absolute;left:50%;transform:translateX(-50%);bottom:1px;width:9px;height:9px;border-radius:50%;background:#8a929c;border:2px solid #120d09;pointer-events:none;display:none}
.mebtn[data-status] .me-sdot{display:block}
.mebtn[data-status="online"] .me-sdot{background:#3fbf5a}
.mebtn[data-status="away"] .me-sdot{background:#e8c33a}
.mebtn[data-status="busy"] .me-sdot{background:#e0453f}

/* ==================== v154 (build 212): circle events and photos ==================== */
.cc-tabs{flex-wrap:wrap}
.hp-circ-host{margin:4px 0 8px;font:italic 14px "IM Fell English",Georgia,serif;color:var(--bone)}
.hp-circ-host b{color:var(--gold-hi);font-style:normal}
.hp-seen{margin-bottom:6px}
.hp-seen .cc-door.off{opacity:.5;cursor:default}
.cc-albums{margin:6px 0}
.cc-phtools{margin:4px 0 6px}
.cc-phnote:empty{display:none}
.cc-grid{margin-top:6px}
.cc-lb .pf-lb-cap:empty{display:none}
.cc-lb .pf-lb-acts{display:flex;gap:8px;justify-content:center;padding:8px}
.cc-grid .pf-th{border:1px solid #3a3026;background:#110c08}

/* ==================== v155 (build 213): safer events and notices ==================== */
.hp-where-tip{font:italic 12px "IM Fell English",Georgia,serif;color:var(--ash);margin:3px 0 4px}
.hp-priv{display:flex;align-items:center;gap:6px;font:13px "IM Fell English",Georgia,serif;color:var(--bone);margin:2px 0 6px;cursor:pointer}
.hp-privnote{font:italic 12px "IM Fell English",Georgia,serif;color:var(--ash)}
.hp-told{font:italic 12px "IM Fell English",Georgia,serif;color:var(--ash);margin:4px 0 8px}
.hp-top .hp-report{margin-left:auto}
.hp-top .hp-report + .hp-host-tools{margin-left:6px}

/* v156 (build 214): who can see an event */
.hp-reach{margin-top:2px}

/* ==================== v157 (build 215): the purse at a glance ==================== */
.purse-chip .pc-amt{font-variant-numeric:tabular-nums;color:var(--gold-hi)}
.purse-chip.up{animation:purseUp 1.4s ease-out}
.purse-chip.down{animation:purseDown 1.4s ease-out}
@keyframes purseUp{0%{box-shadow:0 0 0 0 rgba(90,200,110,.0)}20%{box-shadow:0 0 12px 3px rgba(90,200,110,.8);border-color:#5ac86e}100%{box-shadow:0 0 0 0 rgba(90,200,110,0)}}
@keyframes purseDown{0%{box-shadow:0 0 0 0 rgba(224,69,63,0)}20%{box-shadow:0 0 12px 3px rgba(224,69,63,.8);border-color:#e0453f}100%{box-shadow:0 0 0 0 rgba(224,69,63,0)}}
.status .purse-chip{font:inherit;color:var(--ash);background:none;border:1px solid var(--gold-lo);cursor:pointer;flex:none}
@media (max-width:500px){
  .title-tools .purse-chip.in-title{display:inline-flex;align-items:center;gap:2px;width:auto !important;min-width:0;padding:0 6px !important;height:26px}
  .title-tools .purse-chip.in-title .popover-label{display:inline !important;font:700 12px Cinzel,Georgia,serif;letter-spacing:0}
  .title-tools .purse-chip.in-title .btn-icon{font-size:13px}
  .title-tools .purse-chip.in-title .pc-word{display:none}
  .gc-root.tools-up.signed-on .win > .title{padding-right:176px}
}
.purse-chip.hidden{display:none !important}
.gr-purse{margin:0 0 8px;font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.gr-purse b{color:var(--gold-hi)}
.gr-purse span{color:var(--ash);font-style:italic;font-size:12px}
.er-purse{float:right;font:italic 12px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;color:var(--gold)}

/* v159 (build 217): XP from the betting games */
.bet-xp{color:var(--leaf,#6fcf6f)}

/* ==================== v160 (build 218): Phase 6, the card redesigned ==================== */
.nmenu .pc-biorow{display:flex;gap:6px;align-items:stretch;margin:6px 10px 0}
.nmenu .pc-biorow .pc-bio{flex:1;min-width:0;margin:0}
.nmenu .pc-today{flex:none;width:58px;padding:0 !important;border:1px solid var(--gold-lo) !important;border-radius:3px;overflow:hidden;position:relative;background:#080200;cursor:pointer}
.nmenu .pc-today img{width:100%;height:100%;min-height:52px;max-height:66px;object-fit:cover;display:block}
.nmenu .pc-today span{position:absolute;left:0;right:0;bottom:0;font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;text-align:center;color:#111;background:rgba(201,162,74,.9);padding:1px 0}
.nmenu .pc-view{padding:6px 4px 2px}
.nmenu .pc-view .pc-viewbtn{text-align:center;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi);border:1px solid var(--gold-lo);background:rgba(201,162,74,.08)}
.nmenu .pc-secs{display:flex;flex-direction:column;gap:2px;padding:2px 0 2px}
.nmenu .pc-sec{border:1px solid #2a2119;border-radius:3px;background:rgba(0,0,0,.18)}
.nmenu .pc-sec.open{border-color:var(--gold-lo)}
.nmenu .pc-sec-hd{display:flex !important;align-items:center;justify-content:space-between;font:700 12px Cinzel,Georgia,serif !important;letter-spacing:1px;color:var(--bone) !important;padding:6px 8px !important}
.nmenu .pc-sec.open .pc-sec-hd{color:var(--gold-hi) !important}
.nmenu .pc-chev{font-style:normal;transition:transform .15s;color:var(--gold)}
.nmenu .pc-sec.open .pc-chev{transform:rotate(90deg)}
.nmenu .pc-sec-body{display:none !important;padding:0 2px 4px}
.nmenu .pc-sec.open .pc-sec-body{display:grid !important}

/* ==================== v161 (build 219): On the road ==================== */
.trv{margin-left:4px;font-size:12px;cursor:help}
.nmenu .pc-travel{color:var(--bone);font-size:12px}
.hm-travel .hm-sec-hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.hm-travel .hm-sec-hd select{margin-left:auto;height:26px;font-size:12px;padding:0 6px;max-width:170px}
.trv-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:5px 2px;border-bottom:1px dashed #2a2119;font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.trv-row .who{display:inline-flex;align-items:center;gap:5px;cursor:pointer;color:var(--gold-hi)}
.trv-note{color:var(--bone)}
.trv-lock{font-size:11px;opacity:.8}

/* ==================== v162 (build 220): the Marketplace ==================== */
.tp-price{width:150px;flex:0 1 150px}
.tp-listing-hint{font:italic 12px "IM Fell English",Georgia,serif;color:var(--gold);margin:2px 0 4px}
.tp-price-chip{display:inline-block;font:700 11px Cinzel,Georgia,serif;color:#111;background:var(--gold);border-radius:3px;padding:0 5px;letter-spacing:.5px}
.tp-price-chip.sold{background:#7a2a2a;color:#fff}
.tp-listings-chip{border-color:var(--gold) !important;color:var(--gold-hi) !important}
.mk-top{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:0 0 8px;grid-column:1/-1}
.mk-top .mk-q{flex:1 1 160px;min-width:0;height:30px}
.mk-top .mk-board{height:30px;max-width:180px}
.mk-sold{font:13px "IM Fell English",Georgia,serif;color:var(--bone);display:flex;align-items:center;gap:4px;cursor:pointer}
.mk-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px;grid-column:1/-1}
.mk-card{position:relative;display:flex;flex-direction:column;text-align:left;padding:0;border:1px solid #3a3026;border-radius:6px;overflow:hidden;background:#110c08;cursor:pointer;color:var(--bone);font:inherit}
.mk-card:hover{border-color:var(--gold)}
.mk-card img,.mk-card .mk-nopic{width:100%;aspect-ratio:1/1;object-fit:cover;display:flex;align-items:center;justify-content:center;font-size:34px;background:#080200}
.mk-card.sold img{filter:grayscale(.8) brightness(.6)}
.mk-stamp{position:absolute;top:10px;left:-4px;transform:rotate(-12deg);font:700 16px Cinzel,Georgia,serif;letter-spacing:3px;color:#fff;background:#b3261e;padding:2px 12px;box-shadow:0 2px 6px rgba(0,0,0,.6)}
.mk-price{font:700 14px Cinzel,Georgia,serif;color:var(--gold-hi);padding:5px 7px 0}
.mk-body{font:13px "IM Fell English",Georgia,serif;padding:2px 7px;line-height:1.3;max-height:34px;overflow:hidden}
.mk-meta{font:italic 11px "IM Fell English",Georgia,serif;color:var(--ash);padding:2px 7px 6px}
.mk-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:6px 0;padding:6px 10px;border:1px solid var(--gold-lo);border-radius:4px;background:rgba(201,162,74,.08);font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.mk-bar b{font:700 15px Cinzel,Georgia,serif;color:var(--gold-hi)}
.mk-bar .mk-open{font-style:italic;color:var(--leaf,#6fcf6f);font-size:12px}
.mk-stamp-sm{font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;color:#fff;background:#b3261e;padding:1px 6px;border-radius:2px}
.mk-bar .mk-toggle{margin-left:auto;height:26px;line-height:26px;font-size:11px;min-width:0;padding:0 10px}
.tp-items .mk-top,.tp-items .mk-grid{flex:0 0 100%;width:100%}
.tp-price,.mk-top .mk-q{color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:4px 8px;outline:none}
.tp-price::placeholder,.mk-top .mk-q::placeholder{color:#7a6d5a}
@media (max-width:500px){.mk-grid{grid-template-columns:repeat(2,1fr)}}

/* ==================== v163 (build 221): Rituals, part one ==================== */
.nmenu .pc-bday{color:var(--gold-hi);font-size:12px}
.hm-qotd .qd-q{font:italic 17px/1.35 "IM Fell English",Georgia,serif;color:var(--gold-hi);margin:4px 2px 8px}
.qd-form{display:flex;gap:6px;margin-bottom:8px}
.qd-form input{flex:1;min-width:0;color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:5px 8px;outline:none}
.qd-list{display:flex;flex-direction:column;gap:4px}
.qd-a{font:14px "IM Fell English",Georgia,serif;color:var(--bone);padding:3px 2px;border-bottom:1px dashed #2a2119}
.qd-a .who{color:var(--gold-hi);cursor:pointer}
.qd-queue{display:flex;flex-direction:column;gap:4px;margin:8px 0;max-height:40vh;overflow:auto}
.qd-qrow{display:flex;gap:8px;align-items:baseline;font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.qd-day{flex:none;width:70px;font-size:12px;color:var(--gold)}
.qd-qbody{flex:1}
.hm-qotd .sys-act,.hm-sunday .sys-act{display:inline-block;margin:6px 0 0;padding:3px 10px;font:12px "IM Fell English",Georgia,serif;color:var(--gold-hi);background:none;border:1px solid var(--gold-lo);border-radius:12px;cursor:pointer;width:auto}
.hm-qotd .hm-sec-hd .sys-act{margin:0 0 0 8px;padding:1px 8px;font-size:11px;letter-spacing:0;text-transform:none}

/* ==================== v164 (build 222): Rituals, part two -- the Sunday board ==================== */
.sun-top{margin:4px 0 10px;padding:10px 12px;border:1px solid var(--gold-lo);border-radius:4px;background:rgba(201,162,74,.07);font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.sun-hd{font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);margin-bottom:4px}
.sun-title{font-style:italic;color:var(--gold-hi);margin-bottom:6px;line-height:1.35}
.sun-refs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}
.sun-ref{display:inline-block;padding:2px 8px;border:1px solid var(--gold-lo);border-radius:12px;color:var(--gold-hi);text-decoration:none;font:14px "IM Fell English",Georgia,serif}
.sun-ref:hover,.sun-ref:focus-visible{background:rgba(201,162,74,.18);outline:none}
.sun-src{font-size:11px;color:var(--gold);opacity:.8}
.sun-how{margin-top:6px;font-size:13px}
.sun-chip{display:inline-block;font:700 11px Cinzel,Georgia,serif;color:var(--gold-hi);border:1px solid var(--gold-lo);border-radius:3px;padding:0 4px}
.sun-chip.mine{background:var(--gold);color:#111}
.sun-praybar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:6px 0;padding:6px 10px;border:1px solid var(--gold-lo);border-radius:4px;background:rgba(201,162,74,.08);font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.sun-praylbl{font:700 13px Cinzel,Georgia,serif;color:var(--gold-hi)}
.sun-praycount{font-style:italic}
.sun-pray{margin-left:auto;height:26px;line-height:26px;font-size:11px;min-width:0;padding:0 10px}
.sun-pray.on{background:var(--gold);color:#111}
.hm-sunday .sun-refs{margin-top:4px}
.hm-sunday .sun-ref{font-size:13px}

/* ==================== v166 (build 224): small fixes ==================== */
.pf-pill-t{white-space:nowrap}

/* ==================== v167 (build 225): one way back ==================== */
/* every full page has a ← bar; the threads board's floating 💬 and the Pit's pill are gone */
.gc-root.mobile-threads-open #threadToggleBtn{display:none !important}
.pit-tank .pt-hd{display:none}
.gc-root.pit-open .pit-tank .pt-hd{display:flex;order:0;width:100%;box-sizing:border-box;position:relative;z-index:3}
html.ios .gc-root.pit-open .pit-tank .pt-hd{padding-top:calc(env(safe-area-inset-top) + 8px)}
.gc-root.pit-open .pit-tank .pt-back{display:none !important}
/* the Messages pill shrinks to its envelope (and badge) in the corner while a full page is open */
/* build 309: except the Game Room, which keeps the same pill as the chat -- same size, same label,
   where it was parked -- at the owner's request (mock-up A over B). It was also the one page where
   the shrink was measured snapping 140px to 39px in a frame (csslint's one real finding). */
.gc-root:is(.home-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.pit-open,.profile-open,.mobile-threads-open,.mobile-roulette-open) .dm-dock.collapsed{width:auto !important;max-width:none;left:auto !important;top:auto !important;right:8px !important;bottom:8px !important;opacity:.9}
.gc-root:is(.home-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.pit-open,.profile-open,.mobile-threads-open,.mobile-roulette-open) .dm-dock.collapsed :is(.dm-bar-title,.dm-bar-chev){display:none}
.gc-root:is(.home-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.pit-open,.profile-open,.mobile-threads-open,.mobile-roulette-open) .dm-dock.collapsed .dm-bar{padding:8px 10px}

/* ==================== v168 (build 226): a tray that fits ==================== */
/* Roulette isn't built yet: its button leaves the phone tray and the desktop header (its desktop column goes in 228). */
#rouletteToggleBtn{display:none !important}
/* build 350: back in the header on computers, on the left after Games (its "coming soon" page has its own Back to chat).
   From 760px (the frame at full size) only: narrower, the extra button wraps the site's name onto two lines (header 57 -> 65px). */
@media (min-width:760px){
  #rouletteToggleBtn.in-header.ready{display:inline-flex !important}
  /* build 350b: it joins the left group (Home, Threads, Games, Roulette) instead of sitting by the lantern, the left
     spacer that made up for the shorter left group goes, and the buttons sit 6px apart (were 12): with all nine buttons
     the name wrapped to two or three lines on a full-size computer screen. */
  .win > .title.hb-pit.hb-gr.hb-left.hb-right.hb-home.hb-bell.hb-hap.hb-circ::before{content:none}
  .win > .title{column-gap:6px}
}
/* One order everywhere, Home first: Home, Threads, Game Room, then Pit, Happenings, Circles (and the bell on desktop).
   CSS order, so every place*Btn() that moves a button about keeps working untouched. */
#fabItems > #homeBtn{order:1} #fabItems > #threadToggleBtn{order:2} #fabItems > #gameRoomBtn{order:3}
#fabItems > #pitBtn{order:4} #fabItems > #hapBtn{order:5} #fabItems > #circBtn{order:6}
.win > .title > #homeBtn{order:-3} .win > .title > #threadToggleBtn{order:-2} .win > .title > #gameRoomBtn{order:-1}
.win > .title > #pitBtn{order:1} .win > .title > #hapBtn{order:2} .win > .title > #circBtn{order:3} .win > .title > #bellBtn{order:4} .win > .title > #titleTools{order:5}
/* six icons fit a phone: the open tray drops the word MENU from its knob and takes the room back */
@media (max-width:500px){
  .fab-tray:not(.collapsed) .ft-lbl{display:none}
  .fab-tray:not(.collapsed) .ft-items{max-width:calc(100vw - 64px)}
}

/* ==================== v169 (build 227): one place for you ==================== */
/* your card holds page, picture, status, name, region, on the road and save-with-email; ⋯ is Settings only */
#statusPopover [data-card-only]{display:none !important}
#popMe #st,#popMe #statusBtn{display:none !important}
#popMe #meBtn{display:flex;align-items:center;gap:8px;width:100%}
#popMe #meBtn .popover-label::after{content:" — your card ›"}
/* Messages off is a quiet state, not an error: dimmed, no strike, no red */
.status .dmbtn[aria-pressed="true"]{color:var(--ash);border-color:var(--gold-lo);text-decoration:none;opacity:.6}
.status .dmbtn[aria-pressed="true"] .popover-label{text-decoration:none}

/* ==================== v170 (build 228): the desktop Today column ==================== */
/* build 318: not in the phone's full-screen Roulette page -- this rule is for the desktop column, which the Today
   box took over; on a phone it left that page showing only the Popularity Contest, once More made the page reachable */
.gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel > :is(.rp-eyebrow,.rp-title,.rp-rule,.rp-blurb,.rp-wheel,.rp-hint,.rp-fortune,.rp-back){display:none !important}
.gc-root:not(.signed-on) .td-box{display:none}
.td-box{width:100%;text-align:left;font:14px "IM Fell English",Georgia,serif;color:var(--bone);overflow-y:auto;min-height:0;flex:0 1 auto}
.td-hd{font:700 12px Cinzel,Georgia,serif;letter-spacing:3px;text-transform:uppercase;color:var(--gold);text-align:center}
.td-date{text-align:center;font-style:italic;color:var(--gold-hi);margin:2px 0 8px}
.td-sec{padding:8px 0;border-top:1px solid #2a2119}
.td-sh{font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);margin-bottom:4px}
.td-box .sun-title{font-size:13px}
.td-box .sun-refs{gap:4px}
.td-box .sun-ref{font-size:12px;padding:1px 6px}
.td-q{font-style:italic;color:var(--gold-hi);line-height:1.35}
.td-mine{font-size:13px;margin-top:3px}
.td-who{color:var(--gold-hi);cursor:pointer}
.td-hap{font-size:13px;margin:2px 0}
.td-box .sys-act{display:inline-block;margin:6px 0 0;padding:2px 10px;font:12px "IM Fell English",Georgia,serif;color:var(--gold-hi);background:none;border:1px solid var(--gold-lo);border-radius:12px;cursor:pointer}
/* Build 228 took the desktop tank out of the gutter when the Today column went in, and build 257 put it
   back: it was asked after, it sits clear under the Ballot Box at every width from 1340px up (measured
   1094-1354 against the Ballot Box's 6-447 at 1400px), and the gutter has the room. The rule that hid it
   is left here, disabled, so the next person can see it was a decision and not an accident. */
/* .gc-root:not(.pit-open) .pit-tank{display:none !important} */

/* ==================== v171 (build 229): Threads, the Contest and the Game Room ==================== */
/* Threads: board chips on a desktop; one Board picker on a phone, and the tags on one scrolling row */
.tp-boardpick{display:none}
.tp-list > .tp-hd .tp-sub{position:absolute;right:10px;top:50%;transform:translateY(-50%)}
.tp-list > .tp-hd{position:relative}
@media (max-width:500px){
  .tp-boards .tp-board{display:none}
  .tp-boardpick{display:flex;align-items:center;gap:8px;width:100%;font:700 10px Cinzel,Georgia,serif;letter-spacing:1.5px;text-transform:uppercase;color:var(--gold)}
  .tp-boardpick select{flex:1;min-width:0;color:var(--bone);font:14px "IM Fell English",Georgia,serif;padding:5px 8px}
  .tp-tags{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .tp-tags::-webkit-scrollbar{display:none}
  .tp-tags .tp-tag{flex:none}
  .tp-list > .tp-hd .tp-sub{right:6px;padding:3px 6px;font-size:9px}
  .tp-list > .tp-hd #tpBoardName{max-width:calc(100% - 180px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
/* the Popularity Contest: People, then Games */
.lb-grp{flex:0 0 100%;font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);text-align:center;margin-top:4px}
@media (max-width:500px){.lb-tabs .adm-tab{flex-basis:28%}}
/* the Game Room: the one-on-one games */
.gr-duel-list{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 6px}
.gr-duel-list span{padding:3px 10px;border:1px solid var(--gold-lo);border-radius:12px;font:13px "IM Fell English",Georgia,serif;color:var(--gold-hi)}
.gr-duel-s{font:italic 13px "IM Fell English",Georgia,serif;color:var(--bone);opacity:.85}

/* ==================== v172 (build 230): Badges ==================== */
.pc-badges{display:flex;flex-wrap:wrap;gap:4px}
.pc-badge{background:none;border:1px solid var(--gold-lo);border-radius:12px;padding:0 6px;font-size:14px;line-height:20px;cursor:pointer}
.pc-badge:hover,.pc-badge:focus-visible{border-color:var(--gold);outline:none}
.pf-badges.hidden{display:none}
.pf-badge{display:flex;gap:8px;align-items:flex-start;padding:4px 0;font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.pf-badge b{color:var(--gold-hi)}
.pf-badge-i{font-size:20px;line-height:1.2;flex:none}
.pf-badge-d{font-size:12px;opacity:.8;font-style:italic}
.nmenu .pc-line.pc-badges{display:flex;flex-wrap:wrap;gap:4px;margin:3px 0}
.nmenu .pc-badges .pc-badge{display:inline-flex;align-items:center;justify-content:center;width:auto;min-width:0;margin:0;padding:1px 7px;font-size:14px;line-height:20px;border:1px solid var(--gold-lo);border-radius:12px;background:none;text-align:center}

/* ==================== v173 (build 231): Reports → Errors ==================== */
.err-row .err-more{font-size:11px;color:var(--ash)}
.err-row .err-more summary{cursor:pointer;color:var(--gold)}
.err-row .err-more pre{white-space:pre-wrap;word-break:break-word;font:11px/1.4 ui-monospace,Menlo,Consolas,monospace;max-height:200px;overflow:auto;margin:6px 0}

/* ==================== v174 (build 233): save-with-email nudges ==================== */
.nmenu .me-save{margin:6px 8px 2px;padding:6px 8px;border:1px solid #8a5a2a;border-radius:4px;background:rgba(160,90,30,.12);font:13px "IM Fell English",Georgia,serif;color:var(--bone);line-height:1.4}
.nmenu .me-save .sys-act{display:inline-block;width:auto;margin:4px 0 0;padding:2px 10px;font:12px "IM Fell English",Georgia,serif;color:var(--gold-hi);background:none;border:1px solid var(--gold-lo);border-radius:12px;cursor:pointer}
.hm-save{border:1px solid #8a5a2a;border-radius:4px;background:rgba(160,90,30,.10);padding:8px 10px}
.hm-save-t{font:14px "IM Fell English",Georgia,serif;color:var(--bone);margin-bottom:4px}
.hm-save .sys-act{display:inline-block;margin:6px 4px 0 0;padding:3px 10px;font:12px "IM Fell English",Georgia,serif;color:var(--gold-hi);background:none;border:1px solid var(--gold-lo);border-radius:12px;cursor:pointer;width:auto}
.hm-save .hm-save-later{color:var(--ash)}

/* ==================== v175 (build 234): a modern layout for Events, Circles and Threads ====================
   The user, 20 Sept: "modern, same soul" -- the gold-on-dark palette and the serif headings stay; lists become
   cards in a feed (one column on a phone, two or three on a desktop), with rounded corners, room to breathe, a
   photo on top when there is one, pill buttons and bigger tap targets. The single event, circle and thread get the
   same treatment. Everything here is scoped to those three pages; nothing in the room changes. */
.hap-panel,.circ-panel,.threads-panel{--m-card:linear-gradient(180deg,#231b15,#17120e);--m-line:rgba(201,162,74,.24);--m-line-hi:rgba(201,162,74,.55);--m-soft:rgba(255,240,210,.04);--m-r:14px;--m-shadow:0 6px 18px rgba(0,0,0,.35)}
/* the page body: wider on a desktop, so the cards can sit side by side */
.hap-panel .hm-body,.circ-panel .hm-body{max-width:1040px;padding:12px 16px 32px}
/* section headings */
.hap-panel .hm-sec-hd,.circ-panel .hm-sec-hd{border-bottom:none;padding-bottom:2px;margin-bottom:8px;font-size:12px;letter-spacing:2.5px}
/* pill buttons and chips */
.hap-panel .btn,.circ-panel .btn,.threads-panel .tp-newactions .btn,.threads-panel .tp-composebar .btn{border-radius:999px;padding:0 16px;min-height:34px;line-height:32px}
.hap-panel .pf-chip,.circ-panel .pf-chip{border-radius:999px;padding:5px 12px}
.hap-panel .sunk,.circ-panel .sunk,.threads-panel .tp-sel{border-radius:10px}
.hap-panel .hp-top,.circ-panel .hp-top{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px}
.circ-panel .cc-q{flex:1 1 220px;min-width:0;border-radius:999px;padding:8px 14px}

/* ---- the feeds: cards, one column on a phone, a grid on a desktop ---- */
.hap-panel .hm-sec,.circ-panel .hm-sec{display:grid;grid-template-columns:1fr;gap:12px}
@media (min-width:760px){.hap-panel .hm-sec,.circ-panel .hm-sec{grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}}
.hap-panel .hm-sec > :is(.hm-sec-hd,.pf-empty-sm,.cc-kinds),.circ-panel .hm-sec > :is(.hm-sec-hd,.pf-empty-sm,.cc-kinds){grid-column:1/-1}
.hap-panel .hp-card,.circ-panel .cc-card{margin:0;padding:12px;border:1px solid var(--m-line);border-radius:var(--m-r);background:var(--m-card);box-shadow:var(--m-shadow);transition:transform .15s ease,border-color .15s ease,box-shadow .15s ease;align-items:flex-start;height:100%;box-sizing:border-box}
.hap-panel .hp-card:hover,.circ-panel .cc-card:hover,.hap-panel .hp-card:focus-visible,.circ-panel .cc-card:focus-visible{transform:translateY(-2px);border-color:var(--m-line-hi);box-shadow:0 10px 24px rgba(0,0,0,.45);outline:none}
/* an event card: the photo across the top, then the date badge beside the title */
.hap-panel .hp-card{display:grid;grid-template-columns:auto 1fr;gap:10px 12px}
.hap-panel .hp-card .hp-thumb{grid-row:1;grid-column:1/-1;width:100%;height:150px;border-radius:10px;border:none}
.hap-panel .hp-date{border-radius:12px;min-width:48px;padding:6px 4px;background:rgba(201,162,74,.10);border:1px solid var(--m-line)}
.hap-panel .hp-title,.circ-panel .cc-name{font-size:17px;line-height:1.25}
.hap-panel .hp-sub,.circ-panel .cc-sub{line-height:1.45}
.hap-panel .hp-mine{display:inline-block;margin-top:6px;padding:1px 10px;border-radius:999px;background:rgba(111,207,111,.12);border:1px solid rgba(111,207,111,.35)}
/* a circle card: its cover across the top when it has one; otherwise the kind's glyph in a round badge */
.circ-panel .cc-card{display:flex;gap:12px}
.circ-panel .cc-card:has(img.cc-cover){display:grid;grid-template-columns:1fr}
.circ-panel .cc-card img.cc-cover{width:100%;height:130px;border-radius:10px;border:none}
.circ-panel .cc-glyph{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;background:rgba(201,162,74,.10);border:1px solid var(--m-line)}
.circ-panel .cc-status{display:inline-block;margin-top:6px;padding:1px 10px;border-radius:999px;border:1px solid var(--m-line)}
.circ-panel .cc-inv{display:grid;gap:8px}

/* ---- the calendar ---- */
.hap-panel .hp-cal{gap:6px}
.hap-panel .hp-day{border-radius:10px;border-color:var(--m-line)}
.hap-panel .hp-day.today{box-shadow:0 0 0 2px var(--gold) inset}
.hap-panel .hp-monthnav .hp-nav{min-width:34px;padding:0}

/* ---- one event, one circle ---- */
.hap-panel .hp-cover,.circ-panel .hp-cover{border-radius:18px;border:none;max-height:300px;box-shadow:var(--m-shadow)}
.hap-panel .hp-head,.circ-panel .hp-head{margin:6px 0 10px}
.hap-panel .hp-kind,.circ-panel .hp-kind{display:inline-block;padding:2px 10px;border-radius:999px;border:1px solid var(--m-line);background:var(--m-soft)}
.hap-panel .hp-h2,.circ-panel .hp-h2{font-size:26px;line-height:1.2;margin:8px 0 6px}
.hap-panel .hp-when{padding:8px 12px;margin:6px 0;border-radius:12px;background:var(--m-soft);border:1px solid var(--m-line)}
.hap-panel .hp-body,.circ-panel .hp-body{border-radius:var(--m-r);border-color:var(--m-line);background:var(--m-soft)}
.hap-panel .hp-rsvp,.circ-panel .hp-rsvp{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}
.hap-panel .hp-rsvp .btn{min-height:40px;padding:0 20px;font-size:14px}
.hap-panel .hp-rsvp .btn.on{background:linear-gradient(180deg,#e0bd62,#b8923e);color:#16110c;border-color:#e0bd62}
.hap-panel .pf-sec,.circ-panel .pf-sec{margin-top:16px;padding:12px;border-radius:var(--m-r);border:1px solid var(--m-line);background:var(--m-card)}
.hap-panel .pf-sec-hd,.circ-panel .pf-sec-hd{border-bottom:none}
.hap-panel .hp-post,.circ-panel .hp-post{padding:8px 12px;margin:8px 0;border-radius:12px;background:var(--m-soft);border:1px solid rgba(201,162,74,.12)}
.hap-panel .pf-comp textarea,.circ-panel .pf-comp textarea{border-radius:12px}
.circ-panel .cc-tabs{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;padding:2px 0 8px;margin-top:6px}
.circ-panel .cc-tabs::-webkit-scrollbar{display:none}
.circ-panel .cc-tabs .pf-chip{flex:none}
.circ-panel .cc-members{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}
.circ-panel .cc-mem{padding:8px 10px;border-radius:12px;background:var(--m-soft);border:1px solid rgba(201,162,74,.12)}
.circ-panel .cc-room{border-radius:var(--m-r);border-color:var(--m-line)}

/* ---- Threads: the catalog as a feed of cards ---- */
.threads-panel .tp-items{display:grid;grid-template-columns:1fr;gap:12px;padding:12px 14px 24px;align-content:start;justify-content:stretch;max-width:1100px;margin:0 auto;width:100%;box-sizing:border-box}
@media (min-width:640px){.threads-panel .tp-items{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}}
.threads-panel .tp-items > :is(.tp-empty,.sun-top,.mk-top,.mk-grid){grid-column:1/-1}
.threads-panel .tp-item{width:auto;padding:12px;border:1px solid var(--m-line);border-radius:var(--m-r);background:var(--m-card);box-shadow:var(--m-shadow);transition:transform .15s ease,border-color .15s ease}
.threads-panel .tp-item:hover,.threads-panel .tp-item:focus-visible{transform:translateY(-2px);border-color:var(--m-line-hi);outline:none}
.threads-panel .tp-item .tp-thumb{height:170px;border-radius:10px;border:none;box-shadow:none;margin-bottom:8px}
.threads-panel .tp-item .tp-thumb-wrap{margin-bottom:0}
.threads-panel .tp-item .tp-op{font-size:13px;margin-bottom:2px}
.threads-panel .tp-item .tp-preview{font-size:15px;line-height:1.4;margin:2px 0 8px}
.threads-panel .tp-item .tp-meta{margin-top:auto;display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px}
.threads-panel .tp-chip,.threads-panel .tp-price-chip{border-radius:999px;padding:1px 8px}
.threads-panel .tp-newwrap{max-width:1100px;margin:0 auto;width:100%;box-sizing:border-box;padding:0 14px}
/* ---- one thread: each post a soft card, the opening post picked out ---- */
.threads-panel .tp-posts{padding:10px 14px}
.threads-panel .tp-posts .tp-post{padding:10px 12px;margin:0 auto 10px;max-width:760px;border-radius:var(--m-r);background:var(--m-soft);border:1px solid rgba(201,162,74,.14);line-height:1.5}
.threads-panel .tp-posts .tp-post.op{background:var(--m-card);border-color:var(--m-line-hi);box-shadow:var(--m-shadow)}
.threads-panel .tp-posts .tp-post > .t{display:block;font-size:11px;opacity:.7;margin-bottom:2px}
.threads-panel .tp-posts :is(.mk-bar,.sun-praybar){max-width:760px;margin-left:auto;margin-right:auto;border-radius:12px}
.threads-panel .tp-reply textarea,.threads-panel #tpReplyBody,.threads-panel #tpNewBody{border-radius:12px}
/* the Messages envelope sits above a thread's reply box, not on its Reply button */
.gc-root.thread-open .dm-dock.collapsed{bottom:74px !important}
@media (prefers-reduced-motion:reduce){.hap-panel .hp-card,.circ-panel .cc-card,.threads-panel .tp-item{transition:none}}
/* v175 polish: cards keep their own height (no tall empty boxes beside a photo card); chips hug their text;
   one event or circle reads at a comfortable width; the board and tag rows line up with the cards */
.hap-panel .hm-sec,.circ-panel .hm-sec,.threads-panel .tp-items{align-items:start}
.hap-panel .hp-card,.circ-panel .cc-card{height:auto}
.hap-panel .hp-mine,.circ-panel .cc-status,.circ-panel .cc-req{width:fit-content;align-self:flex-start;justify-self:start}
.hap-panel .hm-body:has(.hp-h2),.circ-panel .hm-body:has(.hp-h2){max-width:820px}
.threads-panel .tp-boards,.threads-panel .tp-tagrow{max-width:1100px;margin-left:auto;margin-right:auto;width:100%;box-sizing:border-box}
.gc-root.thread-open .dm-dock.collapsed{bottom:128px !important}

/* ==================== build 235: board tabs in the Messages colours; Sunday in sanguine ==================== */
/* the user, 20 Sept: "make these tabs the same colorway as the PMs, except Sunday's -- make that one sanguine" */
.tp-board{color:#e2c4ff;background:linear-gradient(180deg,#1f1526,#0a050e);border-color:#4a3560;border-radius:4px;text-shadow:0 1px 0 #000}
.tp-board:hover,.tp-board:focus-visible{color:#fff;border-color:#9a6bd0;outline:none} /* text: option D of five tried -- the Messages title lilac, 11.4:1 */
.tp-board.active{color:#e2c4ff;border-color:#9a6bd0;background:linear-gradient(180deg,#2c1e36,#110918);
text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000;box-shadow:inset 0 0 8px rgba(160,110,230,.3),0 0 6px rgba(122,75,176,.35)}
.tp-board[data-board="sunday"]{color:#f6e3de;background:linear-gradient(180deg,#280a0a,#0e0000);border-color:#6e2320}
.tp-board[data-board="sunday"]:hover,.tp-board[data-board="sunday"]:focus-visible{color:#fff;border-color:#b3261e}
.tp-board[data-board="sunday"].active{color:#ffe1dc;border-color:#c8342a;background:linear-gradient(180deg,#4d1a17,#1c0000);
text-shadow:0 0 8px rgba(230,90,70,.55),0 1px 0 #000;box-shadow:inset 0 0 8px rgba(200,50,40,.35),0 0 6px rgba(179,38,30,.4)}

/* ==================== build 236: square calendar days ==================== */
/* the user, 20 Sept: "make these calendar days square, not rectangular". Square cells at 7 across would be huge on
   a desktop, so the calendar is capped at 560px and centred (about 74px a day); on a phone a day is about 48px. */
.hap-panel .hp-cal{max-width:560px;margin-left:auto;margin-right:auto}
.hap-panel .hp-day{aspect-ratio:1/1;padding:0;display:flex;align-items:center;justify-content:center;font-size:14px}
.hap-panel .hp-day.has i{bottom:14%}
.hap-panel .hp-day.empty{border-color:transparent;background:none;box-shadow:none}

/* ==================== build 237: calendar colours ==================== */
/* the user picked from six mock-ups, 20 Sept: the calendar in the Messages purple, + New in sanguine, the month
   arrows in ember copper. Days with events are bright and bold with a glowing dot; today has a glowing ring. */
.hap-panel .hp-day:not(.empty){background:linear-gradient(180deg,#1f1526,#0a050e);border-color:#4a3560;color:#b99ad8}
.hap-panel .hp-day.has{color:#e2c4ff;font-weight:700}
.hap-panel .hp-day.has i{background:#9a6bd0;box-shadow:0 0 6px rgba(160,110,230,.45)}
.hap-panel .hp-day.today{border-color:#9a6bd0;box-shadow:0 0 0 2px #9a6bd0 inset,0 0 10px rgba(160,110,230,.45);color:#e2c4ff}
.hap-panel .hp-day.has:hover{border-color:#9a6bd0;color:#fff}
.hap-panel .hp-dow{color:#b99ad8;opacity:.8}
.hap-panel .hp-month{color:#e2c4ff;text-shadow:0 0 8px rgba(200,150,255,.4)}
.hap-panel .hp-nav{background:linear-gradient(180deg,#5a3212,#1d0900);border-color:#e08a2c;color:#fff0dd;box-shadow:0 0 8px rgba(224,138,44,.45);text-shadow:0 1px 0 #000}
.hap-panel .hp-nav:hover{border-color:#f0a24a;color:#fff}
.hap-panel .hp-new{background:linear-gradient(180deg,#5a1d19,#1f0000);border-color:#c8342a;color:#ffe1dc;box-shadow:0 0 8px rgba(200,50,40,.45);text-shadow:0 1px 0 #000}
.hap-panel .hp-new:hover{border-color:#e0453a;color:#fff}

/* ==================== build 238: Circles in the same colours as the calendar ==================== */
/* purple for the chips (kind filters on the list, the tabs on a circle), sanguine for the action that makes
   something (＋ Start a circle, Join / Ask to join / Accept invitation), ember copper for the way back (‹ All circles) */
.circ-panel .pf-chip{background:linear-gradient(180deg,#1f1526,#0a050e);border-color:#4a3560;color:#b99ad8}
.circ-panel .pf-chip:hover,.circ-panel .pf-chip:focus-visible{border-color:#9a6bd0;color:#e2c4ff;outline:none}
.circ-panel .pf-chip.on{background:linear-gradient(180deg,#2c1e36,#110918);border-color:#9a6bd0;color:#e2c4ff;
text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000;box-shadow:inset 0 0 8px rgba(160,110,230,.3),0 0 6px rgba(122,75,176,.35)}
.circ-panel .pf-chip .cc-badge{background:#c8342a;color:#fff}
.circ-panel #circNew,.circ-panel .cc-join{background:linear-gradient(180deg,#5a1d19,#1f0000);border-color:#c8342a;color:#ffe1dc;box-shadow:0 0 8px rgba(200,50,40,.45);text-shadow:0 1px 0 #000}
.circ-panel #circNew:hover,.circ-panel .cc-join:hover{border-color:#e0453a;color:#fff}
.circ-panel [data-circback]{background:linear-gradient(180deg,#5a3212,#1d0900);border-color:#e08a2c;color:#fff0dd;box-shadow:0 0 8px rgba(224,138,44,.45);text-shadow:0 1px 0 #000}
.circ-panel [data-circback]:hover{border-color:#f0a24a;color:#fff}

/* ==================== build 239: a single event in the Circles colours ==================== */
/* ember copper for the way back (‹ Calendar), sanguine for the actions (Going / Maybe, Post on the wall, Delete),
   purple for the quieter tools and labels (the kind pill, Edit, Report, the people who are coming) */
.hap-panel [data-hapback]{background:linear-gradient(180deg,#5a3212,#1d0900);border-color:#e08a2c;color:#fff0dd;box-shadow:0 0 8px rgba(224,138,44,.45);text-shadow:0 1px 0 #000}
.hap-panel [data-hapback]:hover{border-color:#f0a24a;color:#fff}
.hap-panel .hp-kind{background:linear-gradient(180deg,#1f1526,#0a050e);border-color:#4a3560;color:#b99ad8}
.hap-panel [data-hapedit],.hap-panel .hp-report{background:linear-gradient(180deg,#1f1526,#0a050e);border-color:#4a3560;color:#b99ad8}
.hap-panel [data-hapedit]:hover,.hap-panel .hp-report:hover{border-color:#9a6bd0;color:#e2c4ff}
.hap-panel .hp-person{background:linear-gradient(180deg,#1f1526,#0a050e);border-color:#4a3560;color:#e2c4ff}
.hap-panel .hp-rsvp [data-rsvp="going"],.hap-panel .hp-rsvp [data-rsvp="maybe"],.hap-panel .hp-wall button[type=submit],.hap-panel [data-hapdel]{background:linear-gradient(180deg,#5a1d19,#1f0000);border-color:#c8342a;color:#ffe1dc;box-shadow:0 0 8px rgba(200,50,40,.45);text-shadow:0 1px 0 #000}
.hap-panel .hp-rsvp [data-rsvp="going"]:hover,.hap-panel .hp-rsvp [data-rsvp="maybe"]:hover,.hap-panel .hp-wall button[type=submit]:hover,.hap-panel [data-hapdel]:hover{border-color:#e0453a;color:#fff}
.hap-panel .hp-rsvp .btn.on{background:linear-gradient(180deg,#a8322a,#5a1d19);border-color:#ff6a5c;color:#fff;box-shadow:0 0 12px rgba(230,70,55,.6),inset 0 0 8px rgba(255,120,100,.3)}
.hap-panel .hp-wall textarea:focus{border-color:#9a6bd0;outline:none;box-shadow:0 0 6px rgba(160,110,230,.35)}

/* ==================== build 240: page headers, mock-up A ==================== */
/* The user picked A of six mock-ups, 20 Sept: every page header except the main chat's gets the ember copper
   back pill (the same one as ‹ Calendar and ‹ All circles, labelled ‹ Chat, or ‹ Threads inside a thread),
   a brighter gold title, and a soft gold rule under the bar. On a desktop the pill sits at the left edge and
   equal padding on both sides keeps the title dead centre; on a phone the pill stays in the row and the title
   centres in the space that is left, so a long name gets as much room as it can. */
.tp-hd{position:relative;min-height:52px;padding:8px 124px;gap:9px;
background:linear-gradient(180deg,#241910,#0d0806);border-bottom:1px solid var(--gold-lo);box-shadow:0 1px 0 #000,0 6px 14px rgba(0,0,0,.45);
font:700 16px Cinzel,Georgia,serif;letter-spacing:2px;color:var(--gold-hi);text-shadow:0 0 10px rgba(241,217,138,.45),0 1px 0 #000}
.tp-hd::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;pointer-events:none;
background:linear-gradient(90deg,transparent,var(--gold-hi),transparent);opacity:.7}
.tp-hd > span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tp-hd .tp-back{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:auto;height:32px;line-height:30px;padding:0 14px;
border-radius:999px;border:1px solid #e08a2c;background:linear-gradient(180deg,#5a3212,#1d0900);color:#fff0dd;
font:700 12px Cinzel,Georgia,serif;letter-spacing:1.2px;white-space:nowrap;box-shadow:0 0 8px rgba(224,138,44,.45);text-shadow:0 1px 0 #000}
.tp-hd .tp-back:hover,.tp-hd .tp-back:focus-visible{border-color:#f0a24a;color:#fff;outline:none;box-shadow:0 0 12px rgba(240,162,74,.6)}
/* the thread title is a quoted first line and can be long: let it take two lines instead of cutting it short */
.tp-detail .tp-hd > span{white-space:normal;text-align:center;line-height:1.3}
.tp-detail .tp-hd{padding-right:124px}
.tp-detail .tp-hd .tp-share{position:absolute;right:12px;top:50%;transform:translateY(-50%)}
@media (max-width:500px){
  .tp-hd{padding:8px 10px;gap:8px;font-size:14px;letter-spacing:1.5px}
  .tp-hd .tp-back{position:static;transform:none;flex:none;height:30px;line-height:28px;padding:0 11px;font-size:11px;letter-spacing:1px}
  .tp-hd > span{flex:1 1 auto;text-align:center;justify-content:center}
  .tp-hd > .tp-back + span{margin-right:0}
  .home-panel .tp-hd{padding-right:104px}
  .profile-panel .tp-hd{padding-right:48px}
  .tp-list > .tp-hd{padding-right:78px}
  .tp-list > .tp-hd #tpBoardName{max-width:none}
  .tp-detail .tp-hd{padding-right:10px}
  .tp-detail .tp-hd .tp-share{position:static;transform:none;flex:none}
  .tp-detail .tp-hd > span{font-size:13px}
}
/* the small icon buttons on the right of a header (🔗 copy a profile link, ➦ send a thread) become round
   copper-edged buttons to sit with the pill instead of the old square boxes */
.tp-hd .tp-share,.tp-hd .pf-share{width:32px;height:32px;line-height:30px;padding:0;border-radius:50%;border:1px solid rgba(224,138,44,.6);
background:rgba(224,138,44,.08);color:#f0a24a;font-size:14px;text-align:center}
.tp-hd .tp-share:hover,.tp-hd .tp-share:focus-visible,.tp-hd .pf-share:hover,.tp-hd .pf-share:focus-visible{border-color:#f0a24a;color:#fff0dd;background:rgba(224,138,44,.18);outline:none}

/* ==================== build 241: the colourway on every other page ==================== */
/* Same three colours as the calendar, Circles and an event page, now on Threads, Home, the Game Room,
   the Contest (and the Reports tabs, which share its tab class) and Profile:
   purple  = something you pick or a label (tags, tabs, the Everyone filter, Notify me, game names)
   sanguine = the thing that makes or sends something (Create new post, Reply, Post, Wave, Gift, Quick seat)
   ember copper = a way to somewhere else (the Listings chip, today's readings, the Sunday board) */
.tp-tag,.hm-filter,.tp-sub,.adm-tab,.gr-duel-list > span,.tp-img,.pf-act[data-act="whisper"],.pf-act[data-act="edit"],.pf-act[data-act="picture"],.pf-act[data-act="unfriend"],.pf-act[data-act="unblock"],.pf-song{
background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;border-radius:999px !important;text-shadow:0 1px 0 #000}
.tp-tag:hover,.hm-filter:hover,.tp-sub:hover,.adm-tab:hover,.tp-img:hover,.pf-act[data-act="whisper"]:hover,.pf-song:hover,
.tp-tag:focus-visible,.hm-filter:focus-visible,.tp-sub:focus-visible,.adm-tab:focus-visible,.tp-img:focus-visible{border-color:#9a6bd0 !important;color:#e2c4ff !important;outline:none}
.tp-tag.active,.hm-filter[aria-pressed="true"],.tp-sub.on,.adm-tab.active{background:linear-gradient(180deg,#2c1e36,#110918) !important;border-color:#9a6bd0 !important;color:#e2c4ff !important;
text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000;box-shadow:inset 0 0 8px rgba(160,110,230,.3),0 0 6px rgba(122,75,176,.35)}
.adm-tab{padding:6px 14px !important;margin:0 2px}
.gr-duel-list > span{padding:3px 12px}
#tpNewBtn.tp-new,#tpReplySend,.pf-act[data-act="wave"],.pf-act[data-act="gift"],.pf-act[data-act="friend"],.pf-act[data-act="add"],.pf-wall button[type=submit],.pf-comp button[type=submit],
.gr-quickseat,.gr-sit,#ballotCast{background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;color:#ffe1dc !important;border-radius:999px !important;
box-shadow:0 0 8px rgba(200,50,40,.45) !important;text-shadow:0 1px 0 #000}
#tpNewBtn.tp-new:hover,#tpReplySend:hover,.pf-act[data-act="wave"]:hover,.pf-act[data-act="gift"]:hover,.pf-act[data-act="friend"]:hover,.pf-act[data-act="add"]:hover,
.pf-wall button[type=submit]:hover,.pf-comp button[type=submit]:hover,.gr-quickseat:hover,.gr-sit:hover,#ballotCast:hover{border-color:#e0453a !important;color:#fff !important}
#tpNewBtn.tp-new{padding:0 18px 0 14px;height:36px;gap:8px}
#tpNewBtn .tp-new-gem{display:none}
#tpNewBtn .tp-new-label{color:inherit !important;font:700 12px Cinzel,Georgia,serif;letter-spacing:1.2px}
#tpNewBtn .tp-new-label::before{content:"＋ "}
#tpReplySend{padding:0 18px;min-height:32px}
.tp-listings-chip,.sun-ref,.sys-act{background:linear-gradient(180deg,#5a3212,#1d0900) !important;border:1px solid #e08a2c !important;color:#fff0dd !important;border-radius:999px !important;
box-shadow:0 0 6px rgba(224,138,44,.4);text-shadow:0 1px 0 #000}
.tp-listings-chip:hover,.sun-ref:hover,.sys-act:hover{border-color:#f0a24a !important;color:#fff !important}
.pf-act{border-radius:999px !important}
.pf-act.pf-danger{background:linear-gradient(180deg,#240a0a,#0c0000) !important;border:1px solid #7a2a2a !important;color:#e07a7a !important}
#tpReplyBody{border-color:#4a3560 !important;box-shadow:none !important}
#tpReplyBody:focus{border-color:#9a6bd0 !important;box-shadow:0 0 8px rgba(160,110,230,.35) !important;outline:none}

/* ==================== build 241: pages open and close with a little motion ==================== */
/* A page fades in and rises 12px as it opens (the animation runs each time its display flips on). Pressing the
   copper back pill plays the reverse -- a slide to the right and a fade -- before the page actually closes;
   app.js adds .gc-leaving for 170ms and then lets the click through. Nothing moves for someone whose phone or
   computer is set to reduce motion. */
@keyframes gcPageIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes gcPageOut{from{opacity:1;transform:none}to{opacity:0;transform:translateX(28px)}}
.gc-root.hap-open .hap-panel,.gc-root.circ-open .circ-panel,.gc-root.home-open .home-panel,.gc-root.profile-open .profile-panel,
.gc-root.gameroom-open .gameroom-panel,.gc-root.leaderboard-open .leaderboard-panel,.gc-root.admin-open .admin-panel,
.gc-root.mobile-threads-open .threads-panel,.gc-root.pit-open .pit-tank,.tp-detail:not(.hidden){animation:gcPageIn .24s cubic-bezier(.2,.7,.3,1)}
.gc-leaving{animation:gcPageOut .17s ease-in forwards !important;pointer-events:none}
@media (prefers-reduced-motion:reduce){
  .gc-root.hap-open .hap-panel,.gc-root.circ-open .circ-panel,.gc-root.home-open .home-panel,.gc-root.profile-open .profile-panel,
  .gc-root.gameroom-open .gameroom-panel,.gc-root.leaderboard-open .leaderboard-panel,.gc-root.admin-open .admin-panel,
  .gc-root.mobile-threads-open .threads-panel,.gc-root.pit-open .pit-tank,.tp-detail:not(.hidden),.gc-leaving{animation:none !important}
}

/* ==================== build 241: candlelight after sunset ==================== */
/* app.js works out the viewer's own sunset and sunrise (from their clock's time zone, no location asked) and puts
   .gc-night on <html> between them. At night the gold runs warmer, the page headers and the chat title catch a
   faint candle flicker, and a low amber glow sits at the top of the screen. The flicker stops for reduced motion. */
html.gc-night{--gold:#cf9852;--gold-hi:#edc99e;--gold-lo:#714d20}
html.gc-night body::before{content:"";position:fixed;inset:0;pointer-events:none;z-index:1;
background:radial-gradient(120% 60% at 50% -10%,rgba(255,150,60,.10),transparent 60%)}
@keyframes gcCandle{0%,100%{opacity:1}22%{opacity:.86}47%{opacity:.97}63%{opacity:.82}81%{opacity:.95}}
@keyframes gcCandleGlow{0%,100%{text-shadow:0 0 10px rgba(255,190,110,.55),0 1px 0 #000}30%{text-shadow:0 0 14px rgba(255,170,80,.7),0 1px 0 #000}
60%{text-shadow:0 0 8px rgba(255,200,130,.45),0 1px 0 #000}}
html.gc-night .tp-hd::after{background:linear-gradient(90deg,transparent,#ffc070,transparent);animation:gcCandle 3.8s ease-in-out infinite}
html.gc-night .tp-hd > span,html.gc-night .win > .title{animation:gcCandleGlow 4.6s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){html.gc-night .tp-hd::after,html.gc-night .tp-hd > span,html.gc-night .win > .title{animation:none}}

/* ==================== build 242: reactions on the walls ==================== */
/* Pills sit under a wall post the same way they sit under a thread reply; holding a post (or right-clicking it)
   builds the same gold wash while the finger is down. The Reply button in the picker only belongs to room lines. */
.pf-post,.hp-post[data-rpost]{-webkit-touch-callout:none}
.pf-post.pressing,.hp-post[data-rpost].pressing{background:rgba(201,162,74,.14);transition:background-color .45s linear}
.pf-post .reactions:not(:empty),.hp-post .reactions:not(:empty){margin-top:5px}
.rpicker .rp-reply[hidden]{display:none}

/* ==================== build 242: voice notes -- hold to record, and a track to play along ==================== */
.icomp .mic{touch-action:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.icomp .mic.holding{transform:scale(1.12);transition:transform .12s}
.icomp .mic.cancelling{opacity:.55;filter:grayscale(.6)}
.vn-bar.cancelling{background:linear-gradient(180deg,#240a0a,#0c0000)}
.vn-bar.cancelling .vn-dot{background:#666;animation:none}
.vn-track{position:relative;width:88px;height:6px;flex:none;border-radius:3px;background:#110818;border:1px solid #4a3560;cursor:pointer}
.vn-track::before{content:"";position:absolute;inset:-8px 0}   /* a taller target than it looks */
.vn-track i{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:3px;background:linear-gradient(90deg,#7a4bb0,#c89bff);box-shadow:0 0 6px rgba(200,155,255,.5)}
.vn.playing .vn-len{color:#e2c4ff}
@media (max-width:500px){.vn-track{width:70px}}

/* ==================== build 243: main chat in the colourway (mock-up B) ==================== */
/* The user picked B of three, 20 Sept. The square gold frame stays -- it is the most 2000 thing on the site --
   and the controls and panes take the same colours as every other page:
   sanguine  Send (the thing that sends)
   purple    😊 and GIF, the bottom toolbar, the reply box's edge; the Online / Friends headers wear the
             whisper windows' purple bar, and the chat log and online list get a purple edge
   copper    the phone's MENU knob and the "someone's page ›" pill in the log (both take you somewhere) */
#send{background:linear-gradient(180deg,#5a1d19,#1f0000)!important;border:1px solid #c8342a!important;color:#ffe1dc!important;border-radius:14px!important;
box-shadow:0 0 10px rgba(200,50,40,.5)!important;text-shadow:0 1px 0 #000}
#send:hover,#send:focus-visible{border-color:#e0453a!important;color:#fff!important;outline:none}
#emoBtn,#gifBtn{background:linear-gradient(180deg,#1f1526,#0a050e)!important;border:1px solid #4a3560!important;color:#b99ad8!important;border-radius:14px!important}
#emoBtn:hover,#gifBtn:hover,#emoBtn:focus-visible,#gifBtn:focus-visible{border-color:#9a6bd0!important;color:#e2c4ff!important;outline:none}
#msg{border-color:#4a3560!important}
#msg:focus{border-color:#9a6bd0!important;box-shadow:0 0 8px rgba(160,110,230,.35)!important;outline:none}
.status{background:linear-gradient(180deg,#170f1a,#08030a)!important}
.status button.cell{background:linear-gradient(180deg,#1f1526,#0a050e)!important;border:1px solid #4a3560!important;color:#b99ad8!important;border-radius:12px!important}
.status button.cell:hover,.status button.cell:focus-visible{border-color:#9a6bd0!important;color:#e2c4ff!important;outline:none}
.users .hd{background:linear-gradient(180deg,#2c1e36,#110918)!important;border-bottom:2px solid #7a4bb0!important;color:#e2c4ff!important;text-shadow:0 0 8px rgba(200,150,255,.45),0 1px 0 #000}
.users,#log.log{border:1px solid #6a4a8c!important;box-shadow:inset 0 0 18px rgba(122,75,176,.12)!important}
.ft-knob{background:linear-gradient(180deg,#5a3212,#1d0900)!important;border-color:#e08a2c!important;color:#fff0dd!important;box-shadow:0 0 10px rgba(224,138,44,.5)!important}
#log .pf-pill{border-color:#e08a2c!important;color:#fff0dd!important;background:linear-gradient(180deg,#5a3212,#1d0900)!important}

/* ==================== build 244: On the road by place and length ==================== */
.trv-lens{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 4px}
.trv-lens .pf-chip{border-radius:999px;padding:5px 12px;cursor:pointer;font:700 11px Cinzel,Georgia,serif;letter-spacing:.8px;
background:linear-gradient(180deg,#1f1526,#0a050e);border:1px solid #4a3560;color:#b99ad8}
.trv-lens .pf-chip:hover,.trv-lens .pf-chip:focus-visible{border-color:#9a6bd0;color:#e2c4ff;outline:none}
.trv-lens .pf-chip.on{background:linear-gradient(180deg,#2c1e36,#110918);border-color:#9a6bd0;color:#e2c4ff;
text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000;box-shadow:inset 0 0 8px rgba(160,110,230,.3),0 0 6px rgba(122,75,176,.35)}
.trv-preview{margin:10px 0 2px;min-height:18px;font:italic 14px "IM Fell English",Georgia,serif;color:#e8dcc4}
#travelForm #trvOk{background:linear-gradient(180deg,#5a1d19,#1f0000);border-color:#c8342a;color:#ffe1dc;box-shadow:0 0 8px rgba(200,50,40,.45)}
#travelForm #trvHome{background:linear-gradient(180deg,#5a3212,#1d0900);border-color:#e08a2c;color:#fff0dd}
#travelForm select optgroup{font-style:normal;color:#b99ad8}

/* ==================== build 245: regions v2 -- threads by state ==================== */
.tp-place-chip{display:inline-block;font:italic 11px "IM Fell English",Georgia,serif;color:#e0b98a;letter-spacing:.2px}
.tp-statesel{height:26px;padding:0 8px;font-size:12px;border-radius:999px;border:1px solid #e08a2c !important;color:#fff0dd;
background:linear-gradient(180deg,#5a3212,#1d0900);max-width:190px;flex:none}
.tp-newmeta .tp-place{max-width:170px}
.tp-newmeta select.tp-place{min-width:130px}
@media (max-width:500px){.tp-newmeta .tp-place{max-width:none;flex:1 1 40%}}

/* ==================== build 246: the Threads page, reorganised ==================== */
.tpx-body{flex:1;min-height:0;display:grid;grid-template-columns:250px minmax(0,1fr);gap:20px;width:100%;max-width:1260px;margin:0 auto;padding:16px 18px;box-sizing:border-box;overflow:hidden}
.tpx-side{overflow-y:auto;align-self:stretch;background:linear-gradient(180deg,#1a110a,#0c0702);border:1px solid rgba(201,162,74,.22);border-radius:14px;padding:8px 6px;scrollbar-color:var(--gold-lo) #0f0d0b}
.tpx-main{display:flex;flex-direction:column;min-width:0;min-height:0}
.tpx-boards{display:block;padding:0}
.tpx-sec{font:700 10px Cinzel,Georgia,serif;letter-spacing:2.2px;color:#8f7446;text-transform:uppercase;margin:12px 10px 6px}
.tpx-sec:first-child{margin-top:2px}
.tpx-bd{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border-radius:9px;border:1px solid transparent;background:none;color:#cbbfa7;cursor:pointer;text-align:left;font:14px "IM Fell English",Georgia,serif}
.tpx-bd:hover{border-color:rgba(201,162,74,.3);color:var(--bone)}
.tpx-ic{width:18px;flex:none;text-align:center}
.tpx-nm{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tpx-fl{font-size:11px}
.tpx-dot{width:7px;height:7px;border-radius:50%;background:#e0453a;box-shadow:0 0 6px rgba(224,69,58,.7);flex:none}
.tpx-n{margin-left:auto;font:700 10px Cinzel,Georgia,serif;color:#7d705c}
.tpx-bd.on{background:linear-gradient(180deg,#2c1e36,#110918);border-color:#9a6bd0;color:#e2c4ff;text-shadow:0 0 8px rgba(200,150,255,.45);box-shadow:inset 0 0 8px rgba(160,110,230,.25)}
.tpx-bd.on .tpx-n{color:#e2c4ff}
.tpx-bbtn{display:none}
.tpx-line{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 2px 12px;flex:none}
.tpx-line h2{margin:0;font:700 22px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold-hi);text-shadow:0 0 10px rgba(241,217,138,.35)}
.tpx-note{color:var(--ash);font-style:italic;font-size:14px}
.tpx-grow{flex:1}
.tp-tagrow{flex:none}
.tp-list .tp-tags{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;padding:8px 10px;border:1px solid rgba(201,162,74,.18);border-radius:12px;background:rgba(255,240,210,.03);margin-bottom:12px}
.tpx-lbl{font:700 9px Cinzel,Georgia,serif;letter-spacing:2px;color:#8f7446;text-transform:uppercase;flex:none}
/* build 255: they wrap now. The mask and overflow:hidden meant the row was simply cut off at the
   right -- on a computer that lost the last couple of topics, and on a phone it lost all ten, because
   the box had no width left to draw them in. */
.tpx-chips{display:flex;gap:6px;flex-wrap:wrap;row-gap:5px;flex:1 1 auto;min-width:0}
.tpx-topicsel{display:none}
.tpx-vsep{width:1px;align-self:stretch;background:rgba(201,162,74,.2);flex:none}
.tpx-sortsel{flex:none;height:28px;border-radius:999px;padding:0 8px;font-size:12px;border:1px solid #4a3560 !important;background:linear-gradient(180deg,#1f1526,#0a050e);color:#b99ad8;max-width:150px}
.tp-list .tp-statesel{flex:none}
.tp-items{padding:0;justify-content:flex-start;display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:14px;align-content:start;overflow-y:auto;flex:1}
.tpx-tile{position:relative;width:auto;display:flex;flex-direction:column;gap:5px;padding:12px 14px;border-radius:14px;border:1px solid rgba(201,162,74,.24);background:linear-gradient(180deg,#1c120c,#0e0803);box-shadow:0 6px 18px rgba(0,0,0,.35);text-align:left}
.tpx-tile:hover{border-color:rgba(201,162,74,.5)}
.tpx-new{position:absolute;top:10px;right:10px;width:9px;height:9px;border-radius:50%;background:#e0453a;box-shadow:0 0 8px rgba(224,69,58,.8)}
.tpx-pic{display:block;position:relative;height:120px;border-radius:10px;overflow:hidden;margin-bottom:2px}
.tpx-pic img{width:100%;height:100%;object-fit:cover;display:block}
.tpx-top{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--ash);min-width:0}
.tpx-ava{width:24px;height:24px;flex:none}
.tpx-who{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold-hi);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tpx-who.admin{color:#ff9b9b}
.tpx-bchip{margin-left:auto;padding:1px 8px;border-radius:999px;border:1px solid rgba(201,162,74,.35);font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);text-transform:uppercase;white-space:nowrap}
.tpx-h{font:700 16px "IM Fell English",Georgia,serif;color:#f4e9d2;line-height:1.25}
.tpx-p{color:#b7aa92;font-size:14px;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tpx-foot2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;color:#8f836c;margin-top:2px}
.tpx-when{white-space:nowrap}
.tpx-fade{margin-left:auto;font-style:italic;color:#c98a6a;white-space:nowrap}
.tpx-foot{flex:none;margin:12px 0 2px;text-align:center;font-style:italic;font-size:13px;color:#7d705c}
/* the new-thread form as its own panel */
.gc-root.tpx-new-open .tp-newpost{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:60;width:min(680px,94vw);max-height:86vh;overflow-y:auto;
background:linear-gradient(180deg,#1d120d,#0c0702);border:1px solid var(--gold-lo);border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.7);padding:14px}
.gc-root.tpx-new-open::before{content:"";position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:59}
/* the phone: one Board button and a sheet */
@media (max-width:860px){
  .tpx-body{grid-template-columns:1fr;gap:0;padding:10px 10px 0}
  .tpx-side{display:none}
  .tpx-bbtn{display:flex;align-items:center;gap:10px;width:100%;padding:8px 14px;border-radius:14px;border:1px solid #9a6bd0;background:linear-gradient(180deg,#2c1e36,#110918);color:#e2c4ff;margin-bottom:8px;flex:none}
  .tpx-bb-t{display:flex;flex-direction:column;align-items:flex-start;min-width:0}
  .tpx-bb-l{font:700 9px Cinzel,Georgia,serif;letter-spacing:2px;color:#b99ad8}
  .tpx-bb-v{font:700 15px Cinzel,Georgia,serif;letter-spacing:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:74vw}
  .tpx-bb-c{margin-left:auto;font-size:16px}
  .tpx-line h2{display:none}
  .tpx-line{margin-bottom:8px;gap:8px}
  .tpx-note{flex-basis:100%;font-size:13px}
  .tp-items{grid-template-columns:1fr}
  .tp-list .tp-tags{overflow-x:auto;scrollbar-width:none}
  .tp-list .tp-tags::-webkit-scrollbar{display:none}
  /* build 269: centred on a phone too, chosen over the bottom sheet after seeing both side by
     side. The sheet was deliberate and is the usual phone pattern -- buttons under the thumb, and
     it rides up with the keyboard -- but it was read as the form "ending up at the bottom of the
     screen", and one placement at every width is one less thing to learn. 82vh rather than the
     desktop's 86 so there is still a visible margin of dimmed board above and below it, which is
     what tells you the thing is a window over the board and not a new screen. */
  .gc-root.tpx-new-open .tp-newpost{left:50%;top:50%;bottom:auto;transform:translate(-50%,-50%);
  width:min(680px,94vw);border-radius:16px;max-height:82vh}
}
.tpx-sheet-ov{position:fixed;inset:0;z-index:62;background:rgba(0,0,0,.55);display:flex;align-items:flex-end}
.tpx-sheet{width:100%;max-height:80vh;display:flex;flex-direction:column;background:linear-gradient(180deg,#1d120d,#0c0702);border-top:1px solid var(--gold-lo);border-radius:18px 18px 0 0;padding:8px 12px 16px;box-shadow:0 -10px 30px rgba(0,0,0,.6)}
.tpx-grab{width:44px;height:4px;border-radius:2px;background:#5a4a36;margin:4px auto 8px;flex:none}
.tpx-sheet-in{overflow-y:auto}
.tpx-sheet .tpx-grp{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.tpx-sheet .tpx-bd{border:1px solid rgba(201,162,74,.16);background:rgba(255,240,210,.03);padding:9px 10px;border-radius:10px}
.tpx-sheet .tpx-bd.on{border-color:#9a6bd0}
@media (max-width:860px){
  .tpx-line .tp-new{position:fixed;left:14px;right:auto;bottom:16px;z-index:30;height:46px;padding:0 20px;box-shadow:0 0 14px rgba(200,50,40,.6),0 6px 18px rgba(0,0,0,.6)}
  .tpx-line{padding-right:0}
  .gc-root.thread-open .tpx-line .tp-new{display:none}
  .tpx-foot{margin-bottom:54px}
}
/* Sunday keeps the sanguine it had as a tab */
.tpx-bd[data-board="sunday"].on{background:linear-gradient(180deg,#360d0a,#150000);border-color:#c8342a;color:#ffe1dc;text-shadow:0 0 8px rgba(255,120,100,.5),0 1px 0 #000;box-shadow:inset 0 0 8px rgba(200,50,40,.3)}
.tpx-bd[data-board="sunday"].on .tpx-n{color:#ffe1dc}

/* ==================== build 247: the login screen in the purple colourway (mock-up B) ==================== */
/* The user picked B of four, 20 Sept: the front door now wears what the rest of the site wears -- the whisper
   windows' purple for the title, the rule, the labels and the key boxes, sanguine for Enter the room, ember
   copper for "Sign in with email". Only the signed-out screen changes; the moment you are in, the chat window's
   own gold frame and title (build 243) come back. */
.login{background:radial-gradient(120% 80% at 50% 0%,rgba(122,75,176,.22),transparent 64%)}
.login h1{color:#e2c4ff;text-shadow:0 0 20px rgba(200,150,255,.6),0 2px 0 #000}
.login .rule{width:220px;background:linear-gradient(90deg,transparent,#9a6bd0,transparent)}
.login .tag{color:#b99ad8}
.login label{color:#b99ad8}
.login .sunk{border-color:#4a3560;background:linear-gradient(180deg,#110918,#08020e);color:#efe6d6}
.login .sunk:focus{border-color:#9a6bd0;box-shadow:inset 0 0 18px #000,0 0 10px rgba(160,110,230,.5);outline:none}
.login .room-peek b{color:#e2c4ff}
.login label.remember-row{color:#b99ad8}
.remember-row input{accent-color:#9a6bd0}
#join{background:linear-gradient(180deg,#5a1d19,#1f0000);border:1px solid #c8342a;color:#ffe1dc;border-radius:999px;
box-shadow:0 0 14px rgba(200,50,40,.5);text-shadow:0 1px 0 #000;height:38px !important;padding:0 26px;font-size:13px;letter-spacing:1.2px}
#join:hover,#join:focus-visible{border-color:#e0453a;color:#fff;outline:none}
.admin-toggle{color:#e08a2c}
.admin-toggle:hover,.admin-toggle:focus-visible{color:#f0a24a;outline:none}
.gc-root:not(.signed-on) .win > .title{background:linear-gradient(180deg,#2c1e36,#110918);border-bottom:2px solid #7a4bb0;color:#e2c4ff;text-shadow:0 0 8px rgba(200,150,255,.5),0 1px 0 #000}
.gc-root:not(.signed-on) .win > .title::after{opacity:0}

/* ==================== build 248: a long trip no longer runs off the player card ==================== */
/* .pc-line is a flex row, and text-overflow never reaches a bare text node inside one -- so "🧳 Your mom's
   house · Northeast · till Fri" was simply cut off at the card's edge with no ellipsis. The trip line now wraps
   to at most two lines inside the card and is cut with an ellipsis after that; the status line keeps its one
   line but its message can finally shrink. */
.nmenu .pc-line.pc-travel{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
white-space:normal;overflow-wrap:anywhere;line-height:1.35;text-overflow:ellipsis}
.nmenu .pc-status .pc-stmsg{min-width:0;white-space:nowrap}
.nmenu .pc-line.pc-bday{white-space:normal;overflow-wrap:anywhere}

/* ==================== build 249: Terms & privacy ==================== */
.terms-link{font:inherit;font-size:inherit;color:#b99ad8;background:none;border:none;padding:0;cursor:pointer;text-decoration:underline}
.terms-link:hover,.terms-link:focus-visible{color:#e2c4ff;outline:none}
.tm-modal{width:min(720px,94vw);max-height:86vh;display:flex;flex-direction:column;text-align:left}
.tm-body{overflow-y:auto;padding:4px 4px 6px;margin:6px 0;font:15px "IM Fell English",Georgia,serif;color:var(--bone);line-height:1.5;scrollbar-color:var(--gold-lo) #0f0d0b}
.tm-body p{margin:0 0 10px}
.tm-lead{color:#e8dcc4;font-style:italic;border-left:2px solid #4a3560;padding-left:10px}
.tm-h{margin:16px 0 6px;font:700 13px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:#b99ad8}
.tm-ul{margin:0 0 10px;padding-left:18px}
.tm-ul li{margin:0 0 7px}
.tm-ul b{color:var(--gold-hi)}
.tm-modal .save-actions{flex:none}
.tm-modal #tmClose{background:linear-gradient(180deg,#5a1d19,#1f0000);border-color:#c8342a;color:#ffe1dc;border-radius:999px;padding:0 20px}
@media (max-width:500px){.tm-body{font-size:14px}.tm-modal{width:96vw;max-height:88vh}}

/* ==================== build 250: taking a voice note back, and leaving for good ==================== */
/* The ✕ only ever appears on your own note, so it sits quietly at the end of the pill and only warms up
   under the pointer -- it is a one-way door and should not invite an idle tap. */
.vn-x{width:18px;height:18px;flex:none;margin-left:1px;padding:0;cursor:pointer;
font:700 9px/1 Cinzel,Georgia,serif;color:#8f6fb0;background:transparent;
border:1px solid transparent;border-radius:50%;opacity:.65;transition:opacity .12s,color .12s,border-color .12s}
.vn:hover .vn-x,.vn-x:focus-visible{opacity:1}
.vn-x:hover,.vn-x:focus-visible{color:#ffd9d4;border-color:var(--blood,#c8342a);background:#360c08;outline:none}
.vn-x:disabled{opacity:.35;cursor:default}
@media (max-width:500px){.vn-x{width:22px;height:22px;font-size:11px;opacity:1}}

/* Deleting an account. Sanguine, not purple: this is the one screen in here that should feel like a door
   closing behind you. */
.da-modal{max-width:440px}
.da-body{padding:14px 16px 4px;text-align:left;font-size:13px;line-height:1.5;color:var(--parch,#e8dcc8)}
.da-lead{margin:0 0 10px}
.da-ul{margin:0 0 10px;padding-left:18px}
.da-ul li{margin:3px 0}
.da-note{margin:0 0 14px;padding:8px 10px;font-size:12px;font-style:italic;color:#ffe1dc;
border:1px solid #c8342a;border-left-width:3px;border-radius:4px;
background:linear-gradient(180deg,#5a1d19,#1f0000)}
.da-lab{display:block;margin:0 0 5px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#c6a6e8}
.da-in{width:100%;padding:7px 9px;font-size:14px;color:var(--parch,#e8dcc8);
background:#0a050e;border:1px solid #4a3560;border-radius:4px}
.da-in:focus{border-color:#9a6bd0;outline:none;box-shadow:0 0 7px rgba(150,90,220,.45)}
.da-err{min-height:16px;margin:6px 0 2px;font-size:12px;color:#ffb3a8}
.btn.da-go{color:#ffe1dc;border-color:#c8342a;background:linear-gradient(180deg,#5a1d19,#1f0000)}
.btn.da-go:hover:not(:disabled),.btn.da-go:focus-visible{color:#fff;border-color:#ff6a5c;
box-shadow:0 0 9px rgba(200,52,42,.65);outline:none}
.btn.da-go:disabled{opacity:.45;cursor:default;box-shadow:none}

/* ==================== build 251: the ban box and the watch list ==================== */
.bb-modal{max-width:430px}
.bb-body{padding:14px 16px 4px;text-align:left;font-size:13px;line-height:1.5;color:var(--parch,#e8dcc8)}
.bb-lab{display:block;margin:10px 0 5px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#c6a6e8}
.bb-lab:first-child{margin-top:0}
.bb-in{width:100%;padding:7px 9px;font-size:14px;color:var(--parch,#e8dcc8);
background:#0a050e;border:1px solid #4a3560;border-radius:4px}
.bb-in:focus{border-color:#9a6bd0;outline:none;box-shadow:0 0 7px rgba(150,90,220,.45)}
.bb-chips{display:flex;flex-wrap:wrap;gap:6px}
.bb-chip{padding:5px 10px;cursor:pointer;font:700 11px Cinzel,Georgia,serif;letter-spacing:.5px;
color:#b99ad8;background:linear-gradient(180deg,#1f1526,#0a050e);
border:1px solid #4a3560;border-radius:999px}
.bb-chip:hover{color:#e2c4ff;border-color:#9a6bd0}
.bb-chip.on{color:#fff;border-color:#9a6bd0;background:linear-gradient(180deg,#4a2f66,#241136);
box-shadow:0 0 7px rgba(150,90,220,.5)}
.bb-chip.bb-net.on{color:#ffe1dc;border-color:#c8342a;background:linear-gradient(180deg,#5a1d19,#1f0000);
box-shadow:0 0 7px rgba(200,52,42,.5)}
.bb-note{margin:12px 0 2px;padding:8px 10px;font-size:12px;font-style:italic;color:#ffe1dc;
border:1px solid #c8342a;border-left-width:3px;border-radius:4px;
background:linear-gradient(180deg,#5a1d19,#1f0000)}
.btn.bb-go{color:#ffe1dc;border-color:#c8342a;background:linear-gradient(180deg,#5a1d19,#1f0000)}
.btn.bb-go:hover,.btn.bb-go:focus-visible{color:#fff;border-color:#ff6a5c;box-shadow:0 0 9px rgba(200,52,42,.65);outline:none}
/* A watch row is a report row that nobody filed: same shape, copper edge, because it is a heads-up
   rather than a complaint. */
.wl-row{border-left:3px solid #e08a2c}

/* ==================== build 252: the house Yes/No box ==================== */
.ask-modal{max-width:400px}
#askTitle{line-height:1.3}
.ask-modal .modal-body{padding:12px 16px 2px;text-align:left;font-size:13px;line-height:1.5;color:var(--parch,#e8dcc8);white-space:pre-wrap}
/* The one that destroys something wears the blood on the button, not on the whole box: the question
   should read calmly and the consequence should sit on the thing you press. */
.btn.ask-danger{color:#ffe1dc;border-color:#c8342a;background:linear-gradient(180deg,#5a1d19,#1f0000)}
.btn.ask-danger:hover,.btn.ask-danger:focus-visible{color:#fff;border-color:#ff6a5c;
box-shadow:0 0 9px rgba(200,52,42,.65);outline:none}
#askCancel:focus-visible{border-color:#9a6bd0;box-shadow:0 0 8px rgba(150,90,220,.55);outline:none}

/* ==================== build 254: haptic taps ==================== */
/* The iPhone trick needs a real, rendered element: display:none or visibility:hidden and Safari fires
   nothing. So it is parked off-screen at a pixel instead, out of the tab order and out of the way. */
.hap-off{position:fixed;left:-9999px;top:0;width:1px;height:1px;opacity:0;pointer-events:none;
margin:0;padding:0;border:0;appearance:none;-webkit-appearance:none}

/* ==================== build 255: the filter bar on a phone ====================
   Below the width where the board list becomes a sheet, the bar is three dropdowns and nothing else:
   Topic, State where the board has states, and Sort. The chips and their labels stand down. */
@media (max-width:860px){
  .tp-list .tp-tags{flex-wrap:nowrap;gap:6px;padding:7px 8px}
  .tp-list .tp-tags .tpx-lbl,.tp-list .tp-tags .tpx-chips,.tp-list .tp-tags .tpx-vsep{display:none}
  .tp-list .tpx-topicsel{display:block}
  .tp-list .tp-tags .tp-sel{flex:1 1 0;min-width:0;max-width:none;width:auto;
    height:30px;border-radius:999px;padding:0 6px 0 10px;font-size:12px;
    border:1px solid #4a3560;background:linear-gradient(180deg,#1f1526,#0a050e);color:#b99ad8}
  .tp-list .tp-tags .tp-sel:focus{border-color:#9a6bd0;outline:none;box-shadow:0 0 7px rgba(150,90,220,.4)}
  /* the state picker wears copper everywhere else on the site; in this row of three it matches its neighbours */
  .tp-list .tp-tags .tp-statesel{border-color:#4a3560 !important;color:#b99ad8}
}

/* ==================== build 255: the calling card, and the profile rearranged ====================
   The name stops being loose text on a background and sits on something issued to it. Everyone gets the
   plain plate; an admin's is the Battle.net legendary orange (#ff8000) and is meant to be unmistakable
   from across the room. The plate keeps the avatar's overlap onto the header picture. */
.pf-plate{position:relative;align-items:center;gap:13px;margin:-38px 16px 0;padding:11px 14px;border-radius:14px;overflow:hidden;
border:1px solid var(--pf-line);box-shadow:0 10px 26px rgba(0,0,0,.45);
/* opaque underneath: the plate overlaps the header picture, and a see-through one lets the band's
   double rule cut straight across the name */
background:linear-gradient(135deg,rgba(255,240,210,.07),rgba(255,240,210,0) 45%,rgba(255,240,210,.06)),var(--pf-card)}
.pf-plate::before{content:'';position:absolute;inset:0;opacity:.12;pointer-events:none;
background:repeating-linear-gradient(115deg,var(--pf-gold) 0 1px,transparent 1px 11px)}
.pf-plate::after{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:linear-gradient(180deg,var(--pf-gold-hi),var(--pf-gold),transparent)}
.pf-plate > *{position:relative}
.pf-plate .pf-lines{padding-top:0}
.pf-plate .pf-ava{width:74px;height:74px;border-width:2px}
.pf-plate .pf-ava-cam{right:-2px;bottom:-2px}
/* the legendary one */
.pf-plate.pf-leg{border-color:#ff8000;
background:linear-gradient(135deg,#361500 0%,#0d0200 45%,#4a2607 100%);
box-shadow:0 0 24px rgba(255,128,0,.3),inset 0 0 22px rgba(255,128,0,.12),0 10px 26px rgba(0,0,0,.45)}
.pf-plate.pf-leg::before{opacity:.18;background:repeating-linear-gradient(115deg,#ffb04d 0 1px,transparent 1px 11px)}
.pf-plate.pf-leg::after{background:linear-gradient(180deg,#ffb04d,#ff8000,#8a4300)}
.pf-plate.pf-leg .pf-name,.pf-plate.pf-leg .pf-name .hd-name,.pf-plate.pf-leg .pf-name .nmt{color:#ffe0bd;text-shadow:0 1px 0 #000,0 0 14px rgba(255,128,0,.6)}
/* the room's admin name treatment is a red glow on a dark plate; on this one it fights the orange, so
   inside the card the name is simply the card's own light */
.pf-plate.pf-leg .pf-name .nmt::before,.pf-plate.pf-leg .pf-name .nmt::after{display:none}
.pf-plate.pf-leg .pf-sub,.pf-plate.pf-leg .pf-sub span{color:#f4d3ad}
.pf-plate.pf-leg .pf-sub .lvl{color:#ffd9a8;border-color:rgba(255,176,77,.7)}
.pf-plate.pf-leg .pf-song{border-color:rgba(255,176,77,.55);color:#ffe0bd}
.pf-plate.pf-leg .pf-ava{border-color:rgba(255,176,77,.8);box-shadow:0 0 14px rgba(255,128,0,.35),0 0 0 1px #000}
.pf-plate.pf-leg .pf-status,.pf-plate.pf-leg .pf-meta{color:#e2b27a}
.pf-plate.pf-leg .pc-role{border-color:#ff8000;color:#ffc07a}
@media (max-width:500px){.pf-plate{margin:-30px 10px 0;padding:10px 11px;gap:10px}.pf-plate .pf-ava{width:58px;height:58px}}

/* The rail, in the order it was asked for: top friends, then standing, then the pictures. On a phone the
   rail stops being a box of its own (display:contents) so its three pieces can be dealt out around the
   wall -- standing, friends, the wall, then the pictures -- with no second copy of the markup. */
@media (max-width:899px){
  .pf-cols{display:flex;flex-direction:column;gap:0}
  .pf-rail{display:contents}
  .pf-rail .pf-stats{order:1}
  .pf-rail .pf-sec:not(.pf-photos){order:2}
  .pf-main{order:3;min-width:0}
  .pf-rail .pf-photos{order:4}
  /* standing, four across and small: it is a footnote on a phone, not the point of the page */
  .pf-stats{grid-template-columns:repeat(4,1fr) !important;gap:5px}
  .pf-stats .pf-stat{padding:6px 2px}
  .pf-stats .pf-stat b{font-size:14px}
  .pf-stats .pf-stat span{font-size:8px;letter-spacing:1px}
  /* top friends become a row you swipe rather than four rows you scroll past */
  .pf-tfs{display:flex !important;gap:7px;overflow-x:auto;scrollbar-width:none;padding-bottom:2px}
  .pf-tfs::-webkit-scrollbar{display:none}
  .pf-tfs .pf-tf{flex:none;width:74px}
}

/* ==================== build 256: a picture on the wall ==================== */
.pf-comp-tools{display:flex;gap:5px;align-items:center;flex:none}
.pf-tool{width:32px;height:32px;padding:0;cursor:pointer;font-size:14px;line-height:1;
color:var(--pf-gold);background:var(--pf-card);border:1px solid var(--pf-line);border-radius:8px}
.pf-tool:hover,.pf-tool:focus-visible{color:var(--pf-gold-hi);border-color:var(--pf-gold);outline:none}
.pf-tool:disabled{opacity:.5;cursor:default}
.pf-tool-gif{width:auto;padding:0 9px;font:700 10px Cinzel,Georgia,serif;letter-spacing:1px}
/* a picture in a post stays inside the post and keeps its shape */
.pf-post-txt img.gif{display:block;max-width:min(300px,100%);max-height:320px;width:auto;height:auto;
margin-top:2px;border-radius:9px;border:1px solid var(--pf-line);cursor:zoom-in}
@media (max-width:500px){.pf-post-txt img.gif{max-width:100%}}

/* ==================== build 258: search ====================
   One panel, a field at the top and the answers under it. On a phone it takes the whole screen, because
   a small box of results with a keyboard over it is no use to anybody. */
.sch-ov{align-items:flex-start;padding-top:8vh}
.sch-modal{width:min(560px,94vw);max-width:none;max-height:80vh;display:flex;flex-direction:column;padding:0;overflow:hidden}
.sch-top{display:flex;gap:8px;align-items:center;padding:12px 12px 10px;border-bottom:1px solid rgba(201,162,74,.2)}
.sch-in{flex:1;min-width:0;padding:9px 12px;font:15px "IM Fell English",Georgia,serif;color:var(--parch,#e8dcc8);
background:#0a050e;border:1px solid #4a3560;border-radius:999px}
.sch-in:focus{border-color:#9a6bd0;outline:none;box-shadow:0 0 8px rgba(150,90,220,.45)}
.sch-in::-webkit-search-cancel-button{filter:invert(.7) sepia(.4)}
/* min-width:0 is load-bearing: `.btn` sets `min-width:66px`, and min-width beats width in the
   cascade whatever the specificity, so this button has been 66 wide and 38 tall -- a stretched
   ellipse, not the round button it reads as. */
.btn.sch-x{flex:none;min-width:0;width:38px;height:38px;padding:0;font-size:14px;line-height:1;border-radius:50%}
.sch-body{flex:1;min-height:0;overflow-y:auto;padding:6px 8px 12px;scrollbar-color:#4a3560 #140f17}
.sch-hint{padding:26px 14px;text-align:center;font:italic 13px "IM Fell English",Georgia,serif;color:var(--ash,#8f836c)}
.sch-hd{position:sticky;top:0;z-index:1;padding:8px 8px 4px;font:700 9px Cinzel,Georgia,serif;letter-spacing:2px;
text-transform:uppercase;color:#8f7446;background:linear-gradient(180deg,#0c0607 70%,rgba(21,16,17,0))}
.sch-row{display:flex;align-items:center;gap:9px;width:100%;padding:8px 9px;margin-bottom:3px;text-align:left;cursor:pointer;
background:transparent;border:1px solid transparent;border-radius:10px;color:var(--parch,#e8dcc8)}
.sch-row:hover,.sch-row:focus-visible{border-color:#9a6bd0;background:linear-gradient(180deg,#1d1225,#0d0511);outline:none}
.sch-ico{width:26px;flex:none;text-align:center;font-size:15px;opacity:.85}
.sch-ava{width:26px;height:26px;flex:none;border-radius:50%}
.sch-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.sch-txt b{font:700 13px Cinzel,Georgia,serif;letter-spacing:.4px;color:var(--gold-hi,#f1d98a);
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-line{font-size:12px;color:#b7aa92;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-meta{flex:none;max-width:34%;font-size:11px;color:#8f836c;text-align:right;
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:560px){
  /* build 289: padding:0, not padding-top:0. `.modal-overlay` (line ~377) sets `padding:16px` on
     every modal backdrop, and this breakpoint -- where the search panel is meant to be full-bleed --
     was only cancelling the TOP of it. The 16px each side stayed, and everything since has been a
     consequence of it:
       * originally `.sch-modal{width:100vw}` -- 414pt of panel inside a box starting at x=16, so it
         hung 16pt off the RIGHT edge. That was the reported "overflows off the screen".
       * build 287 changed that to width:100%, which respects the padding, so the panel went inset
         16pt on BOTH sides instead. A different symptom of the same untouched cause, and worse,
         because it looked deliberate.
     Cancel the padding here and width:100% is exactly the screen. Reported on Android as well as
     iPhone, which is what ruled out safe areas and WebKit and pointed back at plain CSS. */
  .sch-ov{padding:0;align-items:stretch}
  /* width:100% not 100vw -- on iOS 100vw is the LAYOUT viewport and ignores the safe-area insets
     that viewport-fit=cover brings in, so on a notched phone it is wider than what is on screen and
     the panel hangs off the edge. The overlay is position:fixed with inset 0, so 100% is exactly the
     right box and cannot exceed it. Changed here at the source rather than overridden later: build
     283 already cost a pixel to a rule that won on source order, and a stale 100vw sitting at the
     obvious place is the next version of that. */
  .sch-modal{width:100%;height:100dvh;max-height:none;border-radius:0;border-width:0}
  .sch-txt b{font-size:14px}
}

/* ==================== build 259: the empty screens ====================
   An empty board leads with a welcome rather than an apology, and says underneath what to post. */
.tp-emptyhd{display:block;margin-bottom:4px;font:700 17px Cinzel,Georgia,serif;letter-spacing:1px;
color:var(--gold-hi);font-style:normal}
.tp-empty span{display:block;max-width:34em;margin:0 auto;font-size:13px;line-height:1.45}

/* ==================== build 260: the verse of the day ====================
   Set as a quotation, not as a notice: the text carries, the reference stands under it small.
   It appears in three places -- the Sunday board, the Sunday card on Home, the Today column -- and
   .vod-sun is the only one that needs extra room, since on the board it leads the whole panel. */
.vod{margin:0 0 8px;font:14px "IM Fell English",Georgia,serif;color:var(--bone)}
.vod-t{font-style:italic;color:var(--gold-hi);line-height:1.4}
.vod-r{margin-top:3px;font:700 10px Cinzel,Georgia,serif;letter-spacing:2px;text-transform:uppercase;color:var(--gold);opacity:.85}
.vod-sun{margin-bottom:10px;padding-bottom:9px;border-bottom:1px solid var(--gold-lo)}
.vod-sun .vod-t{font-size:16px}
.sun-hd2{margin-top:2px}
.td-box .vod{margin-bottom:0}
.td-box .vod-t{font-size:13px}
.td-sh .td-src{font-size:9px;letter-spacing:1px;color:var(--ash);margin-left:4px}
.hm-sunday .vod{margin-bottom:6px}

/* ==================== build 264: a line waiting for a connection ====================
   Drawn where it would have gone, so a held message is never a silent promise: you can see it
   sitting there, and the ✕ takes it back. Deliberately quieter than a real message and quieter
   than a system line -- it has not happened yet. */
.m.sys.pending{display:flex;align-items:center;gap:8px;opacity:.72;font-style:italic;
border-left:2px solid var(--gold-lo);padding-left:8px}
.m.sys.pending .pd-body{flex:1;min-width:0;overflow-wrap:anywhere}
.m.sys.pending .pd-note{flex:none;font:700 9px Cinzel,Georgia,serif;letter-spacing:1.5px;
text-transform:uppercase;color:var(--ash);font-style:normal}
.m.sys.pending .pd-x{flex:none;width:30px;height:30px;padding:0;line-height:1;cursor:pointer;
background:none;border:1px solid var(--gold-lo);border-radius:4px;color:var(--ash);font-size:12px}
.m.sys.pending .pd-x:hover,.m.sys.pending .pd-x:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
/* On a phone the note is the MOST important part -- a tunnel is where this happens -- so it wraps
   underneath rather than being hidden, which would leave an unexplained grey line with an x on it. */
@media (max-width:500px){
.m.sys.pending{flex-wrap:wrap}
.m.sys.pending .pd-body{flex:1 1 100%;order:1}
.m.sys.pending .pd-note{order:2;flex:1 1 auto}
.m.sys.pending .pd-x{order:3}
}

/* ==================== build 266: the dropdown lists stop being white ====================
   Reported with a screenshot of the state filter: the closed control is right -- sunken black,
   gold rule, bone text -- and then the list that drops out of it is a white box with the bone
   text still on it, which is unreadable and looks like a different program.

   The cause is that a native <select> is two things. The box is ours and has been styled twenty
   times over; the LIST is drawn by the browser, and it takes none of the box's colours. It uses
   the UA's own background -- white -- while <option> quietly inherits `color` from the select,
   so the bone and the gold we chose get painted onto white. Every select on the site did this
   except the one on the login screen, which had `option{background:#0e0906}` written for it by
   hand in v96 and was therefore the only one anybody had ever looked at with the list open.

   So the rule that was written for one select is made general. Two halves, and both are needed:
   `color-scheme` tells the browser the control is a dark one, which is what darkens the parts we
   cannot reach -- the popup's own frame, its scrollbar, the highlight on the row under the
   pointer; the explicit colours on option and optgroup put OUR black and OUR bone inside it
   rather than the browser's idea of dark grey.

   Deliberately kept to `select` rather than put on :root. A page-wide color-scheme would also
   repaint every scrollbar, checkbox and autofill on the site, which is a bigger change than the
   one that was asked for and wants its own look.

   The two selects that already have their own list colours -- the login screen and the travel
   form, both in the purple colourway -- are untouched: `.login select.sunk option` and
   `#travelForm select optgroup` are more specific than these, so they keep their purple.

   What this does NOT fix, and it is worth knowing before somebody reports it as a bug: Safari on
   a Mac and Safari on an iPhone do not let a page colour the list at all. The iPhone draws a
   wheel at the bottom of the screen and the Mac draws a system menu. Both of those DO follow
   color-scheme, so they turn dark and become readable, but they turn the system's dark and not
   ours. Chrome, Edge, Firefox and Android take the colours below exactly. */
select{color-scheme:dark;accent-color:var(--gold)}
select option,select optgroup{background-color:#0e0906;color:var(--bone)}
select optgroup{color:var(--gold);font-style:normal}
select option:checked{color:var(--gold-hi)}
select option:disabled{color:var(--ash)}

/* ==================== build 267: the new-thread form could not be clicked ====================
   Reported: on the Threads board, "New thread" dims the screen, the form appears, and then nothing
   on it can be clicked or typed into. Total, and it blocks the one thing that board is for.

   Not a regression and not a hidden element -- a stacking-context trap, which is why it looks
   impossible on paper. The two rules involved read as correct:

     .gc-root.tpx-new-open::before      the dim, position:fixed, z-index:59
     .gc-root.tpx-new-open .tp-newpost  the form, position:fixed, z-index:60

   60 is above 59, so the form should be on top. It is not, because **z-index is only compared
   inside one stacking context**. The form lives inside `#threadsPanel`, and the expanded board
   gives that panel `position:fixed;z-index:40`, which makes it a stacking context of its own. So
   the form's 60 is a rank *within the panel*, and the whole panel -- form and all -- takes part in
   the page at level 40. The dim is a child of `.gc-root`, in the page's own context, at 59. 59
   beats 40, so the dim covers the form no matter what number the form is given. Raising the form
   to 600 would have changed nothing, and that is the tell for this class of bug.

   Proved rather than reasoned: `document.elementFromPoint()` at the centre of the textarea, the
   board select and the Post button all returned `div.gc-root` -- the dim -- instead of the control
   underneath. Every click was landing on the dim.

   The fix keeps both numbers and fixes what each layer is for:
   - The dim only ever needed to be *seen*. `pointer-events:none` lets it paint over everything --
     including the whisper dock, which is the one thing that floats above the panel -- while
     catching nothing.
   - Something still has to swallow the clicks that land outside the form, or the board behind the
     dim stays live and you can open a thread through it. That shield is `.threads-panel::after`:
     transparent, full-screen, and **inside the panel's own context at 59**, which is where the
     form's 60 finally means something.
   - The whisper dock sits above the panel at 45 and was blocked by the old dim, so it keeps that
     behaviour explicitly rather than becoming the one live control on a dimmed screen.

   This is why the form on a phone (a bottom sheet) and the board picker sheet (z-index 62, inside
   the same panel) were never affected: both are already inside the panel's context. */
.gc-root.tpx-new-open.mobile-threads-open::before{display:none}
.gc-root.tpx-new-open .threads-panel::after{content:"";position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:59}
.gc-root.tpx-new-open .dm-dock{pointer-events:none;opacity:.4}

/* ==================== build 268: the dim was still painting over the form ====================
   267 fixed half of it and shipped the other half broken, which is worth keeping on the record.
   Making the dim `pointer-events:none` let clicks through -- the form became usable, and the
   reporter confirmed that much -- but a layer that does not catch clicks still PAINTS. The dim
   was at 59 in the page's context and the form, trapped in the panel, was still effectively at
   40, so the form went on being drawn under 60% black: usable, and dark grey.

   The mistake underneath the mistake: "the dim only needs to be seen, not clicked" was the right
   sentence about the wrong layer. Clicking and painting are the same ordering problem, and only
   one of the two was actually fixed. A hit test passing is not the same as it looking right, and
   elementFromPoint cannot tell you the difference -- it reports the top CATCHER, and a
   pointer-events:none layer is invisible to it while being perfectly visible to a person.

   So the dim moves into the panel's context outright rather than being made to behave from
   outside it. `.threads-panel::after` is now the dim itself -- it paints AND catches, at 59,
   in the context where the form's 60 finally outranks it -- and the old page-level dim is turned
   off while the expanded board is up, so the two cannot stack into 84% black. The docked board,
   where the panel makes no context of its own, keeps the page-level dim exactly as it was.

   The whisper dock floats above the panel at z-index 45 and so is outside the dim either way.
   Rather than leave it as the one bright, live control on a dimmed screen, it is dimmed and
   deafened to match what the old page-level dim did to it. */

/* ==================== build 271: Home, rearranged and recoloured ====================
   Home rendered six sections in a fixed order with the FEED LAST, so the reason the page exists
   sat below three cards that are the same every day. Measured on the mock-up, with the same data:
   the feed began at y=514 on a 900px desktop and y=539 on a 780px phone, and a phone showed TWO
   events before running out of screen. It now starts at y=72 at both widths and shows eight.

   The section order is changed in renderHome() (the feed sections are emitted first, wrapped in
   .hm-main, the daily cards in .hm-side). It is done in the markup rather than with CSS `order`
   on purpose: order would leave the reading order and the tab order still running through the
   cards first, which is the same wrongness moved somewhere a screen reader still meets it.

   TWO WRAPPERS rather than grid-column on the sections themselves, and this is the part that took
   three goes in the mock-up: a grid places children in DOM order, so with the sections as direct
   children the second column began on the row after the last feed section and left a screen of
   nothing above it -- in both orderings, in mirror image. Each column has to be its own flow. */
@media (min-width:1000px){
  /* build 339: Happenings and Circles share the .hm-body box, and this two-column grid split their pages in half
     on every computer screen (calendar squeezed into the corner, a circle's tabs on the right and their content
     on the left). The grid is Home's alone; the others keep only the width. */
  .hm-body{max-width:1180px;margin:0 auto}
  #homeBody.hm-body{display:grid;grid-template-columns:minmax(0,3fr) minmax(320px,2fr);gap:26px;align-items:start} /* build 349: 3:2 (was 1fr + 340px, 786 vs 340 at 1280) */
  /* build 315: the cards now come first in the markup (for the phone), so each column is placed by hand */
  .hm-body > .hm-main{grid-column:1;grid-row:1}
  .hm-body > .hm-side{grid-column:2;grid-row:1}
}
@media (max-width:999px){ .hm-main,.hm-side{display:contents} }

/* the headings are ranked: news reads louder than furniture */
.hm-main > .hm-sec > .hm-sec-hd{font-size:13px;letter-spacing:2.5px;color:var(--gold-hi);
  border-bottom-color:var(--gold-lo);padding-bottom:7px;margin-bottom:8px}
.hm-side > .hm-sec > .hm-sec-hd{font-size:10px;letter-spacing:2px}

/* one line per event instead of two. The timestamp is <span class="t"> inside .hm-txt -- naming it
   anything else silently does nothing, which is how the first attempt "worked". */
.hm-main .hm-row{position:relative}
.hm-main .hm-row .hm-txt{padding-right:70px}
.hm-main .hm-row .hm-txt .t{position:absolute;right:10px;top:50%;transform:translateY(-50%);
  display:block;margin:0;font-size:11px;white-space:nowrap}

/* banding instead of row borders: the oldest way to make a long list scannable. 2.5% was invisible
   against this background and 5% is the floor that actually reads -- the usable range is narrow. */
.hm-main .hm-row{border-bottom:none}
.hm-main .hm-row:nth-child(even){background:rgba(255,240,210,.05)}
.hm-main .hm-sec-hd{border-bottom-width:2px}

/* the rail takes the whisper purple so it stops competing with the feed for the same gold.
   Only the CHROME -- headings, rules, buttons. Redefining --bone here turned people's NAMES purple
   in On the road, and a purple name already means something else on this site. Names are pinned
   back to gold-hi literally, because var(--gold-hi) is itself purple inside this wrapper. */
.hm-side{--gold:#9a6bd0;--gold-hi:#c8a6ef;--gold-lo:#4a3560}
.hm-side > .hm-sec > .hm-sec-hd{color:#b99ad8;border-bottom-color:#3a2b4a}
.hm-side .who,.hm-side .nmt{color:#f1d98a}

/* two bugs found while looking, both shipping today and neither data-dependent:
   1. .er-count and .er-purse were both float:right with nothing between them, so the errands
      header rendered "0 in your purse1 of 3" jammed together at every width. */
.hm-errands > .hm-sec-hd{display:flex;align-items:baseline;gap:6px}
.hm-errands .er-count{float:none;margin-left:10px}
.hm-errands .er-purse{float:none;margin-left:auto}

/* ==================== build 272: the page headers ==================== */
/* Every full page but the chat room shares one header, .tp-hd. It was a 52px bar carrying the page
   name in 16px gold with a halo, and a copper Back pill. Two changes, which do different jobs:

   THE BAR GETS SHORTER. 52 -> 38 on a desktop, 36 on a phone, with the title at 12px small-caps.
   The header's job is to say where you are and give you the way back; it was spending most of a
   list row saying it. Fourteen pixels come back on nine pages at once, at the width where they are
   scarcest.

   EACH PAGE GETS ITS OWN COLOUR. The height was doing the announcing; colour takes that over and
   costs nothing. The colours are not new -- every one of them already means this elsewhere on the
   site (build 241): purple is a person, ember copper is somewhere to go, leaf is play. Threads,
   Home and the Contest stay gold because gold is the house colour and the pages you are on most
   should look like the house. Reports takes a muted blood because it is the one page where you are
   acting on somebody. The Pit takes cold slate because it is a punishment.

   Gypsy Roulette has no .tp-hd -- it is a standing announcement with its own type -- so it is
   untouched, and so is the chat window's own .win > .title. */

/* 1. THE BACK PILL ON VARIABLES. It was written as literal copper (#e08a2c over #5a3212) inside
   .tp-hd .tp-back. It is the most saturated object in the bar, so recolouring the bar alone left a
   copper button sitting in a purple header and the whole thing read as half-finished. Now one
   accent moves the bar, the title and the button together. */
.tp-hd{--hd-acc:#e08a2c;--hd-acc-b1:#5a3212;--hd-acc-b2:#241306;--hd-acc-ink:#fff0dd}
.tp-hd .tp-back{border-color:var(--hd-acc);background:linear-gradient(180deg,var(--hd-acc-b1),var(--hd-acc-b2));
color:var(--hd-acc-ink);box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 1px 0 #000}
.tp-hd .tp-back:hover,.tp-hd .tp-back:focus-visible{border-color:var(--hd-acc-ink);color:#fff;
box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 0 10px var(--hd-acc)}

/* 2. THE SLIM BAR. */
.tp-hd{min-height:38px;padding:5px 110px;font-size:12px;letter-spacing:2.4px;
background:linear-gradient(180deg,#1a120a,#0a0706);box-shadow:0 1px 0 #000}
.tp-hd .tp-back{height:26px;line-height:24px;padding:0 11px;font-size:11px}
/* the thread header's right padding was set to 124px to clear the share button; match the left so a
   long title still centres in the space that is left.
   MIN-WIDTH 501 ON PURPOSE. Media queries add no specificity, so an unscoped `.tp-detail .tp-hd`
   here -- two classes, and later in the file -- beats the phone rule above that drops this padding
   to 10px, and does so INSIDE the phone media query. Unscoped, it left 110px of dead margin on a
   390px screen: the title was squeezed into 154px and a long one wrapped to four lines, so the one
   header on the site that got TALLER was the thread. The share button is absolutely positioned
   only on a desktop; on a phone it is a flex item in the row and needs no reserved space at all. */
@media (min-width:501px){ .tp-detail .tp-hd{padding-right:110px} }

/* 3. SMALL CAPS ONLY ON THE NAMES WE CHOOSE. The first render came back with the board as
   "/GEN/ - GENERAL" and somebody's thread title shouted in full capitals across the bar. The two
   headers whose text a PERSON wrote -- the board name and the thread title -- are left alone. */
.home-panel .tp-hd > span,.hap-panel .tp-hd > span,.circ-panel .tp-hd > span,
.gameroom-panel .tp-hd > span,.leaderboard-panel .tp-hd > span,.admin-panel .tp-hd > span,
.pit-tank .tp-hd > span{text-transform:uppercase}

@media (max-width:500px){
  .tp-hd{min-height:36px;padding:4px 8px;font-size:11px;letter-spacing:1.8px}
  .tp-hd .tp-back{height:24px;line-height:22px;padding:0 9px;font-size:10px}
}

/* 4. ONE COLOUR PER PAGE. Each block sets the bar's three golds, the pill's four, and -- on Profile
   -- its own theme variables as well. Profile has --pf-gold because a person can set their page to
   midnight, and .profile-panel .tp-hd{color:var(--pf-gold)} is two classes and outranks .tp-hd: a
   colourway that only sets --gold leaves Profile gold while the other eight change. --pf-gold takes
   the BRIGHT value, because that is the variable Profile's title actually reads. */
.hap-panel .tp-hd{--gold:#e08a2c;--gold-hi:#ffc98a;--gold-lo:#5a3a12;
--hd-acc:#e08a2c;--hd-acc-b1:#5a3212;--hd-acc-b2:#241306;--hd-acc-ink:#ffe2c2;
background:linear-gradient(180deg,#261809,#0d0806)}
.circ-panel .tp-hd{--gold:#9a6bd0;--gold-hi:#d9bcf5;--gold-lo:#4a3560;
--hd-acc:#9a6bd0;--hd-acc-b1:#3c2456;--hd-acc-b2:#190f24;--hd-acc-ink:#eadcff;
background:linear-gradient(180deg,#1d1428,#09060e)}
.profile-panel .tp-hd{--gold:#9a6bd0;--gold-hi:#d9bcf5;--gold-lo:#4a3560;
--pf-gold:#d9bcf5;--pf-gold-hi:#eadcff;
--hd-acc:#9a6bd0;--hd-acc-b1:#3c2456;--hd-acc-b2:#190f24;--hd-acc-ink:#eadcff;
background:linear-gradient(180deg,#1d1428,#09060e)}
.gameroom-panel .tp-hd{--gold:#5aa15a;--gold-hi:#a6e0a6;--gold-lo:#2c4a2c;
--hd-acc:#5aa15a;--hd-acc-b1:#234a23;--hd-acc-b2:#0f1d0f;--hd-acc-ink:#dff0df;
background:linear-gradient(180deg,#0f1e11,#060a06)}
.admin-panel .tp-hd{--gold:#c46a5c;--gold-hi:#f0a99c;--gold-lo:#5a2620;
--hd-acc:#c46a5c;--hd-acc-b1:#5a2620;--hd-acc-b2:#210d0a;--hd-acc-ink:#ffdcd6;
background:linear-gradient(180deg,#240f0d,#0d0606)}
.pit-tank .tp-hd{--gold:#7a8f9c;--gold-hi:#c2d4de;--gold-lo:#2c3a42;
--hd-acc:#7a8f9c;--hd-acc-b1:#24343d;--hd-acc-b2:#0d1317;--hd-acc-ink:#dbe8ef;
background:linear-gradient(180deg,#0a1218,#010609)}
.leaderboard-panel .tp-hd{--gold:#e0b44a;--gold-hi:#ffe6a3;--gold-lo:#6e5323}

/* ==================== build 273: black ==================== */
/* The site was a warm near-black stack -- page #0b0a09, then #141210 / #1f1b17 / #2b2521 -- and is
   now a true-black one. Not a switchable theme: there is one stylesheet and this is it.

   HOW THE COLOURS MOVED. Every literal inside a background declaration was rewritten by one rule,
   out = clamp(round((c - 11) * 1.15), 0, 255) per channel, applied only where no channel exceeded
   64. 11 because #0b0a09 is rgb(11,10,9), so the page floor lands exactly on #000; the 1.15 gain
   restores the separation that subtracting the floor costs, so the stack stays a stack:
       #0b0a09 -> #000000      #141210 -> #0a0806      #1f1b17 -> #17120e      #2b2521 -> #251e19
   331 colours across 216 declarations. The rule and the reasoning are in tests/mkblack.js, which
   generated this and now refuses to run again.

   ABOVE 64 IS UNTOUCHED, and that line is doing real work: the buttons, the copper Back pill, the
   blood red, the level badges, build 272's per-page header accents and the Black Ball Pit's teal
   water are all above it. The Pit is the clearest case -- that page's colour IS the feature, you
   are looking into a fishbowl, and the ceiling is what protected it while the chrome went black.

   ANYTHING OUTSIDE A BACKGROUND DECLARATION IS UNTOUCHED TOO. Borders, rules and text keep their
   colour on purpose. On black the edges carry more of the structure, not less, and dimming them
   with the fills is how a dark theme turns into one flat field.

   The rest of this block is what a per-colour rule cannot reach. */

/* 1. A full-screen panel is a PAGE, not a card. .win is a 760px window sitting on the page, so a
   fill one step above the floor reads correctly there. The panels cover the whole screen, and at
   that same fill they are a whole screen of brown with nothing to be lifted against. They drop to
   the floor and let their own rows and cards do the layering. Found by measuring, not by looking:
   with only the colour rewrite, the chat room went black and Circles stayed brown, because the
   panels are filled from var(--stone-2)/var(--stone) and a literal rewriter cannot see a variable. */
.threads-panel,.home-panel,.hap-panel,.circ-panel,.profile-panel,.gameroom-panel,
.leaderboard-panel,.admin-panel,.pit-tank,.roulette-panel{background:linear-gradient(180deg,#070505,#000)}

/* 2. Profile keeps a private palette because a person can theme their own page, and
   .gc-root.profile-open .profile-panel (two classes) outranks .profile-panel alone. Without this
   Profile silently excused itself: every other page dropped ~62% and Profile moved 17.0 to 16.6.
   Same shape as the --pf-gold trap in build 272. pf-theme-midnight is a choice its owner made and
   is deliberately left alone -- a site-wide theme does not overwrite somebody's own page. */
.profile-panel{--pf-bg:linear-gradient(180deg,#070505,#000);--pf-card:#0a0806;--pf-line:#2a2119;
--pf-band:linear-gradient(135deg,#2e1f0e,#0a0806 60%,#1d1409)}

/* 3. The glow comes off the type. Every text-shadow here existed to lift gold off a lighter
   background and is now lifting it off nothing. The golds themselves came down a step at source
   (:root and html.gc-night above). Contrast was never the problem on black -- body text would have
   gone 12.08:1 to 12.83:1 untouched -- bloom is: bright warm type on true black fringes on OLED and
   on cheap LCDs. The gain is spent calming the type rather than banked, and the tamed bone still
   measures 11.28:1, well past the 4.5 that normal text needs. */
.tp-hd{text-shadow:none}
.tp-hd > span,.win > .title{text-shadow:0 1px 0 #000}
html.gc-night body::before{background:radial-gradient(120% 60% at 50% -10%,rgba(255,150,60,.055),transparent 60%)}

/* 4. The frame does the work the fill used to. This is the whole reason the result still looks like
   this site and not like a generic dark theme: as the panel fills recede toward black, the double
   gold border and the outer glow are pushed harder so a window still reads as a window. */
.win{box-shadow:0 0 0 2px var(--gold),0 0 0 3px #000,0 0 34px rgba(201,162,74,.20),inset 0 0 0 1px #000}
.threads-panel,.home-panel,.hap-panel,.circ-panel,.profile-panel,.gameroom-panel,
.leaderboard-panel,.admin-panel,.pit-tank{border-left:1px solid #241d16;border-right:1px solid #241d16}

/* 5. A row needs an edge once its fill is near-black, or a long list becomes one dark field. */
.hm-row{border-bottom-color:#241d16}

/* ==================== build 274: the header glow stopped being a box ==================== */
/* Every page header except the chat room drew its title glow cut off square. Two rules meet on the
   same element and neither is wrong on its own:

     .tp-hd > span{overflow:hidden}                      so a long board name or thread title
                                                         ellipsises instead of bursting the bar
     html.gc-night .tp-hd > span{animation:gcCandleGlow}  a 10-14px blurred text-shadow

   A text-shadow is painted as part of the element's CONTENT, so the element's own overflow:hidden
   clips it: the glow spreads out from the letters and is then sliced off at the box. The chat
   room's title takes the same glow and has no overflow:hidden, which is exactly why it was the one
   header that looked right, and Gypsy Roulette has no header at all. That was the whole reported
   set, and it is what identified the cause.

   Build 273 did not create this. The clipped edge has always been there; against the old #0b0a09
   page it had almost nothing to contrast with, and against true black it reads as a box.

   THE FIX. Overflow clips at the PADDING box, not the border box. Pad the span by more than the
   widest blur the animation uses, and take the same amount back as negative margin so the margin
   box -- and therefore the layout, the bar's height and everything beside it -- is unchanged. The
   glow now fades to nothing before it reaches anything that clips it.

   18px and 16px are not arbitrary: gcCandleGlow peaks at a 14px blur, so both have to EXCEED 14,
   not merely reach it. The first attempt used 14px vertically -- equal to the blur, clipping the
   glow exactly where it fades instead of safely past it -- and the test below caught it. Vertical
   padding is free here because the negative margin gives it all back, so it is the more generous
   of the two; horizontal costs title room, so it is the tighter one. tests/hdstyle.js reads the largest blur radius out of the keyframes and
   asserts the padding still exceeds it, so making the glow wider later fails the test instead of
   quietly bringing the box back.

   Chosen over overflow-clip-margin, which is the precise tool for this and costs no title width,
   because it could not be verified on Safari from here and most of this room is on phones. Padding
   needs no feature support at all. The cost is about 16px less room for a title on a phone before
   it truncates, which was measured rather than estimated. */
.tp-hd > span{padding:18px 16px;margin:-18px -16px}

/* ==================== build 278: People ==================== */
/* A second mode on the search overlay rather than a new page: the same box, the same modal, one row
   of tabs. Everything below reuses what the site already has -- .tp-tag for the chips (purple,
   because purple has meant "something you pick" since build 241), .hm-sec-hd for the family
   headings, the same avatar and name treatment as the room. */
.sch-tabs{display:flex;gap:6px;padding:0 10px 8px}
.sch-tab{font:700 10px Cinzel,Georgia,serif;letter-spacing:1.4px;text-transform:uppercase;
background:linear-gradient(180deg,#261d2c,#140f17);border:1px solid #4a3560;border-radius:999px;
color:#b99ad8;padding:4px 12px;cursor:pointer}
.sch-tab.on{border-color:#9a6bd0;color:#e2c4ff}
.pd-chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 8px}
/* the selected chip is .active -- the same class, and therefore the same background, glow and
   text-shadow, that the thread boards and the admin tabs use. Marking it with a class of my own
   gave People a dimmer selected state than every other selected thing on the site. */
.pd-said{font:italic 13px "IM Fell English",Georgia,serif;color:var(--ash);padding:2px 2px 8px}
.pd-count{color:var(--ash);font-size:10px}
.pd-list{display:flex;flex-direction:column}
.pd-row{display:flex;align-items:center;gap:9px;padding:8px 6px;border-bottom:1px solid #1e1811;cursor:pointer;border-radius:6px}
.pd-row:hover{background:rgba(201,162,74,.05)}
.pd-ava{flex:none;width:30px;height:30px;border-radius:50%;vertical-align:middle}
.pd-txt{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:1px}
/* .pd-txt is a column, so a bare child stretches the full width -- the friend pill came out as a
   full-width bar the first time. The name and the pill get their own row. */
.pd-nm{display:flex;align-items:baseline;gap:6px;min-width:0}
.pd-txt .who{color:var(--gold-hi);font:700 14px Cinzel,Georgia,serif;letter-spacing:.5px;
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pd-fr{flex:none;font:700 8px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;color:#b99ad8;
border:1px solid #4a3560;border-radius:999px;padding:1px 6px}
.pd-meta{font-size:11px;color:var(--ash);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pd-lv{flex:none;font:700 9px Cinzel,Georgia,serif;color:var(--gold);border:1px solid var(--gold-lo);
border-radius:999px;padding:1px 6px}
.pd-w{flex:none;font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;color:#b99ad8;
background:linear-gradient(180deg,#261d2c,#140f17);border:1px solid #4a3560;border-radius:999px;
padding:4px 10px;cursor:pointer;white-space:nowrap}
.pd-w:hover{border-color:#9a6bd0;color:#e2c4ff}
/* "Add friend" is the sanguine one: it is the action that MAKES something, per build 241 */
.pd-add{color:#e0b0a8;background:linear-gradient(180deg,#3a1a16,#1c0c0a);border-color:#5a2620}
.pd-add:hover{border-color:#c46a5c;color:#ffdcd6}
.pd-more{display:block;margin:12px auto 4px}
@media (max-width:500px){ .pd-lv{display:none} .pd-w{padding:4px 8px;font-size:9px} }
/* build 280: the whisper button is 58x20 at 390px -- under WCAG 2.5.8's 24x24, never mind Apple's
   44 or Android's 48. It is a TOUCH problem, not a narrow-screen one (a touch tablet at 700px has
   the same 20px button), so it is keyed to the pointer rather than to a width.
   Same treatment as .title-tools > button above: the pill keeps its look and an invisible
   pseudo-element carries the touch. 44 tall because that is the axis a thumb misses on -- you come
   up from below and undershoot -- and it is free inside a 47px row, so nothing moves and no two
   rows' targets overlap (1.5px clear top and bottom). Width is left alone: 58 is already well over
   the minimum, and widening it would eat into the name.
   The cost, stated: the right-hand ~56px of a row now whispers rather than opening the profile.
   That is the trade that was chosen -- the name and the avatar, which is where you aim to open
   somebody, are the whole left of the row. */
@media all{   /* build 286: unscoped from touch, same reasoning as the rest */
  .pd-w{position:relative}
  .pd-w::after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px}
}

/* ==================================================================================
   build 285: the last of the build 281 tap-target debt.

   Deliberately at the END of the file. Build 283 put a touch block next to the rules it was
   documenting and lost on source order to a same-specificity rule 200 lines below it, costing a
   pixel that only the sweep noticed. Appending guarantees these win without anybody having to
   reason about where their neighbours live.
   ================================================================================== */
@media all{   /* build 286: was (hover:none) and (pointer:coarse); a mouse is precise but WCAG 2.5.8 does not exempt it, and two sets of sizes is two things to keep right */
  /* build 308: `.users .uzv{right:0}` lived here, with two comments explaining it -- build 301's undo
     of build 286's `right:48px`, which kept the resize handle off the minimise caret. The guard-
     deletion pass (tests/guardpass.js) removed it and nothing in the sweep noticed, because the base
     rule for .uzv already says right:0 and 286's offset had gone with 301. A guard that outlived its
     cause (trap 9). The history is in the build log, builds 286 and 301. */
  /* The handle itself was 16 tall. It grows DOWNWARD -- `top` stays at -10 and the height goes to
     24 -- and that direction is the whole point. Growing it upward (top:-14) also passed the sweep,
     but only because of what happened to be above it in that layout: probed in a layout where the
     users panel sits directly under the title bar, `div.title` painted over the handle's top 7px
     and it got 17, not 24. A target that depends on its neighbour above not covering it is a
     target that works until the layout moves. Downward it depends on nothing: the handle carries
     z-index:6 and wins over the panel beneath it.
     Growing down also leaves the visible grab bar exactly where it was -- it is drawn by ::after
     at `top:6px` from the element's own top, and that top has not moved, so no compensation is
     needed and none can be got wrong. */
  .users .uzv{height:24px}
  /* Both are padding jobs: neither sets an explicit height, so padding grows the hit box rather
     than being eaten by box-sizing, and neither sits in a scrolling or clipping container. */
  .sch-tab{padding:5px 12px}          /* 22 -> 24 */
  .hm-filter{padding:5px 10px}        /* 20 -> 24, absolutely positioned and centred on its own
                                         transform, so growing it moves nothing else */
  /* The Black Ball banner is 14 tall and lives in a flex row; padding would push the sticky bowl
     down by 10px. An invisible ::after costs no layout at all, and `.pit-bowl` sets no overflow so
     nothing clips it. The bowl itself is already clickable and opens the same page, so any pixels
     the target takes from it do the same thing they did before. */
  .pit-bowl .pb-title{position:relative}
  .pit-bowl .pb-title::after{content:"";position:absolute;left:0;right:0;top:50%;
    transform:translateY(-50%);height:24px}
}

/* ==================================================================================
   build 286: the controls only a DESKTOP viewport ever shows.

   Builds 282-285 cleared the tap-target list on a phone, and every one of those rules was keyed to
   `(hover:none) and (pointer:coarse)`. Running the same sweep at 1440x860 found 19 controls under
   24x24: the ten already fixed on touch and simply not on desktop (now unscoped above), plus these,
   which the touch sweep had never seen because they do not exist at phone width.

   Why bother, stated honestly: a cursor is precise in a way a thumb is not, so the wrong-action
   risk that made Buzz/Collapse urgent barely exists here. WCAG 2.5.8 does not exempt a mouse, but
   the real beneficiaries are trackpad users and anyone with a tremor or limited fine motor control.
   That is a narrower case than the phone work -- worth doing, not worth overselling.
   ================================================================================== */

/* The header navigation -- Home, Game room, Bell, Pit -- at 26x20 each. These are the most-used
   controls on the site and they sit in a flex row, so they take an invisible ::after rather than
   padding that would reflow the header. 26 wide already clears the minimum; only height is short. */
.in-header{position:relative}
.in-header::after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:24px}

/* A user row in the list: 142x22, tabindex="0", opens the name card. Two pixels short, and it is a
   plain block in a column, so padding is the simplest thing that can work. */
.users div[data-id]{padding-top:1px;padding-bottom:1px}

/* The comment delete/report control, 14x16 -- an inline text button with padding:0. */
.pf-cmt-x{position:relative}
.pf-cmt-x::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:24px;height:24px}

/* The column resize grip: 12 wide, full height, desktop only (hidden at <=500px). Widened to 24 and
   shifted left by the same 6 so the visible grip stays exactly where it was -- left goes -9 -> -15,
   which keeps its centre on the panel edge. Height was never the problem. */
.users .uz{left:-15px;width:24px}

/* The watermark is a real control, not decoration: app.js gives roomWatermark and rouletteWatermark
   role="button", tabindex="0" and an About bubble. 166x12. An ::after keeps the footer line where it
   is; padding would push the room's bottom edge around. */
#roomWatermark,#rouletteWatermark{position:relative}
#roomWatermark::after,#rouletteWatermark::after{content:"";position:absolute;left:0;right:0;top:50%;
  transform:translateY(-50%);height:24px}

/* "Today's readings". Padding was the obvious fix and it silently did nothing: `.sun-ref` is styled
   at three sizes -- the base, a smaller font under `.hm-sunday`, and `.td-box .sun-ref{padding:1px
   6px}` which is a two-class selector and beats a one-class rule however late it appears. Rather
   than escalate that for each variant, an ::after does not compete on padding at all and is right
   for all three. The rows wrap with a 6px gap (4px in .td-box), and the target only reaches 2-4px
   past the chip, so it stays inside the gutter. */
.sun-ref{position:relative}
.sun-ref::after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:24px}

/* ==================================================================================
   build 287: two things reported from a real iPhone, and neither reproduced in the harness.

   Chromium at iPhone 15 metrics showed no overlap in the header and no overflow in the search
   overlay. WebKit cannot be installed here (the download is blocked), and Chromium resolves every
   env(safe-area-inset-*) to 0, so the harness is blind to exactly the conditions these happen in.
   Both fixes below are therefore structural -- they remove the CONDITION that makes the failure
   possible -- rather than tuned against a measurement. Needs confirming on the device.
   ================================================================================== */
@media (max-width:500px){
  /* 1. "Gypsy Chat 2000" running under the coin purse.
     `.title-tools` is position:absolute -- out of flow -- and the title reserves room for it with
     padding. Two wrong turns before the right one, both worth keeping:

     (a) Putting the tools back into the flow so flex could keep them apart at any width. It removed
         the overlap and then made the title's OWN content exceed its box in ordinary states --
         run16 caught it, `fits:false`, the name shoved 155px off centre. The targeted probe missed
         it because it only stressed an absurd width. The full sweep is what said so.
     (b) "The reserve is stale at 96px." It is 96 only when signed OUT, where there is no purse at
         all. Signed in -- the only state with a purse -- line ~3309 has reserved **176px** all
         along, and the tools measured 164. So the reserve was never the bug.

     Which leaves the real one: the tools in the owner's state are wider than 176, and the name had
     nothing telling it to yield, so it slid underneath. Chasing the number is a losing game -- the
     purse grows with the digits and any fixed reserve is one big number from being wrong again.
     `min-width:0` plus an ellipsis makes the name shorten instead, at ANY tools width, with no
     figure to keep in step. */
  .gc-root.tools-up .win > .title .name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}

@media (max-width:560px){
  /* 2. The search/People overlay running off the screen.
     `.sch-modal` was `width:100vw`. On iOS `100vw` is the LAYOUT viewport and ignores the safe-area
     insets that `viewport-fit=cover` brings in, so on a notched iPhone -- in landscape especially --
     it is wider than the area actually on screen and the panel hangs off the edge. The overlay is
     `position:fixed` with inset 0, so `width:100%` is exactly the right box and cannot exceed it.
     The padding keeps the contents out from under the notch and the home indicator; it resolves to
     0 everywhere that has no insets, including the harness, which is why this changes nothing there
     and everything on the device. */
  /* the width itself is fixed at its own rule above; this only adds the insets. They resolve to 0
     anywhere without a notch, including this harness -- which is why the tests see no change. */
  /* build 287 added left/right/bottom and left out TOP -- in portrait the other three are 0 and the
     top is the one that matters, which is why the clock and the battery were drawn straight across
     the search field. */
  .sch-modal{padding-top:env(safe-area-inset-top);padding-left:env(safe-area-inset-left);
    padding-right:env(safe-area-inset-right);padding-bottom:env(safe-area-inset-bottom)}
}

/* ==================================================================================
   build 290: the grey flash iOS paints behind a tapped control.

   iOS paints `-webkit-tap-highlight-color` behind anything tappable, and it is a RECTANGLE that
   ignores border-radius -- which is why the round ✕ on the search panel photographed as a gold
   ellipse sitting inside a black box. Reported as iPhone-only, which is exactly right: no other
   platform draws it.

   The site already knew about this. Build ~263 set it to transparent on `.rpicker` and its buttons
   and wrote the reason in a comment, then left every other control on the site with the default.
   A fix applied to the one place it was noticed is a fix that was never finished.
   ================================================================================== */
button,a,[role="button"],[role="tab"],[role="switch"],summary,label,input,select,textarea{
  -webkit-tap-highlight-color:transparent}

/* ==================== build 311: Threads in an imageboard layout ====================
   4chan's layout in the site's own colours (see the build-311 header in app.js). One page that scrolls as
   a whole, like theirs, instead of a sidebar beside a scrolling grid. Above 640px it is their desktop page;
   at 640 and under it is their phone page, which is a different layout: a board bar that stays at the top,
   button rows, and every post a full-width card with a header band. */
.threads-panel .tp-list.ib .ib-scroll{flex:1;min-height:0;overflow-y:auto;padding:0 0 24px;scrollbar-color:var(--gold-lo) #0f0d0b}
.tp-list.ib .ib-nav{font-size:12.5px;line-height:1.7;color:var(--ash);padding:6px 12px}
.tp-list.ib .ib-nav a{color:var(--gold);text-decoration:none;margin:0 1px}
.tp-list.ib .ib-nav a:hover{color:var(--gold-hi);text-decoration:underline}
.tp-list.ib .ib-nav a.cur{color:var(--gold-hi);font-weight:700}
.tp-list.ib .ib-bar{display:none}
.ib-home,.ib-board,.ib-thead{max-width:1100px;margin:0 auto;padding:0 14px;box-sizing:border-box}
.tp-list.ib.ib-v-home .ib-board{display:none}
.tp-list.ib:not(.ib-v-home) .ib-home{display:none}
.ib-hr{border:0;border-top:1px solid #3a2e22;margin:10px 0}
/* the front page */
.ib-box{border:1px solid var(--stone-3);background:var(--stone-2);margin:14px 0}
.ib-box h3{margin:0;padding:5px 12px;font:700 15px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi);background:linear-gradient(180deg,#3a2c1c,#221910);border-bottom:1px solid var(--stone-3)}
.ib-intro{padding:9px 14px;font-size:14px;line-height:1.5;color:var(--bone)}
.tp-list.ib .ib-colset{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px 22px;padding:10px 14px 12px}
.ib-col h4{margin:0 0 4px;font:700 13px Georgia,serif;text-decoration:underline;color:var(--bone)}
.tp-list.ib .ib-col .tpx-bd{min-height:24px;padding:2px 0;border:0;border-radius:0;background:none;color:var(--gold);gap:6px;font-size:14.5px;box-shadow:none;text-shadow:none}
.tp-list.ib .ib-col .tpx-bd:hover{color:var(--gold-hi);text-decoration:underline}
.tp-list.ib .ib-col .tpx-bd.on{background:none;color:var(--gold-hi);font-weight:700}
.tp-list.ib .ib-col .tpx-ic{width:auto}
.tp-list.ib .ib-col .tpx-n{font:12px Georgia,serif;color:var(--ash)}
.ib-pop{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;padding:10px 14px 14px}
.ib-popc{display:flex;flex-direction:column;align-items:stretch;gap:4px;background:none;border:0;padding:0;color:var(--bone);font:13px Georgia,serif;cursor:pointer;text-align:center;min-width:0}
.ib-popc b{color:var(--gold-hi);font-size:13px}
.ib-popc img,.ib-popc .ib-ni{width:100%;height:120px;object-fit:cover;border:1px solid var(--stone-3);display:flex;align-items:center;justify-content:center;font-size:26px;background:#0d0a07;box-sizing:border-box}
.ib-popc:hover img{border-color:var(--gold)}
.ib-popc i{color:var(--ash);font-size:11.5px}
/* the board's heading, its links, the new-thread link and the filters */
.ib-head{text-align:center;padding:14px 0 4px}
.tp-list.ib .ib-btitle,.ib-thead .ib-btitle{margin:0;font:700 28px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);text-shadow:0 0 10px rgba(201,162,74,.35);text-align:center}
.ib-thead .ib-btitle{padding-top:10px}
.tp-list.ib .ib-bsub{display:block;color:var(--ash);font-style:italic;font-size:13px;margin-top:2px}
.ib-ctl{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px}
.ib-links{order:1;display:flex;flex-wrap:wrap;gap:2px 8px;align-items:center}
.tp-list.ib .ib-lk,.tp-detail.ib .ib-lk{background:none !important;border:0 !important;border-radius:0 !important;box-shadow:none !important;padding:0 !important;min-height:26px;
color:var(--gold) !important;font:14px Georgia,serif !important;letter-spacing:0 !important;text-shadow:none !important;cursor:pointer;text-transform:none}
.tp-list.ib .ib-lk::before,.tp-detail.ib .ib-lk::before{content:"[";color:var(--ash)}
.tp-list.ib .ib-lk::after,.tp-detail.ib .ib-lk::after{content:"]";color:var(--ash)}
.tp-list.ib .ib-lk:hover,.tp-detail.ib .ib-lk:hover{color:var(--gold-hi) !important;text-decoration:underline}
.tp-list.ib .ib-lk.hidden{display:none}
.tp-list.ib .ib-ctl .tp-new{order:0;flex:0 0 100%;justify-content:center;padding:4px 0 0;gap:0;font:700 20px Georgia,serif;letter-spacing:0;color:var(--gold);text-shadow:none}
.tp-list.ib .ib-ctl .tp-new.hidden{display:none}
.tp-list.ib .ib-ctl .tp-new .tp-new-gem{display:none}
.tp-list.ib .ib-ctl .tp-new::before{content:"[";color:var(--bone)}
.tp-list.ib .ib-ctl .tp-new::after{content:"]";color:var(--bone)}
.tp-list.ib .ib-ctl .tp-new:hover .tp-new-label{color:var(--gold-hi)}
/* the site-wide red pill (build 2xx's #tpNewBtn rule) is !important, so this has to be too */
.tp-list.ib #tpNewBtn.tp-new{background:none !important;border:0 !important;border-radius:0 !important;box-shadow:none !important;height:auto;padding:4px 0 0;gap:0;color:var(--gold) !important}
.tp-list.ib #tpNewBtn .tp-new-label{font:700 20px Georgia,serif;letter-spacing:0;color:var(--gold) !important;text-transform:none}
.tp-list.ib #tpNewBtn .tp-new-label::before{content:none}
.tp-list.ib #tpNewBtn:hover .tp-new-label{color:var(--gold-hi) !important;text-decoration:underline}
.tp-list.ib .ib-ctl .tp-tags{order:2;flex:0 1 auto;margin:0 0 0 auto;border:0;background:none;padding:0;gap:6px 8px;flex-wrap:wrap;border-radius:0}
.tp-list.ib .tp-tags .tpx-chips,.tp-list.ib .tp-tags .tpx-vsep{display:none}
.tp-list.ib .tp-tags .tpx-lbl{font:13px Georgia,serif;letter-spacing:0;text-transform:none;color:var(--ash)}
.tp-list.ib .tp-tags select{display:inline-block;height:28px;border-radius:3px;border:1px solid var(--stone-3) !important;background:var(--stone-2);color:var(--bone);font:13px Georgia,serif;padding:0 6px;max-width:170px;box-shadow:none}
/* the list: threads one under another, the whole page scrolling */
.threads-panel .tp-list.ib .tp-items{display:block;overflow:visible;padding:0;flex:none;max-width:none;width:auto;margin:0;gap:0}
.ib-thread{overflow:hidden;padding:2px 0}
.tp-list.ib .tp-item.ib-op{display:block;width:auto;padding:0;margin:0;background:none;border:0;box-shadow:none;text-align:left;cursor:pointer;color:var(--bone);font:inherit}
.tp-list.ib .tp-item.ib-op:hover{box-shadow:none}
.ib-post .ib-thumb{float:left;position:relative;display:block;margin:3px 16px 6px 0}
.threads-panel .ib-post .ib-thumb img{display:block;width:auto;height:auto;max-width:200px;max-height:170px;margin:0;border:1px solid var(--stone-3);border-radius:0;box-shadow:none;cursor:zoom-in}
.ib-reply .ib-thumb img,.threads-panel .ib-reply .ib-thumb img{max-width:125px;max-height:125px}
.ib-thumb .tp-more{top:auto;bottom:4px}
.ib-pi{font-size:13px;color:var(--ash);line-height:1.6}
.ib-pl,.ib-pr{display:inline}
.ib-pr{margin-left:5px}
.ib-dots{display:none;color:var(--ash);margin-right:6px}
.ib-sub{color:#f4e9d2;font-weight:700;font-size:15px}
/* a name is a tap target of its own (the name menu), not a word in a sentence, so it gets WCAG 2.5.8's 24px */
.threads-panel .ib-pi b.who,.threads-panel .tp-posts .tp-post .ib-pi b.who{display:inline-block;min-height:24px;line-height:24px;vertical-align:middle;font:700 13.5px/24px Georgia,serif;letter-spacing:0;color:var(--gold-hi);cursor:pointer;text-shadow:none}
.threads-panel .ib-pi b.who.admin,.threads-panel .tp-posts .tp-post .ib-pi b.who.admin{color:var(--admin);text-shadow:0 0 8px rgba(209,59,47,.45)}
.ib-pi b.who:hover{text-decoration:underline}
.ib-pi .tp-chip,.ib-pi .tp-price-chip,.ib-pi .tpx-bchip,.ib-pi .tp-place-chip{margin:0 3px;vertical-align:1px}
.ib-pi .tpx-fade{margin:0;font-size:12px}
.ib-opl{color:var(--gold);font-size:12px}
.ib-new{color:#e0453a;font-size:12px}
.ib-no,.threads-panel .tp-posts .tp-post .ib-no{color:var(--ash);text-decoration:none}
a.ib-no:hover{color:var(--gold-hi);text-decoration:underline}
.ib-pi a{color:var(--gold)}
.threads-panel .tp-posts .tp-post .ib-pr .t{color:var(--ash);font-size:13px;margin:0}
.ib-msg{margin:6px 0;font-size:14.5px;line-height:1.45;white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:var(--bone)}
.ib-msg:empty{margin:0}
.ib-ql,.ib-bl a,.ib-blstrip a{color:var(--ember) !important;text-decoration:underline}
.ib-bl a{font-size:12px;margin-left:4px}
.ib-long{font-size:12.5px;color:var(--ash);margin-top:4px;white-space:normal}
.ib-long a,.ib-omit a{color:var(--gold)}
.ib-opfoot,.ib-blstrip{display:none}
.ib-omit{color:var(--ash);font-size:13px;margin:4px 0 6px}
.ib-prevs{overflow:hidden}
/* a reply: a box beside a >> gutter, shrunk to what it holds */
.ib-post.ib-reply,.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-reply{display:table;position:relative;max-width:calc(100% - 24px);box-sizing:border-box;margin:4px 0 4px 22px;padding:4px 10px 6px 8px;
background:var(--stone-2);border:1px solid var(--stone-3);border-radius:3px;box-shadow:none;cursor:pointer}
.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-reply{cursor:default}
.ib-post.ib-reply::before{content:">>";position:absolute;left:-20px;top:5px;color:#4a3c2c;font-size:13px}
.ib-reply .ib-msg{margin:4px 0 2px 12px}
.ib-hl{animation:ib-hl 1.6s ease-out}
@keyframes ib-hl{from{background-color:rgba(224,138,44,.35)}to{background-color:var(--stone-2)}}
.ib-post .tp-pics,.ib-post .reactions{clear:both}
/* the pager and the note under it */
.threads-panel .tp-list.ib .tp-pages{justify-content:flex-start;padding:14px 0 4px}
.tp-list.ib .ib-foot{margin:10px 0 0;text-align:center;font-style:italic;font-size:12.5px;color:#7d705c}
/* the catalog */
.threads-panel .tp-list.ib .tp-items.ib-cat{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:18px 12px;padding-top:4px}
.tp-list.ib .tp-item.ib-cc{display:flex;flex-direction:column;align-items:center;width:auto;gap:2px;padding:0;background:none;border:0;box-shadow:none;text-align:center;font:12.5px Georgia,serif;color:var(--bone);min-width:0}
.tp-list.ib .tp-item.ib-cc:hover .ib-ccimg{border-color:var(--gold)}
.ib-ccimg{width:140px;height:140px;object-fit:cover;border:1px solid var(--stone-3);box-shadow:0 0 6px rgba(0,0,0,.5);margin-bottom:3px}
.ib-cc .ib-ni{width:140px;height:64px;border:1px dashed var(--stone-3);display:flex;align-items:center;justify-content:center;font-size:22px;margin-bottom:3px;box-sizing:border-box}
.ib-cnt{font-size:11px;color:var(--ash)}
.ib-cnt b{color:var(--bone)}
.ib-cch{font-weight:700;color:#f4e9d2;line-height:1.3}
.ib-ccp{color:#b7aa92;font-size:12px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.ib-ccw{color:var(--gold-hi);font-size:11.5px}
/* the thread page */
.threads-panel .tp-detail.ib .tp-posts{max-width:1100px;padding:0 14px 14px}
.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-op{background:none;border:0;border-radius:0;box-shadow:none;padding:0 0 6px;margin:0;max-width:none;overflow:hidden}
.ib-thead{padding:0}
.ib-thead .ib-ctl{margin-top:8px}
.ib-count{margin-left:auto;color:var(--ash);font-size:13px;order:2}

@media (max-width:640px){
  .tp-list.ib .ib-nav,.ib-dk{display:none !important}
  .tp-list.ib .ib-bar{display:flex;position:sticky;top:0;z-index:5;align-items:center;gap:8px;padding:6px 10px;background:var(--stone-2);border-bottom:1px solid var(--stone-3)}
  .ib-bar b{font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi)}
  .ib-bar select{flex:1;min-width:0;height:36px;background:var(--stone);color:var(--bone);border:1px solid var(--stone-3);font:15px Georgia,serif;padding:0 6px}
  .ib-home,.ib-board,.ib-thead{padding:0}
  .ib-box{margin:10px 8px}
  .tp-list.ib .ib-colset{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 16px}
  .ib-pop{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ib-head{padding:10px 8px 2px}
  .tp-list.ib .ib-btitle,.ib-thead .ib-btitle{font-size:21px;padding:0 8px}
  .ib-ctl{justify-content:center;padding:0 8px;gap:8px}
  .ib-links{order:0;flex:0 0 100%;justify-content:center;gap:6px}
  .tp-list.ib .ib-lk,.tp-detail.ib .ib-lk{background:linear-gradient(180deg,#2a2016,#17110b) !important;border:1px solid var(--gold-lo) !important;border-radius:4px !important;
  color:var(--gold-hi) !important;font:700 14px Georgia,serif !important;padding:8px 12px !important;min-height:38px}
  .tp-list.ib .ib-lk::before,.tp-list.ib .ib-lk::after,.tp-detail.ib .ib-lk::before,.tp-detail.ib .ib-lk::after{content:none}
  .tp-list.ib .ib-ctl .tp-new{order:1;flex:0 0 auto;margin:0 auto;padding:8px 14px;font-size:15px;background:linear-gradient(180deg,#2a2016,#17110b);border:1px solid var(--gold-lo);border-radius:4px;color:var(--gold-hi);min-height:40px}
  .tp-list.ib .ib-ctl .tp-new::before,.tp-list.ib .ib-ctl .tp-new::after{content:none}
  .tp-list.ib #tpNewBtn.tp-new{background:linear-gradient(180deg,#2a2016,#17110b) !important;border:1px solid var(--gold-lo) !important;border-radius:4px !important;padding:8px 14px;min-height:40px}
  .tp-list.ib #tpNewBtn .tp-new-label{font-size:15px;color:var(--gold-hi) !important}
  .tp-list.ib .ib-ctl .tp-tags{order:2;flex:0 0 100%;margin:4px 0 0;flex-wrap:nowrap;overflow:visible}
  .tp-list.ib .tp-tags .tpx-lbl{display:none}
  .tp-list.ib .tp-tags select{flex:1 1 0;min-width:0;max-width:none;height:36px;font-size:14px}
  .ib-count{flex:0 0 100%;text-align:right;padding:0 8px}
  .ib-hr{margin:8px 0}
  .tp-list.ib .tp-items > .ib-hr{display:none}
  .ib-thread{overflow:visible;padding:0;margin:0 0 10px}
  /* every post is a full-width card: a header band, the picture beside the text, then a strip */
  .tp-list.ib .tp-item.ib-op,.ib-post.ib-reply,.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-op,.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-reply{
  display:flex;flex-direction:row;flex-wrap:wrap;align-items:flex-start;width:100%;max-width:none;box-sizing:border-box;margin:0;padding:0;
  background:var(--stone-2);border:0;border-top:1px solid var(--stone-3);border-radius:0}
  .ib-post.ib-reply,.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-reply{margin:6px 0 0}
  .ib-post.ib-reply::before{content:none}
  .ib-post > *{order:3;width:100%}
  .ib-post > .ib-pi{order:0;display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:2px 8px;padding:6px 10px;box-sizing:border-box;
  background:linear-gradient(180deg,#241b12,#1a130c);border-bottom:1px solid var(--stone-3)}
  .ib-post > .ib-thumb{order:1;float:none;width:auto;flex:none;margin:10px 0 8px 10px}
  .threads-panel .ib-post .ib-thumb img,.threads-panel .ib-reply .ib-thumb img{max-width:120px;max-height:120px}
  .ib-post > .ib-msg,.ib-reply .ib-msg{order:2;flex:1 1 0;width:auto;min-width:0;margin:10px;font-size:15px}
  .ib-post > .tp-pics{margin:0 10px 8px;width:calc(100% - 20px)}
  .ib-post > .reactions{padding:0 10px 6px;box-sizing:border-box}
  .ib-dots{display:inline}
  .ib-pr{margin-left:auto;font-size:12.5px}
  .ib-sub{display:block}
  .ib-bl{display:none}
  .ib-post > .ib-blstrip:not(.hidden){display:block;order:5;padding:5px 10px;box-sizing:border-box;border-top:1px solid var(--stone-3);background:rgba(0,0,0,.2);font-size:13px}
  .ib-blstrip a{margin-right:6px}
  .ib-post > .ib-opfoot{display:flex;order:4;justify-content:space-between;align-items:center;padding:6px 10px;box-sizing:border-box;border-top:1px solid var(--stone-3);color:var(--ash);font-size:13px;
  background:linear-gradient(180deg,#1a130c,#241b12)}
  .ib-vt{background:var(--stone);color:var(--gold-hi);border:1px solid var(--gold-lo);border-radius:4px;font:700 14px Georgia,serif;padding:6px 12px;min-height:36px;cursor:pointer}
  .ib-omit{display:none}
  .threads-panel .tp-list.ib .tp-items.ib-cat{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 10px;padding:0 8px}
  .ib-ccimg,.ib-cc .ib-ni{width:100%;height:150px}
  .threads-panel .tp-list.ib .tp-pages{padding:12px 8px 4px}
  .tp-list.ib .ib-foot{padding:0 10px}
  .threads-panel .tp-detail.ib .tp-posts{padding:0 0 14px}
  .tp-list.ib .tp-items > .tp-empty,.tp-list.ib .tp-items > .sun-top,.tp-list.ib .tp-items > .mk-top,.tp-list.ib .tp-items > .mk-grid{margin-left:8px;margin-right:8px;width:auto}
}

/* ==================== build 314: Threads, "Lifted" ====================
   The owner saw a parchment palette and turned it down -- the Threads pages must stay in keeping with the rest of
   the site -- but liked its contrast between the page and what sits on it. Round two kept the site's stone and gold
   and took only that: the page goes darker, and every card (front-page boxes, the opening post and its replies, the
   catalog tiles' placeholders, the filters) is a clearly lighter warm brown with a soft shadow. On a computer each
   thread on the board page is a card of its own. Chosen over a gold-framed version (mockup-framed.css). Scoped to
   .threads-panel: nothing else on the site changes. */
.threads-panel{--stone:#050302;--stone-2:#2a1f16;--stone-3:#5c4526;--bone:#ece2cc;--ash:#a8977a;
  --m-soft:#2a1f16;--m-card:#2a1f16;background:#050302 radial-gradient(ellipse at 50% 0%,#140d07 0%,#050302 70%) !important}
.threads-panel .ib-box{background:#2a1f16;border:1px solid #5c4526;box-shadow:0 2px 10px rgba(0,0,0,.6)}
.threads-panel .ib-box h3{background:linear-gradient(180deg,#4a3620,#34261a);border-bottom-color:#5c4526;color:var(--gold-hi)}
.threads-panel .ib-intro{color:#ece2cc}
.threads-panel .ib-post.ib-reply,.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-reply{background:#2a1f16 !important;border:1px solid #5c4526 !important;box-shadow:0 2px 8px rgba(0,0,0,.55) !important}
.threads-panel .ib-post.ib-reply::before{color:#6b5638}
.threads-panel .ib-msg{color:#ece2cc}
.threads-panel .ib-sub,.threads-panel .ib-cch{color:#fff4dc}
.threads-panel .ib-hr{border-top-color:#3a2c1c}
.threads-panel .ib-post .ib-thumb img,.threads-panel .ib-ccimg,.threads-panel .ib-popc img{border-color:#7a5c30 !important;box-shadow:0 2px 8px rgba(0,0,0,.6) !important}
.threads-panel .ib-cc .ib-ni,.threads-panel .ib-popc .ib-ni{background:#2a1f16;border-color:#5c4526}
.threads-panel .tp-tags select,.threads-panel .ib-bar select{background:#2a1f16 !important;border-color:#5c4526 !important;color:#ece2cc !important}
/* on the desktop board page the opening post is a card too, so it stands off the page like the replies */
.threads-panel .tp-list.ib .ib-thread{background:#1a130d;border:1px solid #3a2c1c;border-radius:4px;padding:10px 12px;margin:0 0 12px;box-shadow:0 2px 10px rgba(0,0,0,.5)}
.threads-panel .tp-list.ib .tp-items > .ib-hr{display:none}
.threads-panel .tp-reply{background:#1a130d}
@media (max-width:640px){
  .threads-panel .tp-list.ib .ib-thread{padding:0;border:0;border-radius:0;background:none;box-shadow:none}
  .threads-panel .tp-list.ib .tp-item.ib-op,.threads-panel .ib-post.ib-reply,.threads-panel .tp-detail.ib .tp-posts .tp-post.ib-op{background:#2a1f16 !important;border:0 !important;border-top:1px solid #5c4526 !important;box-shadow:none !important}
  .threads-panel .ib-post > .ib-pi{background:linear-gradient(180deg,#43311f,#35271a) !important;border-bottom-color:#5c4526 !important}
  .threads-panel .ib-post > .ib-opfoot{background:linear-gradient(180deg,#35271a,#43311f) !important;border-top-color:#5c4526}
  .threads-panel .ib-bar{background:#1a130d;border-bottom-color:#5c4526}
}

/* ==================== build 316: fresh-eyes fixes ====================
   Signed out, the Ballot Box opened a note nobody could send (and on top of whatever was open), and the Popularity
   Contest showed an empty ladder because a signed-out visitor may not read the scores -- so the site looked dead to
   exactly the people deciding whether to join. Both wait for sign-on now. */
.gc-root:not(.signed-on) #ballotBtn,.gc-root:not(.signed-on) #leaderboardBtn{display:none !important}

/* ==================== build 317: the phone's bottom bar ====================
   Chat · Home · Threads · Games · Messages · More, with a word under every picture, replacing the ☰ Menu
   pill and the Messages pill. --nav-h is the bar's height while it shows (0 elsewhere and while typing),
   and every full-screen page, the room and the open Messages panel end that far above the bottom. */
.bnav,.bnav-sheet,.bnav-dim{display:none}
.tb-word{display:none}
@media (max-width:500px){
  .gc-root.signed-on{--nav-h:60px}
  .gc-root.signed-on.nav-typing{--nav-h:0px}
  .gc-root.signed-on:not(.nav-typing) .bnav{position:fixed;left:0;right:0;bottom:0;height:60px;z-index:46;display:flex;justify-content:space-around;align-items:stretch;
    background:linear-gradient(180deg,#1d150e,#0a0704);border-top:1px solid var(--gold-lo);box-shadow:0 -4px 14px rgba(0,0,0,.6);padding:0 4px;box-sizing:border-box}
  .bnav button{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;background:none;border:0;padding:0;margin:0;cursor:pointer;
    color:#b9a988;font:600 10.5px Georgia,serif;letter-spacing:.3px;position:relative;min-width:0;-webkit-tap-highlight-color:transparent}
  .bnav button .ic{height:24px;display:flex;align-items:center;justify-content:center;font-size:20px;line-height:1}
  .bnav button .ic img{width:24px;height:24px;object-fit:contain}
  .bnav button .lb{white-space:nowrap}
  .bnav button.on{color:var(--gold-hi)}
  .bnav button.on::before{content:"";position:absolute;top:0;left:22%;right:22%;height:2px;background:var(--gold-hi);border-radius:2px}
  .bnav button.news::after{content:"";position:absolute;top:8px;left:calc(50% + 9px);width:8px;height:8px;border-radius:50%;background:#e0b04a;box-shadow:0 0 0 2px #140e09}
  .bnav .bnav-badge{position:absolute;top:5px;left:calc(50% + 5px);min-width:16px;height:16px;border-radius:8px;background:#c8342a;color:#fff;font:700 10px/16px Georgia,serif;text-align:center;padding:0 4px;box-sizing:border-box}
  .bnav .bnav-badge.hidden{display:none}
  .gc-root.signed-on .bnav-sheet{position:fixed;left:0;right:0;bottom:60px;z-index:47;background:linear-gradient(180deg,#221810,#120c08);border-top:1px solid var(--gold-lo);border-radius:16px 16px 0 0;
    box-shadow:0 -10px 30px rgba(0,0,0,.7);padding:10px 12px 14px;display:grid;grid-template-columns:repeat(3,1fr);gap:8px;box-sizing:border-box}
  .bnav-sheet h4{grid-column:1/-1;margin:2px 4px 4px;font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;color:#8f7446;text-transform:uppercase}
  .bnav-sheet button{display:flex;flex-direction:column;align-items:center;gap:5px;padding:12px 4px;border-radius:12px;border:1px solid #3a2c1c;background:#1a130d;color:var(--bone);font:13px Georgia,serif;position:relative;cursor:pointer;min-height:44px}
  .bnav-sheet button:active{background:#241a11}
  .bnav-sheet button .ic{font-size:24px;height:28px;display:flex;align-items:center}
  .bnav-sheet button .ic img{width:28px;height:28px;object-fit:contain}
  .bnav-sheet button i{font-style:normal;font-size:10px;color:#8f836c}
  .bnav-sheet .bnav-dot{position:absolute;top:8px;right:10px;width:8px;height:8px;border-radius:50%;background:#e0b04a}
  .gc-root.signed-on .bnav-dim{display:block;position:fixed;left:0;right:0;top:0;bottom:60px;background:rgba(0,0,0,.5);z-index:46}
  /* the two pills are gone: the bar does their jobs */
  .gc-root.signed-on .fab-tray,.gc-root.signed-on .dm-dock.collapsed{display:none !important}
  /* everything full-screen stops at the bar */
  .gc-root.signed-on .win{height:calc(100dvh - 8px - var(--nav-h))}
  .gc-root.signed-on.mobile-threads-open .threads-panel,.gc-root.signed-on.admin-open .admin-panel,.gc-root.signed-on.leaderboard-open .leaderboard-panel,
  .gc-root.signed-on.mobile-roulette-open .roulette-panel,.gc-root.signed-on.gameroom-open .gameroom-panel,.gc-root.signed-on.pit-open .pit-tank,
  .gc-root.signed-on.profile-open .profile-panel,.gc-root.signed-on.home-open .home-panel,.gc-root.signed-on.hap-open .hap-panel,
  .gc-root.signed-on.circ-open .circ-panel{bottom:var(--nav-h);height:auto}
  .gc-root.signed-on .dm-dock:not(.collapsed){bottom:calc(6px + var(--nav-h));height:calc(100vh - 56px - var(--nav-h))}
  body:has(.gc-root.signed-on:not(.nav-typing)) .update-banner{bottom:68px}
  /* the header: the purse, the bell and ⚙ Settings; the scroll and the trophy live under More */
  .gc-root.signed-on #ballotBtn,.gc-root.signed-on #leaderboardBtn{display:none !important}
  .gc-root.signed-on .more-dots{display:none}
  .gc-root.signed-on .more-gear{display:inline;font-size:19px;line-height:1}
}
/* the computer: a word under each picture in the title bar */
@media (min-width:501px){
  .win > .title .tb-word{display:block;font:600 9.5px Georgia,serif;letter-spacing:.3px;color:#b9a988;margin-top:2px;text-transform:none;text-shadow:none;white-space:nowrap;line-height:1.1}
  .win > .title button:has(> .tb-word){display:inline-flex !important;flex-direction:column;align-items:center;justify-content:flex-end;height:46px !important;width:auto !important;min-width:44px;padding:3px 4px !important}
}

/* ==================== build 318: the phone's Roulette page ====================
   More → Roulette made this page reachable on a phone for the first time since build 228, and it showed only the
   Popularity Contest (the desktop column's hide rule, now scoped away from here, above). With the wheel back the
   column is taller than a short phone: centred with overflow hidden, its top was cut off and could not be reached.
   So it scrolls, and centring is done with auto margins, which give way instead of pushing the top off screen. */
@media (max-width:500px){
  .gc-root.mobile-roulette-open .roulette-panel{overflow-y:auto;justify-content:flex-start;padding-top:12px}
  .gc-root.mobile-roulette-open .roulette-panel > :first-child{margin-top:auto}
  .gc-root.mobile-roulette-open .roulette-panel > .room-watermark{margin-bottom:auto}
}

/* ==================== build 319: the first week ====================
   The "new" tag sits beside the level badge and borrows its size, so a line does not get taller for it. The colour
   is the whisper's soft violet, kept clear of the admin orange (staff) and the leaf green the vouching design
   reserved for "vouched for". */
.new-tag{display:inline-block;margin-left:4px;padding:0 5px;border:1px solid #6d5a9a;border-radius:8px;font:italic 600 10px/14px Georgia,serif;
  letter-spacing:.3px;color:#cdbdf2;background:rgba(109,90,154,.16);vertical-align:1px;text-transform:none;white-space:nowrap}
.new-tag[hidden]{display:none}
/* the setup card */
.hm-setup{border:1px solid var(--gold-lo);border-radius:6px;background:rgba(201,162,74,.05);padding:8px 10px}
.hm-setup .hm-sec-hd{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.hm-setup-n{font:italic 12px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;color:var(--ash)}
.hm-setup-bar{height:4px;border-radius:2px;background:#221a12;margin:4px 0 8px;overflow:hidden}
.hm-setup-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi));border-radius:2px}
.hm-setup-t{font:14px "IM Fell English",Georgia,serif;color:var(--bone);margin-bottom:4px}
.hm-setup-row{display:flex;align-items:center;gap:8px;min-height:40px;border-top:1px solid #2a2119;font:15px "IM Fell English",Georgia,serif;color:var(--bone)}
.hm-setup-row:first-of-type{border-top:0}
.hm-setup-ic{width:24px;flex:none;text-align:center;font-size:17px}
.hm-setup-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hm-setup-row.has-why .hm-setup-l{white-space:normal;padding:6px 0}
.hm-setup-why{display:block;font-size:13px;line-height:1.3;color:var(--ash);margin-top:2px}
.hm-setup-why b{color:#e3b27a;font-weight:normal}
.hm-setup-row.done{color:var(--ash)}
.hm-setup-row.done .hm-setup-l{text-decoration:line-through;text-decoration-color:rgba(143,131,113,.6)}
.hm-setup-row.done .hm-setup-ic{color:#8fc98f;font:700 15px Georgia,serif}
.hm-setup .sys-act{flex:none;min-width:64px;min-height:32px;padding:3px 12px;font:13px "IM Fell English",Georgia,serif;color:var(--gold-hi);background:none;border:1px solid var(--gold-lo);border-radius:14px;cursor:pointer}
.hm-setup .sys-act:hover,.hm-setup .sys-act:focus-visible{border-color:var(--gold);outline:none}
.hm-setup-hide{display:block;margin:6px 0 0 auto;min-height:32px;padding:4px 6px;background:none;border:0;color:var(--ash);font:italic 12px "IM Fell English",Georgia,serif;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
/* the push ask, inside a whisper window */
.im .ilog .m.sys.push-ask{display:flex;flex-direction:column;gap:6px;margin:6px 4px;padding:8px 10px;border:1px solid var(--gold-lo);border-radius:8px;background:rgba(201,162,74,.06);white-space:normal;font-style:normal;text-align:left}
.push-ask .pa-t{font:14px "IM Fell English",Georgia,serif;color:var(--bone);line-height:1.35}
.push-ask .pa-b{display:flex;gap:8px}
.push-ask .sys-act{min-height:32px;padding:3px 14px;font:13px "IM Fell English",Georgia,serif;color:var(--gold-hi);background:none;border:1px solid var(--gold-lo);border-radius:14px;cursor:pointer;margin:0}
.push-ask .pa-later{color:var(--ash)}

/* ==================== build 320: vouching ====================
   From the 21 September mock-up, on the classes that already exist. The mark sits in .pf-sub, the row of plain
   facts about a person, and takes the leaf green; the calling card at twenty is the plate in #5CFBC9 (the first
   choice, --ember, sat too close to the admin orange and read as staff). */
.pf-vouch{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--leaf,#5a8f5a);border-radius:12px;padding:1px 9px;background:none;cursor:pointer;color:#bfe2bf;font:inherit;font-size:13px;line-height:1.5}
.pf-vouch:hover,.pf-vouch:focus-visible{background:rgba(90,161,90,.16);outline:none}
.pf-vouch b{color:#dff0df}
.pf-plate.pf-voucher{border-color:#5CFBC9;box-shadow:0 0 14px rgba(92,251,201,.32)}
.pf-plate.pf-voucher .hd-name{color:#5CFBC9}
.pf-bring-code{display:block;width:100%;margin:6px 0 0;padding:9px 8px;border:1px solid var(--gold-lo);border-radius:4px;background:rgba(0,0,0,.35);color:var(--gold-hi);
  text-align:center;font:700 15px ui-monospace,Menlo,Consolas,monospace;letter-spacing:1px;overflow-wrap:anywhere;box-sizing:border-box;user-select:all;-webkit-user-select:all}
.pf-bring-row{display:flex;gap:6px;margin-top:7px}
.pf-bring-row .btn{flex:1;min-height:36px}
.pf-bring .vb-make{display:block;width:100%;min-height:36px;margin-top:8px}
.pf-bring .vb-note{margin-top:7px}
.pf-brought{margin-top:9px;border-top:1px solid var(--line,#2a2119);padding-top:7px}
.pf-brought > div{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:3px 0;font-size:14px}
.pf-brought .gone{opacity:.55}
.pf-brought .gone > span:first-child{text-decoration:line-through}
.pf-brought .when{display:inline-flex;align-items:center;gap:8px;color:var(--ash);font-size:11px;font-family:Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;white-space:nowrap}
.pf-take{min-height:32px;padding:1px 10px;border:1px solid #6a3a30;border-radius:14px;background:none;color:#d9a08f;font:12px Georgia,serif;letter-spacing:0;text-transform:none;cursor:pointer}
.pf-take:hover,.pf-take:focus-visible{border-color:#a0584a;outline:none}
.vb-lock{margin-top:8px;padding:9px 10px;border:1px dashed #4a3b28;border-radius:6px;font:14px "IM Fell English",Georgia,serif;color:var(--ash);text-align:center}
.vb-lock b{color:var(--bone);font-weight:normal}
.sn-vouch{margin:0 0 10px;padding:9px 11px;border:1px solid var(--leaf,#5a8f5a);border-radius:4px;background:rgba(90,161,90,.10);text-align:center}
.sn-vouch b{display:block;font:700 14px Cinzel,Georgia,serif;letter-spacing:1px;color:#bfe2bf;margin-bottom:3px}
.sn-vouch span{font-size:13px;color:var(--bone)}

/* ==================== build 321: the Roulette page's fortune under the button ====================
   Build 318 let this column scroll, but its children were still allowed to SHRINK (flex-shrink:1 is the
   default): on a phone the column is taller than the screen, so the browser squeezed the fortune to nothing
   and its text spilled out over "Back to chat" below it. Nothing in the column shrinks now; it scrolls. */
.gc-root.mobile-roulette-open .roulette-panel > *{flex-shrink:0}

/* ==================== build 322: the way in -- the lantern ====================
   Concept A of the entry mock-up, chosen by the owner (with the portrait made more visible). The title bar's own
   lantern lowers on a gold chain, lights with its violet flame, and throws candlelight; gold dust rises through it;
   the name is struck in gold letter by letter. While sign-on is still working it waits in a gentle loop; when the
   room (or the sign-on screen) is ready, the lantern flares and its light opens what is underneath in a circle
   from the flame. Everything is sized from the viewport here in CSS, so the first paint -- before app.js has run --
   is already right at 360px and at 1440px. app.js only times it (the "entry" module). */
.gc-entry{--lw:min(64px,10vh);--ch:16vh;position:fixed;inset:0;z-index:10000;overflow:hidden;background:#000;color:var(--bone);
  --lh:calc(var(--lw) * 30 / 18);--gy:calc(var(--ch) + var(--lh) * .62);--ty:calc(var(--ch) + var(--lh) + 7vh);
  --fs:min(34px,9.2vw);--ts:17px;--rm:14px;--sm:34px;--ww:min(105vw,90vh);--wy:28vh;
  animation:ge-failsafe 0s linear 15s forwards}
@media (min-width:501px){.gc-entry{--lw:min(104px,12vh);--ch:14vh;--ty:calc(var(--ch) + var(--lh) + 6vh);--fs:min(64px,4.5vw);--ts:21px;--rm:18px;--sm:42px;--ww:min(50vw,90vh);--wy:18vh}}
@keyframes ge-failsafe{to{visibility:hidden;pointer-events:none}}
.gc-entry.js{animation:none}
.gc-entry.off{display:none}
.ge-veil{position:absolute;inset:0;background:radial-gradient(120% 90% at 50% 38%,#0d0906 0%,#050302 55%,#000 100%)}
/* the portrait from the room's wall -- build 322 at the owner's word: "a little more visible" than the mock-up's 7.5% */
.ge-woman{position:absolute;left:50%;top:var(--wy);width:var(--ww);aspect-ratio:460/430;transform:translate(-50%,0) scale(1.04);
  background:url(../img/gypsy-woman.png) center/contain no-repeat;opacity:0;filter:sepia(1) saturate(.8) brightness(.95);transition:opacity 1.6s ease .4s,transform 6s ease .4s}
.gc-entry.s-lit .ge-woman,.gc-entry.s-wait .ge-woman{opacity:.17;transform:translate(-50%,0) scale(1)}
.ge-dust{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;opacity:0;transition:opacity 1.6s ease}
.gc-entry.s-lit .ge-dust,.gc-entry.s-wait .ge-dust,.gc-entry.s-out .ge-dust{opacity:1}
.ge-hang{position:absolute;left:50%;top:0;width:var(--lw);transform:translate(-50%,-110%);transform-origin:50% 0}
.gc-entry.s-in .ge-hang,.gc-entry.s-lit .ge-hang,.gc-entry.s-wait .ge-hang{animation:ge-drop 1.25s cubic-bezier(.2,.9,.25,1.12) forwards,ge-sway 5.5s ease-in-out 1.25s infinite}
.gc-entry.s-quick .ge-hang{animation:ge-sway 5.5s ease-in-out infinite;transform:translate(-50%,0)}
@keyframes ge-drop{from{transform:translate(-50%,-110%)}to{transform:translate(-50%,0)}}
@keyframes ge-sway{0%,100%{transform:translate(-50%,0) rotate(0deg)}30%{transform:translate(-50%,0) rotate(1.4deg)}70%{transform:translate(-50%,0) rotate(-1.2deg)}}
.ge-chain{display:block;width:2px;height:var(--ch);margin:0 auto;background:repeating-linear-gradient(180deg,var(--gold) 0 5px,transparent 5px 7px);opacity:.75}
.ge-lantern{display:block;width:100%;height:auto;overflow:visible;filter:drop-shadow(0 6px 10px #000)}
.ge-lantern .lt-hook{fill:none;stroke:var(--gold);stroke-width:1.1}
.ge-lantern .lt-cap{fill:var(--gold);stroke:var(--gold-lo);stroke-width:.6;stroke-linejoin:round}
.ge-lantern .lt-glass{fill:rgba(186,70,255,.06);transition:fill 1s ease}
.gc-entry.s-lit .ge-lantern .lt-glass,.gc-entry.s-wait .ge-lantern .lt-glass,.gc-entry.s-out .ge-lantern .lt-glass{fill:rgba(186,70,255,.3)}
.ge-lantern .lt-pane{fill:none;stroke:var(--gold);stroke-width:1.1}
.ge-lantern .lt-bars{fill:none;stroke:var(--gold-lo);stroke-width:.7}
.ge-lantern .lt-flame{transform-box:fill-box;transform-origin:50% 100%;transform:scale(0);opacity:0}
.gc-entry.s-lit .ge-lantern .lt-flame,.gc-entry.s-wait .ge-lantern .lt-flame,.gc-entry.s-out .ge-lantern .lt-flame{animation:ge-ignite .9s cubic-bezier(.3,1.6,.5,1) forwards,ge-flicker 1.1s ease-in-out .9s infinite}
@keyframes ge-ignite{0%{transform:scale(0);opacity:0}40%{transform:scale(1.35,1.5);opacity:1}100%{transform:scale(1);opacity:1}}
@keyframes ge-flicker{0%,100%{transform:scale(1,1) skewX(0)}25%{transform:scale(.94,1.07) skewX(2deg)}50%{transform:scale(1.04,.95) skewX(-1.5deg)}75%{transform:scale(.97,1.04) skewX(1deg)}}
.ge-glow{position:absolute;left:50%;top:var(--gy);width:0;height:0;pointer-events:none}
.ge-glow i{position:absolute;left:0;top:0;border-radius:50%;transform:translate(-50%,-50%) scale(.2);opacity:0;transition:transform 1.6s cubic-bezier(.2,.8,.2,1),opacity 1.2s ease}
.ge-glow .ge-g1{width:min(70vmin,420px);height:min(70vmin,420px);background:radial-gradient(circle,rgba(229,139,255,.42) 0%,rgba(195,60,255,.16) 35%,transparent 68%);mix-blend-mode:screen}
.ge-glow .ge-g2{width:min(170vmin,1400px);height:min(170vmin,1400px);background:radial-gradient(circle,rgba(237,201,158,.13) 0%,rgba(207,152,82,.06) 30%,transparent 62%);mix-blend-mode:screen}
.gc-entry.s-lit .ge-glow i,.gc-entry.s-wait .ge-glow i,.gc-entry.s-out .ge-glow i{transform:translate(-50%,-50%) scale(1);opacity:1}
.gc-entry.s-wait .ge-g1{animation:ge-breathe 2.6s ease-in-out infinite}
@keyframes ge-breathe{0%,100%{opacity:1}50%{opacity:.72}}
.ge-words{position:absolute;left:0;right:0;top:var(--ty);text-align:center;padding:0 16px}
.ge-name{position:relative;display:inline-block;font:700 var(--fs)/1.05 Cinzel,Georgia,serif;letter-spacing:.06em;white-space:nowrap}
.ge-name span{display:inline-block;font-kerning:none;opacity:0;transform:translateY(.25em);filter:blur(6px);
  background:linear-gradient(180deg,#fff3d6 0%,var(--gold-hi) 30%,var(--gold) 62%,#7d5a26 100%);-webkit-background-clip:text;background-clip:text;color:transparent}
.gc-entry.s-lit .ge-name span,.gc-entry.s-wait .ge-name span,.gc-entry.s-out .ge-name span{animation:ge-letter .9s cubic-bezier(.2,.7,.2,1) forwards;animation-delay:calc(.9s + var(--i) * 45ms)}
.gc-entry.s-quick .ge-name span{animation-delay:calc(var(--i) * 25ms)}
@keyframes ge-letter{to{opacity:1;transform:none;filter:blur(0)}}
/* while it waits, a soft light passes along the name (build 323: the owner found the letter-by-letter glint of 322
   too square -- each letter lit whole and went dark whole). A second copy of the name lies exactly over the first,
   drawn only where a wide, feathered band of light is, so the light crosses the letters, not the spaces between. */
.ge-name::after{content:attr(data-t);position:absolute;left:0;top:0;right:0;bottom:0;white-space:nowrap;font-kerning:none;pointer-events:none;
  background:linear-gradient(105deg,transparent 0%,transparent 34%,rgba(255,244,214,.18) 41%,rgba(255,248,230,.95) 50%,rgba(255,244,214,.18) 59%,transparent 66%,transparent 100%);
  background-size:250% 100%;background-position:100% 0;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;color:transparent;opacity:0}
.gc-entry.s-wait .ge-name::after{opacity:1;animation:ge-sheen 4.2s ease-in-out infinite}
@keyframes ge-sheen{0%{background-position:100% 0}60%,100%{background-position:0% 0}}
.ge-rule{position:relative;height:14px;width:min(78vw,420px);margin:var(--rm) auto 0}
.ge-rule::before,.ge-rule::after{content:"";position:absolute;top:50%;height:1px;width:calc(50% - 12px);background:linear-gradient(90deg,transparent,var(--gold));transform:scaleX(0);transition:transform 1.1s cubic-bezier(.2,.8,.2,1) 2s}
.ge-rule::before{right:calc(50% + 12px);transform-origin:right}
.ge-rule::after{left:calc(50% + 12px);background:linear-gradient(270deg,transparent,var(--gold));transform-origin:left}
.ge-rule b{position:absolute;left:50%;top:50%;width:8px;height:8px;border:1px solid var(--gold);transform:translate(-50%,-50%) rotate(45deg) scale(0);transition:transform .6s cubic-bezier(.3,1.6,.5,1) 1.9s;background:rgba(195,60,255,.35)}
.gc-entry.s-lit .ge-rule::before,.gc-entry.s-lit .ge-rule::after,.gc-entry.s-wait .ge-rule::before,.gc-entry.s-wait .ge-rule::after,.gc-entry.s-out .ge-rule::before,.gc-entry.s-out .ge-rule::after{transform:scaleX(1)}
.gc-entry.s-lit .ge-rule b,.gc-entry.s-wait .ge-rule b,.gc-entry.s-out .ge-rule b{transform:translate(-50%,-50%) rotate(45deg) scale(1)}
.ge-tag{margin-top:12px;font:italic var(--ts) "IM Fell English",Georgia,serif;color:var(--bone);opacity:0;transform:translateY(6px);transition:opacity 1s ease 2.3s,transform 1s ease 2.3s}
.gc-entry.s-lit .ge-tag,.gc-entry.s-wait .ge-tag,.gc-entry.s-out .ge-tag{opacity:.9;transform:none}
.ge-status{margin-top:var(--sm);font:700 10.5px Cinzel,Georgia,serif;letter-spacing:.28em;text-transform:uppercase;color:var(--ash);opacity:0;transition:opacity .8s ease 2.8s;min-height:1.5em}
.ge-status em{font-style:normal;display:inline-block;transition:opacity .45s ease,transform .45s ease}
.ge-status em.swap{opacity:0;transform:translateY(-4px)}
.ge-thread{position:relative;width:min(46vw,190px);height:1px;margin:12px auto 0;background:rgba(113,77,32,.55);overflow:hidden;opacity:0;transition:opacity .8s ease 2.8s}
.gc-entry.s-wait .ge-status,.gc-entry.s-wait .ge-thread,.gc-entry.s-lit .ge-status,.gc-entry.s-lit .ge-thread{opacity:1}
.gc-entry.s-quick .ge-rule::before,.gc-entry.s-quick .ge-rule::after,.gc-entry.s-quick .ge-rule b,.gc-entry.s-quick .ge-tag,.gc-entry.s-quick .ge-status,.gc-entry.s-quick .ge-thread,.gc-entry.s-quick .ge-woman,.gc-entry.s-quick .ge-glow i{transition-delay:0s}
.ge-thread::after{content:"";position:absolute;top:0;left:-40%;width:40%;height:100%;background:linear-gradient(90deg,transparent,var(--gold-hi),transparent);animation:ge-run 1.6s ease-in-out infinite}
@keyframes ge-run{to{left:100%}}
/* the way out: app.js grows a hole in this layer from the flame (--gr), so the room shows through the light */
.gc-entry.s-out{-webkit-mask-image:radial-gradient(circle at 50% var(--gy),transparent var(--gr,0px),#000 calc(var(--gr,0px) + 2px));mask-image:radial-gradient(circle at 50% var(--gy),transparent var(--gr,0px),#000 calc(var(--gr,0px) + 2px))}
.gc-entry.s-out .ge-words,.gc-entry.s-out .ge-hang{transition:opacity .5s ease;opacity:0}
.ge-flash{position:absolute;left:50%;top:var(--gy);width:10px;height:10px;border-radius:50%;transform:translate(-50%,-50%);background:radial-gradient(circle,#fff6e6 0%,rgba(237,201,158,.8) 30%,rgba(195,60,255,.25) 60%,transparent 72%);opacity:0;pointer-events:none}
.gc-entry.s-out .ge-flash{animation:ge-flash 1.1s ease-out forwards}
@keyframes ge-flash{0%{opacity:0;width:10px;height:10px}25%{opacity:1}100%{opacity:0;width:260vmax;height:260vmax}}
.gc-entry.s-fade{transition:opacity .45s ease;opacity:0}
@media (prefers-reduced-motion:reduce){
  .ge-hang,.ge-lantern .lt-flame,.ge-thread::after,.ge-g1,.ge-name::after{animation:none!important}
  .ge-name::after{display:none}
  .gc-entry .ge-hang{transform:translate(-50%,0)!important}
  .ge-lantern .lt-flame{transform:none;opacity:1}
  .ge-name span{animation:none!important;opacity:1;transform:none;filter:none}
  .gc-entry *{transition-delay:0s!important}
}

/* ---------- build 324: motion batch 1 — level-up, coins that fly, reactions ---------- */
.fx-layer{position:fixed;inset:0;z-index:9500;pointer-events:none;overflow:hidden}
.fx-canvas{position:absolute;inset:0;width:100%;height:100%}
.fx-ring{position:absolute;width:var(--fx-s,150px);height:var(--fx-s,150px);border-radius:50%;border:2px solid var(--fx-c,rgba(237,201,158,.95));
  box-shadow:0 0 14px var(--fx-c,rgba(237,201,158,.6)),inset 0 0 10px var(--fx-c,rgba(237,201,158,.4));transform:translate(-50%,-50%) scale(.08);opacity:0;
  animation:fx-ring 1.05s cubic-bezier(.15,.7,.3,1) both}
@keyframes fx-ring{0%{transform:translate(-50%,-50%) scale(.08);opacity:0}12%{opacity:1}100%{transform:translate(-50%,-50%) scale(1);opacity:0;border-width:.5px}}
.fx-coin{position:absolute;left:0;top:0;width:16px;height:16px;border-radius:50%;will-change:transform;
  background:radial-gradient(circle at 35% 30%,#fff3d6 0,#edc99e 25%,#cf9852 60%,#8a6428 100%);
  box-shadow:0 0 0 1px #714d20,0 0 10px rgba(255,210,120,.75)}
.fx-coin::after{content:"";position:absolute;inset:4px;border-radius:50%;border:1px solid rgba(113,77,32,.7)}
.fx-spark{position:absolute;left:0;top:0;width:4px;height:4px;border-radius:50%;background:#ffe6aa;box-shadow:0 0 6px rgba(255,210,120,.95)}
/* the badge turns over like a coin */
.lvl.lvl-flip{display:inline-block;animation:lvl-flip .8s cubic-bezier(.3,.7,.3,1)}
@keyframes lvl-flip{0%{transform:perspective(200px) rotateX(0)}45%{transform:perspective(200px) rotateX(90deg) scale(1.15);filter:brightness(2)}100%{transform:perspective(200px) rotateX(0)}}
.lvl.lvl-charge{box-shadow:0 0 0 1px var(--gold-hi,#edc99e),0 0 14px 3px rgba(255,210,120,.8);animation:lvl-charge 1.1s ease-out}
.lvl.lvl-flip.lvl-charge{animation:lvl-flip .8s cubic-bezier(.3,.7,.3,1),lvl-charge 1.1s ease-out}
@keyframes lvl-charge{0%{box-shadow:0 0 0 0 rgba(255,210,120,0)}30%{box-shadow:0 0 0 2px #fff3d6,0 0 22px 6px rgba(255,210,120,.95)}100%{box-shadow:0 0 0 0 rgba(255,210,120,0)}}
/* the banner across the top of the room */
.lvl-banner{position:absolute;left:50%;top:54px;z-index:60;display:flex;align-items:center;gap:10px;white-space:nowrap;pointer-events:none;
  padding:9px 18px;border-radius:12px;background:linear-gradient(180deg,rgba(28,20,12,.97),rgba(10,7,4,.97));
  box-shadow:0 0 0 1px var(--gold,#cf9852),0 0 0 3px #000,0 10px 30px rgba(0,0,0,.8),0 0 30px rgba(207,152,82,.3);
  transform:translate(-50%,-24px);opacity:0;overflow:hidden}
.lvl-banner b{font:700 17px Cinzel,Georgia,serif;letter-spacing:.06em;color:transparent;background:linear-gradient(180deg,#fff3d6,#edc99e 40%,#cf9852);-webkit-background-clip:text;background-clip:text}
.lvl-banner .lvl{margin:0;font-size:11px}
.lvl-banner i{font:italic 13px "IM Fell English",Georgia,serif;color:var(--bone,#cdc1a6)}
.lvl-banner::after{content:"";position:absolute;top:0;bottom:0;left:-40%;width:35%;background:linear-gradient(100deg,transparent,rgba(255,243,214,.35),transparent);filter:blur(4px)}
.lvl-banner.go{animation:lvl-banner 3.3s cubic-bezier(.2,.8,.2,1) forwards}
.lvl-banner.go::after{animation:lvl-sweep 1.1s .35s ease-in-out}
@keyframes lvl-banner{0%{transform:translate(-50%,-24px);opacity:0}12%{transform:translate(-50%,0);opacity:1}82%{transform:translate(-50%,0);opacity:1}100%{transform:translate(-50%,-10px);opacity:0}}
@keyframes lvl-sweep{from{left:-40%}to{left:110%}}
@media (max-width:500px){.lvl-banner{top:48px;padding:8px 13px;gap:8px}.lvl-banner b{font-size:15px}.lvl-banner i{font-size:12px}}
/* the purse takes the coins and rolls */
#purseChip.coin-land{animation:coin-land .32s ease-out}
@keyframes coin-land{0%{transform:scale(1)}40%{transform:scale(1.14);filter:brightness(1.5)}100%{transform:scale(1)}}
.purse-chip .pc-amt{display:inline-block}
.purse-chip .pc-amt.tick{animation:pc-tick .12s ease-out}
@keyframes pc-tick{from{transform:translateY(-3px);opacity:.6}to{transform:none;opacity:1}}
/* reactions roll and pop */
.react-pill span{display:inline-block}
.react-pill span.roll-up{animation:rx-up .38s cubic-bezier(.2,.8,.2,1)}
.react-pill span.roll-down{animation:rx-down .38s cubic-bezier(.2,.8,.2,1)}
@keyframes rx-up{from{transform:translateY(9px);opacity:0}to{transform:none;opacity:1}}
@keyframes rx-down{from{transform:translateY(-9px);opacity:0}to{transform:none;opacity:1}}
.react-pill.rx-pop{animation:rx-pop .45s cubic-bezier(.3,1.6,.5,1)}
@keyframes rx-pop{0%{transform:scale(.6)}60%{transform:scale(1.18)}100%{transform:scale(1)}}
@media (prefers-reduced-motion:reduce){
  .fx-layer{display:none}
  .lvl.lvl-flip,.lvl.lvl-charge,#purseChip.coin-land,.purse-chip .pc-amt.tick,.react-pill span.roll-up,.react-pill span.roll-down,.react-pill.rx-pop{animation:none!important}
  .lvl-banner.go{animation:lvl-fade 3.3s linear forwards}.lvl-banner.go::after{animation:none}
  @keyframes lvl-fade{0%,100%{opacity:0;transform:translate(-50%,0)}8%,85%{opacity:1;transform:translate(-50%,0)}}
}

/* ---------- build 325: motion batch 2 — the bar glides, the bell swings, one lantern waits ---------- */
.bnav-ind{position:absolute;left:0;width:34px} /* the bar's gold line; it only shows on a phone, where it glides */
@media (max-width:500px){
  .bnav button.on::before{display:none}
  .bnav .bnav-ind{position:absolute;top:0;left:0;width:34px;height:2px;border-radius:2px;background:var(--gold-hi);box-shadow:0 0 10px rgba(237,201,158,.8);pointer-events:none;
    transition:left .42s cubic-bezier(.3,.7,.2,1),width .42s cubic-bezier(.3,.7,.2,1),opacity .25s}
  .bnav .bnav-ind.off{opacity:0}
  .bnav button .ic{transition:transform .35s cubic-bezier(.3,1.6,.5,1)}
  .bnav button.on .ic{transform:translateY(-2px) scale(1.12)}
  /* over build 241's rise-and-fade, which every page runs as it opens: from the bar, the page comes in sideways instead */
  .gc-root .bnav-in-r{animation:bnav-in-r .38s cubic-bezier(.3,.7,.2,1) !important}
  .gc-root .bnav-in-l{animation:bnav-in-l .38s cubic-bezier(.3,.7,.2,1) !important}
}
@keyframes bnav-in-r{from{translate:34% 0;opacity:.2}to{translate:0 0;opacity:1}}
@keyframes bnav-in-l{from{translate:-34% 0;opacity:.2}to{translate:0 0;opacity:1}}
/* the bell */
.bell-ic{display:inline-block;transform-origin:50% 8%}
.bell-ic.swing{animation:bell-swing 1.6s cubic-bezier(.3,.6,.4,1)}
@keyframes bell-swing{0%{transform:rotate(0)}12%{transform:rotate(22deg)}26%{transform:rotate(-18deg)}40%{transform:rotate(13deg)}54%{transform:rotate(-9deg)}68%{transform:rotate(5deg)}82%{transform:rotate(-2deg)}100%{transform:rotate(0)}}
#bellBadge.pop{animation:bell-pop .5s cubic-bezier(.3,1.9,.5,1)}
@keyframes bell-pop{0%{transform:scale(0)}100%{transform:scale(1)}}
/* one loading look */
.gc-load{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;padding:14px 0;margin:0 auto;font-style:normal}
.gc-load .gl-lan{position:relative;width:22px;animation:gl-sway 3s ease-in-out infinite;transform-origin:50% -26px}
.gc-load .gl-lan::before{content:"";position:absolute;left:50%;top:55%;width:90px;height:90px;transform:translate(-50%,-50%);border-radius:50%;background:radial-gradient(circle,rgba(195,60,255,.22),transparent 65%);pointer-events:none;animation:gl-br 2.6s ease-in-out infinite}
.gc-load svg{position:relative;display:block;width:100%;height:auto;overflow:visible;filter:drop-shadow(0 0 8px rgba(195,60,255,.55))}
.gc-load .gl-s{fill:none;stroke:#cf9852;stroke-width:1.1}
.gc-load .gl-g{fill:#cf9852}
.gc-load .gl-b{fill:none;stroke:#714d20;stroke-width:.7}
.gc-load .gl-fl{transform-box:fill-box;transform-origin:50% 100%;animation:gl-flk 1.1s ease-in-out infinite}
.gc-load .gl-word{font:700 10px Cinzel,Georgia,serif;letter-spacing:.28em;text-transform:uppercase;color:#8f8371}
.gc-load .gl-thread{position:relative;display:block;width:120px;height:1px;background:rgba(113,77,32,.55);overflow:hidden}
.gc-load .gl-thread::after{content:"";position:absolute;top:0;left:-40%;width:40%;height:100%;background:linear-gradient(90deg,transparent,#edc99e,transparent);animation:gl-run 1.6s ease-in-out infinite}
@keyframes gl-sway{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(4deg)}}
@keyframes gl-flk{0%,100%{transform:scale(1)}50%{transform:scale(.92,1.08)}}
@keyframes gl-br{0%,100%{opacity:.6}50%{opacity:1}}
@keyframes gl-run{from{left:-40%}to{left:100%}}
@media (prefers-reduced-motion:reduce){
  .bnav .bnav-ind{transition:none}.bnav button .ic{transition:none}
  .gc-root .bnav-in-r,.gc-root .bnav-in-l,.bell-ic.swing,#bellBadge.pop{animation:none!important}
  .gc-load .gl-lan,.gc-load .gl-lan::before,.gc-load .gl-fl,.gc-load .gl-thread::after{animation:none!important}
  .gc-load .gl-thread::after{left:30%}
}

/* ---------- build 326: motion batch 3 — the name card, the whisper letter, a new arrival ---------- */
/* the name card */
/* only the name card (.nc-anim, set by openMenu; not the status menu or the other small menus that share .nmenu).
   It is revealed from its bottom edge upward with a clip, and nothing in it moves: the popover guards and the
   on-screen checks measure the card's box while it opens, and a scale or a slide changed that box */
.nmenu.open.nc-anim{animation:nc-up .45s cubic-bezier(.2,.8,.2,1)}
@keyframes nc-up{from{opacity:.2;clip-path:inset(100% 0 0 0)}to{opacity:1;clip-path:inset(0 0 0 0)}}
.nmenu .pcard{position:relative;overflow:hidden}
.nmenu .pcard::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(110deg,transparent 30%,rgba(255,240,210,.2) 48%,rgba(255,240,210,.05) 56%,transparent 70%);background-size:250% 100%;background-position:120% 0}
.nmenu.open .pcard::after{animation:nc-sweep 1s ease .25s both}
@keyframes nc-sweep{from{background-position:120% 0}to{background-position:-20% 0}}
.nmenu .pc-bar i{transform-origin:0 50%}
.nmenu.open .pc-bar i{animation:nc-fill 1.1s cubic-bezier(.2,.8,.2,1) .3s both}
@keyframes nc-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.nmenu.open .pc-view,.nmenu.open .pc-sec{animation:nc-settle .38s ease both}
.nmenu.open .pc-view{animation-delay:.28s}
.nmenu.open .pc-sec:nth-child(1){animation-delay:.34s}.nmenu.open .pc-sec:nth-child(2){animation-delay:.40s}
.nmenu.open .pc-sec:nth-child(3){animation-delay:.46s}.nmenu.open .pc-sec:nth-child(4){animation-delay:.52s}
@keyframes nc-settle{from{opacity:0}to{opacity:1}}
/* foil from level 5: on the card and on a page */
.nmenu .lvl.lvl-foil,.profile-panel .lvl.lvl-foil{position:relative;overflow:hidden}
.nmenu .lvl.lvl-foil::after,.profile-panel .lvl.lvl-foil::after{content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;mix-blend-mode:screen;
  background:linear-gradient(105deg,transparent 20%,rgba(255,120,220,.55) 35%,rgba(255,240,170,.75) 45%,rgba(120,230,255,.55) 55%,transparent 70%);background-size:300% 100%;background-position:100% 0;
  animation:lvl-foil 3.6s ease-in-out infinite}
@keyframes lvl-foil{0%,55%{background-position:100% 0}100%{background-position:-200% 0}}
/* the whisper letter: the envelope on the phone's bar */
.bnav .env{width:26px;height:24px;overflow:visible}
.bnav .env-body{fill:#2a1f3d;stroke:#b48be8;stroke-width:1.2;stroke-linejoin:round}
.bnav .env-fold{fill:none;stroke:#6f55a0;stroke-width:1}
.bnav .env-letter{fill:#efe3c4}
.bnav .env-lines{fill:none;stroke:#b39868;stroke-width:.9}
.bnav .env-paper{transform:translateY(3px);transition:transform .4s cubic-bezier(.3,1.5,.5,1)}
.bnav .env-flap,.bnav .env-flap-up{transform-box:fill-box;transition:transform .22s ease-in}
.bnav .env-flap{transform-origin:50% 0}
.bnav .env-flap-up{transform-origin:50% 100%;transform:scaleY(0)}
.bnav .env-flap path,.bnav .env-flap-up path{fill:#3a2c55;stroke:#b48be8;stroke-width:1.2;stroke-linejoin:round}
.bnav .env-flap-up path{fill:#241a36}
.bnav #bnavMessages:has(.bnav-badge:not(.hidden)) .env-flap{transform:scaleY(0)}
.bnav #bnavMessages:has(.bnav-badge:not(.hidden)) .env-flap-up{transform:scaleY(1);transition:transform .25s ease-out .2s}
.bnav #bnavMessages:has(.bnav-badge:not(.hidden)) .env-paper{transform:translateY(-3px);transition-delay:.4s}
/* the Messages window unfolds up as it opens */
.dm-dock:not(.collapsed) .dm-body{animation:dm-unfold .5s cubic-bezier(.2,.9,.3,1.05);transform-origin:50% 100%}
@keyframes dm-unfold{0%{transform:perspective(900px) rotateX(-70deg);opacity:0}35%{opacity:1}100%{transform:none;opacity:1}}
/* a whisper that arrives inks in */
.im .ilog .m.ink{-webkit-mask-image:linear-gradient(90deg,#000 0,#000 40%,transparent 60%);mask-image:linear-gradient(90deg,#000 0,#000 40%,transparent 60%);
  -webkit-mask-size:260% 100%;mask-size:260% 100%;animation:im-ink 1.1s ease-out both}
@keyframes im-ink{from{-webkit-mask-position:100% 0;mask-position:100% 0;filter:blur(1.5px);opacity:.3}to{-webkit-mask-position:0 0;mask-position:0 0;filter:none;opacity:1}}
/* the quill while they write */
.typing-indicator:not(.hidden):not(:empty)::before{content:"✒️";display:inline-block;margin-right:5px;font-style:normal;animation:im-quill .5s ease-in-out infinite}
@keyframes im-quill{0%,100%{transform:rotate(-8deg) translateX(0)}50%{transform:rotate(6deg) translateX(2px)}}
/* a new arrival: the tiny lantern */
.new-lan{display:inline-block;width:9px;margin-left:3px;vertical-align:-2px;filter:drop-shadow(0 0 4px rgba(195,60,255,.7))}
.new-lan svg{display:block;width:100%;height:auto;overflow:visible}
.new-lan .gl-s{fill:none;stroke:#cf9852;stroke-width:1.2}
.new-lan .gl-g{fill:#cf9852}
.new-lan .nl-glass{fill:rgba(186,70,255,.3);animation:nl-glow 1s ease .6s both}
.new-lan .nl-fl{transform-box:fill-box;transform-origin:50% 100%;animation:nl-ign .6s cubic-bezier(.3,1.6,.5,1) .5s both,gl-flk 1.1s ease-in-out 1.2s infinite}
@keyframes nl-ign{from{transform:scale(0)}to{transform:scale(1)}}
@keyframes nl-glow{from{fill:rgba(186,70,255,0)}to{fill:rgba(186,70,255,.3)}}
/* and the wax seal on a page */
.pf-vouch{position:relative;animation:pf-stamp .5s cubic-bezier(.5,0,.3,1.2) .35s both}
.pf-vouch::after{content:"";position:absolute;inset:-4px;border-radius:16px;border:2px solid rgba(143,201,143,.8);opacity:0;pointer-events:none;animation:pf-sring .6s ease-out .75s}
@keyframes pf-stamp{0%{opacity:0;transform:scale(1.8);filter:blur(2px)}70%{opacity:1;transform:scale(.94);filter:none}100%{opacity:1;transform:scale(1)}}
@keyframes pf-sring{0%{opacity:.9;transform:scale(.9)}100%{opacity:0;transform:scale(1.35)}}
@media (prefers-reduced-motion:reduce){
  .nmenu.open.nc-anim,.nmenu.open .pcard::after,.nmenu.open .pc-bar i,.nmenu.open .pc-view,.nmenu.open .pc-sec,.dm-dock:not(.collapsed) .dm-body,.im .ilog .m.ink,
  .typing-indicator:not(.hidden):not(:empty)::before,.new-lan .nl-glass,.new-lan .nl-fl,.pf-vouch,.pf-vouch::after{animation:none!important}
  .nmenu .lvl.lvl-foil::after{animation:none;background-position:50% 0}.profile-panel .lvl.lvl-foil::after{animation:none;background-position:50% 0}
  .bnav .env-flap,.bnav .env-flap-up,.bnav .env-paper{transition:none!important}
}

/* ---------- build 327: motion batch 4 — the Pit, winning, the Contest ---------- */
.fx-drop{position:absolute;left:0;top:0;width:4px;height:4px;border-radius:50%;background:rgba(170,215,245,.9);pointer-events:none;z-index:3}
/* the 8-ball, the trapdoor and the falling name */
.fx-ball{position:absolute;left:0;top:0;width:28px;height:28px;filter:drop-shadow(0 4px 6px rgba(0,0,0,.8));will-change:transform}
.fx-ball.fall{animation:fx-ball-fall .7s cubic-bezier(.5,0,.9,.5) forwards}
@keyframes fx-ball-fall{to{translate:0 90px;opacity:0}}
.fx-trap{position:absolute;height:3px;margin-top:0;background:linear-gradient(90deg,#1a120b,#3a2c1c,#1a120b);box-shadow:0 0 0 1px #000;transform-origin:0 50%}
.fx-trap::after{content:"";position:absolute;inset:0;background:inherit;transform-origin:100% 50%}
.fx-trap.open{animation:fx-trap-l .3s ease-in forwards}
.fx-trap.open::after{animation:fx-trap-r .3s ease-in forwards}
@keyframes fx-trap-l{to{transform:rotate(70deg) scaleX(.5)}}
@keyframes fx-trap-r{to{transform:rotate(-70deg)}}
.fx-fall{position:absolute;margin:0;white-space:nowrap;font:700 13px Cinzel,Georgia,serif;color:#e6b25a;pointer-events:none}
.fx-fall.go{animation:fx-fall .9s cubic-bezier(.55,0,1,.45) .08s forwards}
@keyframes fx-fall{to{translate:6px 120px;rotate:24deg;opacity:0;filter:blur(1px)}}
.m b.who.pit-gone{visibility:hidden}
/* the tank: a splash, ripples */
.pit-tank .pt-ripple{position:absolute;width:60px;height:14px;margin:-7px 0 0 -30px;border:1.5px solid rgba(180,220,255,.75);border-radius:50%;pointer-events:none;opacity:0;animation:pt-ripple 1.1s ease-out both}
@keyframes pt-ripple{0%{opacity:.9;transform:scale(.2)}100%{opacity:0;transform:scale(1.8)}}
.pit-tank .pt-fish.pt-diving .ava,.pit-tank .pt-fish.pt-diving .ava-fallback{box-shadow:0 0 0 2px rgba(180,220,255,.6)}
/* the climbing wall: a climber, hand over hand */
.pc-climber{position:absolute;bottom:4%} /* its height on the wall, which it climbs by */
.pc-wall .pc-climber{position:absolute;left:50%;bottom:4%;z-index:2;display:flex;align-items:center;gap:1px;translate:-50% 0;transition:bottom .45s cubic-bezier(.3,1.3,.5,1);pointer-events:none}
.pc-wall .pc-climber .ava,.pc-wall .pc-climber .ava-fallback{width:26px;height:26px;margin:0;font-size:12px;border-radius:50%;border:2px solid var(--gold);box-shadow:0 2px 6px #000}
.pc-wall .pc-hand{display:block;width:7px;height:9px;border-radius:4px 4px 3px 3px;background:#d9b48a;box-shadow:inset 0 -2px 0 rgba(0,0,0,.25),0 0 0 1px #3a2616}
.pc-wall .pc-hand.l{translate:0 -6px}.pc-wall .pc-hand.r{translate:0 2px}
.pc-wall .pc-climber.reach .pc-hand.l{animation:pc-hand-l .45s ease}
.pc-wall .pc-climber.reach .pc-hand.r{animation:pc-hand-r .45s ease}
@keyframes pc-hand-l{50%{translate:0 2px}}
@keyframes pc-hand-r{50%{translate:0 -8px}}
.pc-wall .pc-climber.slip{animation:pc-slip .4s ease}
@keyframes pc-slip{0%,100%{rotate:0deg}30%{rotate:-10deg}60%{rotate:8deg}}
/* winning: the chips, the glow, the UNO card, the gold leaf */
.fx-chip{position:absolute;left:0;top:0;width:18px;height:18px;border-radius:50%;will-change:transform;
  background:radial-gradient(circle at 50% 50%,#fff 0 22%,#c8342a 23% 62%,#fff 63% 70%,#c8342a 71%);box-shadow:0 0 0 1px #5a0f0a,0 2px 4px rgba(0,0,0,.7)}
.fx-chip.b{background:radial-gradient(circle at 50% 50%,#fff 0 22%,#2f5fc9 23% 62%,#fff 63% 70%,#2f5fc9 71%);box-shadow:0 0 0 1px #0e1f47,0 2px 4px rgba(0,0,0,.7)}
.fx-chip.land{transition:opacity .25s,scale .25s;opacity:0;scale:.6}
.gr-seat.gr-winner{animation:gr-winner 3s ease-out;border-color:var(--gold-hi)!important}
@keyframes gr-winner{0%{box-shadow:0 0 0 0 rgba(255,210,120,0)}15%{box-shadow:0 0 0 2px #fff3d6,0 0 26px 6px rgba(255,210,120,.85)}100%{box-shadow:0 0 0 1px rgba(255,210,120,.4),0 0 10px 2px rgba(255,210,120,.2)}}
.uno-top .uno-c.uno-flip{animation:uno-flip .9s cubic-bezier(.3,.7,.3,1)}
@keyframes uno-flip{0%{transform:perspective(300px) rotateY(0)}45%{transform:perspective(300px) rotateY(90deg)}55%{transform:perspective(300px) rotateY(90deg);filter:brightness(1.8)}100%{transform:perspective(300px) rotateY(0);box-shadow:0 0 18px 4px rgba(255,210,120,.8)}}
/* the Popularity Contest moves */
.lb-row{transition:translate .6s cubic-bezier(.3,.7,.2,1),box-shadow .3s}
.lb-row.lb-lift{position:relative;z-index:2;box-shadow:0 8px 20px rgba(0,0,0,.7),0 0 0 1px var(--gold-hi)}
.lb-row.lb-new{animation:lb-new .5s ease both}
@keyframes lb-new{from{opacity:0}to{opacity:1}}
.lb-up{flex:none;font:700 11px Georgia,serif;color:#8fe08f;text-shadow:0 0 6px rgba(120,220,120,.5);animation:lb-up .5s .5s ease both}
@keyframes lb-up{from{opacity:0;translate:0 4px}to{opacity:1;translate:0 0}}
.lb-top .lb-medal{position:relative;display:inline-block;overflow:hidden}
.lb-top .lb-medal::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(115deg,transparent 35%,rgba(255,255,255,.75) 50%,transparent 65%);background-size:300% 100%;background-position:100% 0;animation:lb-glint 5s ease-in-out infinite}
.lb-row:nth-child(2) .lb-medal::after{animation-delay:1.3s}.lb-row:nth-child(3) .lb-medal::after{animation-delay:2.6s}
@keyframes lb-glint{0%,80%{background-position:100% 0}100%{background-position:-100% 0}}
@media (prefers-reduced-motion:reduce){
  .fx-ball,.fx-trap,.fx-fall,.fx-drop,.fx-chip,.pit-tank .pt-ripple{display:none!important}
  .pc-wall .pc-climber{transition:none}.pc-wall .pc-climber .pc-hand,.pc-wall .pc-climber.slip{animation:none!important}
  .uno-top .uno-c.uno-flip,.lb-row.lb-new,.lb-up,.lb-top .lb-medal::after{animation:none!important}
  .gr-seat.gr-winner{animation:none;box-shadow:0 0 0 2px #fff3d6,0 0 18px 4px rgba(255,210,120,.6)}
  .lb-row{transition:none}
}

/* ==================== build 328: the way in starts from the icon -- "the lantern catches the flame" ====================
   Concept 2 of the icon-C mock-up, chosen by the owner. The phone's opening screen (the iPhone pictures in img/splash,
   Android's own screen on #000) is this layer's first frame: the gold speech bubble of the app icon with its flame,
   centred on black. From there, all in CSS so it runs from the first paint whether or not app.js has loaded:
     .55s   the flame lifts out of the bubble and rises (.ge-cflame, ge-carry, .9s)
     .35s   the lantern drops on its chain, unlit, and lands at 1.45s -- the moment the flame reaches its glass
     1.3s   the empty bubble fades and swells a little; app.js throws its outline off as gold dust as it starts
     1.45s  app.js sees the flame arrive and lights the lantern (s-lit s-caught): the travelling flame goes, the
            lantern's own flame takes over at full size and flares, a ring of light goes out from the glass
   Geometry is calc() from the same variables as the lantern (--lw, --lh, --ch), so the flame lands on the lantern's
   flame at every screen size. A later load in the same visit (html.ge-seen, set in <head>) never shows the bubble;
   the quick and reduced-motion paths fade it out in a third of a second. */
.gc-entry{--bw:min(42vw,26vh)}
@media (min-width:501px){.gc-entry{--bw:min(22vw,30vh,240px)}}
.ge-bubble{position:absolute;left:50%;top:50%;width:var(--bw);height:auto;aspect-ratio:724/700;transform:translate(-50%,-50%);overflow:visible;pointer-events:none}
.ge-cflame{position:absolute;left:50%;top:calc(50% - var(--bw) * .0966);width:calc(var(--bw) * .3182);height:auto;aspect-ratio:6.4/9.7;transform:translate(-50%,-50%);overflow:visible;pointer-events:none;
  filter:drop-shadow(0 0 calc(var(--bw) * .06) rgba(195,60,255,.55))}
.gc-entry.s-in .ge-cflame,.gc-entry.s-lit .ge-cflame{animation:ge-carry .9s cubic-bezier(.45,0,.3,1) .55s both}
@keyframes ge-carry{from{top:calc(50% - var(--bw) * .0966);width:calc(var(--bw) * .3182)}
  to{top:calc(var(--ch) + var(--lh) * .5683);width:calc(var(--lw) * .3556)}}
.gc-entry.s-in .ge-bubble,.gc-entry.s-lit .ge-bubble{animation:ge-bub-out .65s ease-in 1.3s both}
@keyframes ge-bub-out{from{opacity:1;transform:translate(-50%,-50%) scale(1)}to{opacity:0;transform:translate(-50%,-50%) scale(1.07)}}
/* the lantern drops a little later than before, so it lands as the flame arrives, and without the overshoot (the
   flame would miss a lantern that bounced past it) */
.gc-entry.s-in .ge-hang,.gc-entry.s-lit .ge-hang,.gc-entry.s-wait .ge-hang{animation:ge-drop 1.1s cubic-bezier(.3,.85,.3,1) .35s both,ge-sway 5.5s ease-in-out 1.45s infinite}
/* caught: the travelling flame goes and the lantern's own flame is already full size, and flares */
.gc-entry.s-caught .ge-cflame,.gc-entry.s-wait .ge-cflame,.gc-entry.s-out .ge-cflame{visibility:hidden;animation:none}
.gc-entry.s-out .ge-bubble{opacity:0;animation:none}
.gc-entry:not(.s-quick):is(.s-caught,.s-wait,.s-out) .ge-lantern .lt-flame{animation:ge-catch .6s ease-out forwards,ge-flicker 1.1s ease-in-out .6s infinite}
@keyframes ge-catch{0%{transform:scale(1);opacity:1}35%{transform:scale(1.3,1.45);opacity:1}100%{transform:scale(1);opacity:1}}
.ge-catch{position:absolute;left:50%;top:calc(var(--ch) + var(--lh) * .5683);width:calc(var(--lw) * .5);height:calc(var(--lw) * .5);border-radius:50%;
  border:2px solid rgba(240,200,255,.9);box-shadow:0 0 18px rgba(229,139,255,.8);transform:translate(-50%,-50%) scale(.3);opacity:0;pointer-events:none}
.gc-entry.s-caught:not(.s-quick) .ge-catch{animation:ge-catch-ring .75s ease-out forwards}
@keyframes ge-catch-ring{0%{opacity:1;transform:translate(-50%,-50%) scale(.3)}100%{opacity:0;transform:translate(-50%,-50%) scale(2.6)}}
.ge-bits{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
/* the name follows the light a little sooner than it did, so the whole thing is only half a second longer */
.gc-entry.s-caught .ge-name span{animation-delay:calc(.5s + var(--i) * 45ms)}
/* quick loads, reduced motion, a sign-on that brings the lantern back: no bubble */
html.ge-seen .ge-bubble,html.ge-seen .ge-cflame{display:none}
.gc-entry.s-quick .ge-bubble,.gc-entry.s-quick .ge-cflame{opacity:0;animation:none;transition:opacity .35s ease}
@media (prefers-reduced-motion:reduce){
  .ge-cflame,.ge-bubble,.ge-catch{animation:none!important}
}
/* build 328: the lantern lights later than before (1.6s, when the flame arrives, not .75s), so what follows the light
   comes .8s sooner after it: the whole way in is about a third of a second longer than build 327's */
.gc-entry.s-caught .ge-rule::before,.gc-entry.s-caught .ge-rule::after{transition-delay:1.2s}
.gc-entry.s-caught .ge-rule b{transition-delay:1.1s}
.gc-entry.s-caught .ge-tag{transition-delay:1.5s}
.gc-entry.s-caught .ge-status,.gc-entry.s-caught .ge-thread{transition-delay:2s}
/* build 329: the admin email-login box reuses the Kick box's parts; this is its one line of small print */
.gl-hint{margin-top:5px;font-size:11px;font-style:italic;color:#b99ad8}

/* build 332: 📈 Live, the launch-day dashboard (admins only, Reports). One colour for the one series. */
.lv{padding:12px 12px 20px;max-width:760px;margin:0 auto}
.lv-tiles{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.lv-tile{border:1px solid var(--gold-lo);border-radius:4px;background:rgba(0,0,0,.28);padding:10px 10px 9px;min-width:0}
.lv-n{font:700 28px/1.1 Cinzel,Georgia,serif;color:var(--gold-hi)}
.lv-l{font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--bone);margin-top:4px}
.lv-s{font-size:11px;color:var(--ash);margin-top:2px}
.lv-warn{border-color:var(--ember)}
.lv-sec{margin-top:18px}
.lv-h{font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold);margin-bottom:8px}
.lv-bars{display:flex;align-items:flex-end;gap:2px;height:120px;border-bottom:1px solid var(--gold-lo)}
.lv-bar{flex:1 1 0;min-width:0;height:100%;display:flex;align-items:flex-end;padding:0;margin:0;border:0;background:none;cursor:pointer}
.lv-bar span{display:block;width:100%;background:var(--gold);border-radius:4px 4px 0 0}
.lv-bar:hover span,.lv-bar:focus-visible span{background:var(--gold-hi)}
.lv-bar:focus-visible{outline:1px dotted var(--gold-hi)}
.lv-axis{display:flex;justify-content:space-between;font-size:11px;color:var(--ash);margin-top:4px}
.lv-note{font-size:12px;color:var(--bone);margin-top:6px;min-height:1.3em}
.lv-step{margin-bottom:10px}
.lv-sl{display:flex;justify-content:space-between;gap:8px;font-size:13px;color:var(--bone)}
.lv-sl b{color:var(--gold-hi);font-weight:700}
.lv-track{height:8px;background:rgba(255,255,255,.06);border-radius:4px;margin-top:4px;overflow:hidden}
.lv-track span{display:block;height:100%;background:var(--gold);border-radius:4px}
.lv-foot{margin-top:16px;font-size:11px;color:var(--ash);display:flex;flex-wrap:wrap;align-items:center;gap:8px}
@media (max-width:600px){.lv-tiles{grid-template-columns:repeat(2,1fr)}.lv-n{font-size:24px}}
.lv-refresh{min-height:32px;padding:6px 14px}
/* build 335: photo comments, the owner's pick "A", with Facebook-style replies */
.pf-card.open .pf-cmts{border-top:1px solid var(--pf-line);padding-top:10px;gap:12px;max-height:480px}
.pf-cmt{display:flex;gap:9px;align-items:flex-start;font:14px/1.35 Georgia,serif;color:var(--pf-ink)}
.pf-cmt-av{width:30px;height:30px;border-radius:50%;flex:none;display:inline-flex;align-items:center;justify-content:center;font:700 13px Cinzel,Georgia,serif;color:var(--pf-gold);background:var(--pf-card);border:1px solid var(--pf-line)}
.pf-cmt-b{flex:1;min-width:0;word-break:break-word}
.pf-cmt-b .who{color:var(--pf-gold-hi,var(--pf-gold));font:700 13px Cinzel,Georgia,serif;margin-right:3px}
.pf-cmt-own{font:700 9px Cinzel,Georgia,serif;letter-spacing:1px;color:#1a0c04;background:var(--pf-gold);border-radius:3px;padding:1px 4px;margin-right:5px;vertical-align:1px}
.pf-cmt-meta{display:flex;align-items:center;gap:14px;margin-top:3px;font-size:12px;color:var(--pf-dim)}
.pf-cmt .pf-cmt-t{display:inline}
.pf-cmt-act{background:none;border:0;padding:4px 0;margin:-4px 0;font:700 12px Georgia,serif;color:var(--pf-dim);cursor:pointer;text-decoration:none;min-height:24px}
.pf-cmt-act:hover,.pf-cmt-act:focus-visible{color:var(--pf-gold);outline:none}
.pf-cmt-rep{margin-left:39px}
.pf-cmt-rep .pf-cmt-av{width:24px;height:24px;font-size:11px}
.pf-cmt-more{align-self:flex-start;background:none;border:0;padding:4px 0;font:13px Georgia,serif;color:var(--pf-dim);cursor:pointer;min-height:24px}
.pf-cmt-more:hover{color:var(--pf-gold)}
.pf-cmt-reps{margin-left:39px;font-weight:700}
.pf-cmt-rto{font-size:12px;color:var(--pf-dim);display:flex;align-items:center;gap:8px}
.pf-cmt-rto b{color:var(--pf-gold)}
.pf-cmt-form{align-items:center;gap:8px;margin-top:2px}
.pf-cmt-form input{height:38px;border-radius:19px;padding:0 14px;background:rgba(0,0,0,.35);border:1px solid var(--pf-line);font:14px Georgia,serif}
.pf-cmt-form .btn.pf-cmt-send{width:38px;height:38px;min-width:38px;padding:0;line-height:36px;border-radius:50%;border:1px solid var(--pf-gold);background:rgba(201,162,74,.15);color:var(--pf-gold);font-size:15px;flex:none}
@media (pointer:coarse){.pf-cmt-form input{font-size:16px}}
/* build 335: the profile photo viewer, the owner's pick "2" -- two pills and one ⋯ Edit menu; and a solid backdrop */
.pf-lb{background:#050403}
.pf-lb-acts2{flex:1 1 100%;display:flex;justify-content:space-between;align-items:center;gap:8px}
.pf-lb-main{display:flex;gap:8px}
.pf-lbp{height:44px;border-radius:22px;padding:0 18px;border:1px solid #6b5024;background:rgba(201,162,74,.1);color:#e8d3a2;font:700 13px Cinzel,Georgia,serif;letter-spacing:1px;cursor:pointer}
.pf-lbp:hover,.pf-lbp:focus-visible{border-color:#c49a52;outline:none}
.pf-lbp.pf-like.on{color:#e0505a;border-color:#e0505a;background:rgba(224,80,90,.12)}
.pf-lb-sheet{position:absolute;left:0;right:0;bottom:0;z-index:3;background:#15100b;border-top:2px solid #c49a52;border-radius:14px 14px 0 0;padding:8px 0 calc(14px + env(safe-area-inset-bottom));box-shadow:0 -10px 40px #000;max-width:520px;margin:0 auto}
.pf-lb-grab{width:40px;height:4px;border-radius:2px;background:#6b5024;margin:0 auto 6px}
.pf-lb-si{display:flex;align-items:center;gap:14px;width:100%;min-height:50px;padding:0 20px;background:none;border:0;border-bottom:1px solid #2a2118;color:#e8d3a2;font:15px Georgia,serif;text-align:left;cursor:pointer}
.pf-lb-si span{width:22px;text-align:center;font-size:18px}
.pf-lb-si:hover,.pf-lb-si:focus-visible{background:rgba(201,162,74,.08);outline:none}
.pf-lb-si-red{color:#e0505a;border-bottom:0}
/* build 336: while the Edit sheet is up, the pills behind it are hidden rather than left half-covered under it;
   and while a photo is being swiped down, the viewer's buttons step aside so the picture never slides over them */
.pf-lb:has(.pf-lb-sheet) .pf-lbp{visibility:hidden}
.gc-swiping button{visibility:hidden}

/* ==================== build 337: profile layout (audit items 8, 14, 15, 24, 25, 26; mock-ups 8A, 14A, 15, 24B) ==================== */
/* 8A: no header picture -> a thin gold rule instead of an empty band, and the name card sits under it */
.profile-panel .pf-band.pf-band-rule{height:5px;border:0;box-shadow:none;opacity:.7;background:linear-gradient(90deg,transparent,var(--pf-gold) 30%,var(--pf-gold-hi,var(--pf-gold)) 50%,var(--pf-gold) 70%,transparent)}
.profile-panel .pf-band.pf-band-rule + .pf-plate{margin-top:12px}
/* 14A + 25: photos as square thumbnails, three across, with the like and comment counts on the picture.
   Captions show in the viewer. A card opened for its comments (.open) keeps the old full layout. */
.profile-panel .pf-grid{grid-template-columns:repeat(3,1fr);gap:4px}
@media (min-width:600px) and (max-width:899px){.profile-panel .pf-grid{grid-template-columns:repeat(4,1fr)}}
.profile-panel .pf-card:not(.open){position:relative;border-radius:6px}
.profile-panel .pf-card:not(.open) .pf-card-r{position:absolute;left:0;right:0;bottom:0;padding:14px 4px 2px;background:linear-gradient(transparent,rgba(0,0,0,.8));pointer-events:none}
.profile-panel .pf-card:not(.open) .pf-card-cap{display:none}
.profile-panel .pf-card:not(.open) .pf-card-acts{gap:2px}
.profile-panel .pf-card:not(.open) .pf-ca{border:0;background:none;padding:2px 5px;min-height:24px;min-width:24px;font:12px Georgia,serif;color:#f1e6cc;text-shadow:0 1px 2px #000;pointer-events:auto}
.profile-panel .pf-card:not(.open) .pf-ca[data-plike].on{color:#ff6f78}
/* 15: on a phone the pictures come before the wall: standing, friends, photos, wall */
@media (max-width:899px){
  .profile-panel .pf-rail .pf-photos{order:3}
  .profile-panel .pf-main{order:4}
}
/* 24B + 26: on a computer, top friends in one row of circles beside the standing block across the top,
   then the wall on the left and a 360px photo column on the right, so neither column runs twice the other */
@media (min-width:900px){
  .profile-panel .pf-cols{grid-template-columns:minmax(0,1fr) 360px;grid-template-areas:"tf stats" "tf badges" "main photos";gap:0 12px}
  .profile-panel .pf-cols.pf-notf{grid-template-areas:"stats stats" "badges badges" "main photos"}
  .profile-panel .pf-rail{display:contents}
  .profile-panel .pf-main{grid-area:main}
  .profile-panel .pf-rail > .pf-sec:not(.pf-photos):not(.pf-badges):not(.pf-bring){grid-area:tf}
  .profile-panel .pf-rail .pf-stats{grid-area:stats;grid-template-columns:repeat(4,1fr);gap:5px;margin:12px 16px 0 0;align-self:start}
  .profile-panel .pf-rail .pf-badges{grid-area:badges}
  .profile-panel .pf-rail .pf-photos{grid-area:photos}
  .profile-panel .pf-rail .pf-stat b{font-size:13px}
  .profile-panel .pf-rail .pf-tfs{display:flex;gap:4px}
  .profile-panel .pf-rail .pf-tf{flex:1 1 0;min-width:0;max-width:92px;background:none;border:0;padding:2px 0}
  .profile-panel .pf-rail .pf-tf-ava{width:48px;height:48px}
}

/* ==================== build 338: profile polish (audit items 9-13, 16-23, 27) ==================== */
/* 9: the smallest words on the page were 8-9px */
.profile-panel .pf-stat span,.profile-panel .pf-rail .pf-stat span,.profile-panel .pf-stats .pf-stat span{font-size:10px;letter-spacing:.6px}
.profile-panel .pf-sub .lvl{font-size:11px;padding:1px 5px}
/* 23: a zero is dimmed, not a scoreboard */
.profile-panel .pf-stat.zero b{color:var(--pf-dim);opacity:.7}
.profile-panel .pf-stat.zero{opacity:.75}
/* 10 + 11: the main buttons are one height, and only Add Friend wears the red; Wave and Gift join Whisper's purple */
.profile-panel .pf-acts .pf-act{min-height:36px;padding:0 14px;display:inline-flex;align-items:center;justify-content:center}
@media (max-width:500px){.profile-panel .pf-acts{display:grid;grid-template-columns:repeat(2,1fr);padding:12px 10px 0}}
.profile-panel .pf-act[data-act="wave"],.profile-panel .pf-act[data-act="gift"]{background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;box-shadow:none !important}
.profile-panel .pf-act[data-act="wave"]:hover,.profile-panel .pf-act[data-act="gift"]:hover{border-color:#9a6bd0 !important;color:#e2c4ff !important}
/* Report and Block: a quiet line under the buttons, still easy to hit */
.pf-acts2{display:flex;justify-content:flex-end;gap:6px;padding:6px 16px 0}
@media (max-width:500px){.pf-acts2{padding:6px 10px 0}}
.pf-act2{background:none;border:1px solid transparent;border-radius:999px;min-height:30px;padding:0 10px;cursor:pointer;font:12px Georgia,serif;color:var(--pf-dim)}
.pf-act2:hover,.pf-act2:focus-visible{border-color:var(--pf-line);color:var(--pf-ink);outline:none}
.pf-act2-danger{color:#c86a6a}
.pf-act2-danger:hover,.pf-act2-danger:focus-visible{border-color:#7a2a2a;color:#e07a7a}
/* 13: a friend's name on the wall is a real target; the friends row on a phone fades at the edge so it reads as a row you swipe */
.profile-panel .pf-post-hd b.who{display:inline-block;padding:5px 0;min-height:24px}
@media (max-width:899px){.profile-panel .pf-tfs{-webkit-mask-image:linear-gradient(90deg,#000 85%,transparent);mask-image:linear-gradient(90deg,#000 85%,transparent)}}
/* 17 + 18: the composer's buttons share one shape; Ban is a word, and it and ✕ are proper targets apart from each other */
.profile-panel .pf-comp .pf-tool{border-radius:999px}
.profile-panel .pf-comp button[type=submit]{min-height:32px;height:32px;padding:0 16px}
.profile-panel .pf-post-hd .pf-x{min-width:28px;min-height:28px;display:inline-flex;align-items:center;justify-content:center;font-size:13px}
.profile-panel .pf-post-hd .pf-ban{opacity:.85;font:12px Georgia,serif;color:#c86a6a;border:1px solid transparent;border-radius:999px;padding:0 8px;margin-right:4px}
.profile-panel .pf-post-hd .pf-ban:hover{border-color:#7a2a2a;opacity:1}
/* 21: the empty-page hints are buttons */
.pf-hint{background:none;border:1px solid var(--pf-line);border-radius:999px;color:var(--pf-gold-hi,var(--pf-gold));font:13px "IM Fell English",Georgia,serif;padding:3px 10px;min-height:28px;cursor:pointer;margin-left:4px}
.pf-hint:hover,.pf-hint:focus-visible{border-color:var(--pf-gold);outline:none}
/* 19: Bring somebody in comes last (under the photos on a computer, after the wall on a phone) */
@media (max-width:899px){.profile-panel .pf-rail .pf-bring{order:5}}
@media (min-width:900px){
  .profile-panel .pf-cols{grid-template-areas:"tf stats" "tf badges" "main photos" "main bring"}
  .profile-panel .pf-cols.pf-notf{grid-template-areas:"stats stats" "badges badges" "main photos" "main bring"}
  .profile-panel .pf-rail .pf-bring{grid-area:bring}
}
/* 27: the link button says what it is */
.tp-hd .pf-share{width:auto;padding:0 10px;border-radius:999px;display:inline-flex;align-items:center;gap:2px;font:12px Georgia,serif}


/* ==================== build 340: a floor for small words (site-wide UI audit) ====================
   The audit found labels at 8-10px on every page. These are the ones people have to read; each is lifted to 11px
   (12px for the back pills and the fish names). !important because the originals sit in a dozen media blocks. */
.lvl,.tp-chip,.tp-sub,.tp-newlbl,.tp-meta,.tpx-lbl,.tpx-bchip,.tpx-n,.tpx-sec,.gr-row-lbl,.gr-seat-n,.gr-hd-pos,
.gr-hd-acts .gr-hd-presets .btn,.turn-clock .tc-num,.hm-filter,.hp-dow,.hp-kind,.cc-badge,.cc-role,.hm-sec-hd,
.hm-side > .hm-sec > .hm-sec-hd,.m.scripture .sc-ref,.sc-theme,.td-sh .td-src,.tp-watermark,.bnav .lb,
.win > .title .tb-word,.status .popover-label,.pc-word,.pc-amt,.pfe-lbl,.pf-circ-lbl,.rtag,.sh-kind,.sh-meta,.bs-label{font-size:11px !important}
.gc-load .gl-word,.pit-tank .pt-fish .pt-name,.log .rpt-msg,.im .ilog .rpt-msg{font-size:12px !important}
/* the back pills: 11px words (their size is left for the header mock-up) */
.tp-hd .tp-back{font-size:11px !important}
.hm-filter{min-height:32px}
/* build 340: the thread "No." links are a real target; the phone back pills stay 30px so the 36px header holds */
.ib-no{display:inline-block;min-height:24px;line-height:24px;padding:0 2px}

/* ==================== build 341: Home (UI audit) ==================== */
/* the filter reads as a two-way switch, the chosen side lit */
#homeFilter{display:inline-flex;gap:0;padding:0 !important;overflow:hidden}
#homeFilter span{padding:0 10px;display:inline-flex;align-items:center;opacity:.55}
#homeFilter span.on{opacity:1;background:rgba(154,107,208,.28);color:#f0dcff}
/* empty feed: buttons, not just a sentence */
.hm-go{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin:10px 0 4px}
.hm-go .btn{min-height:34px;padding:0 14px;border-radius:999px}
/* wave back, on a wave row */
.hm-waveback{display:inline-flex;align-items:center;margin:6px 8px 0 0;min-height:30px;padding:0 12px;border-radius:999px;cursor:pointer;
background:linear-gradient(180deg,#1f1526,#0a050e);border:1px solid #4a3560;color:#b99ad8;font:12px Georgia,serif}
.hm-waveback:hover{border-color:#9a6bd0;color:#e2c4ff}.hm-waveback:disabled{opacity:.6;cursor:default}
/* the time no longer prints over a photo: on a row with a thumbnail it sits on its own line under the words */
.hm-main .hm-row.has-thumb .hm-txt .t,.hm-row.has-thumb .hm-txt .t{position:static !important;transform:none !important;display:block;margin-top:3px}
/* names in a row are a real target */
.hm-row .who{display:inline-block;padding:4px 0;min-height:24px}
/* errands you can still do are tappable */
.er-row.er-go{cursor:pointer}.er-row.er-go:hover .er-title{text-decoration:underline;text-decoration-color:rgba(201,162,74,.5)}
.qd-saved{margin:4px 2px 0;font:italic 13px "IM Fell English",Georgia,serif;color:#8fd48f}
@media (max-width:500px){#homeFilter span{padding:0 8px}}

/* ==================== build 342: Threads (UI audit) ==================== */
.tp-emptybtn{display:block;margin:14px auto 0;min-height:36px;padding:0 18px;border-radius:999px !important;
background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;color:#ffe1dc !important;box-shadow:0 0 8px rgba(200,50,40,.45) !important}
/* a thread with no replies says so instead of ending in a black void */
.tp-posts:has(> .tp-post:only-child)::after{content:"No replies yet. Be the first.";display:block;text-align:center;padding:26px 12px;font:italic 14px "IM Fell English",Georgia,serif;color:var(--ash,#9a8b73)}
/* the primary buttons look primary: New Thread and Post wear the red; Cancel steps back to purple */
#tpNewSubmit{background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;color:#ffe1dc !important;box-shadow:0 0 8px rgba(200,50,40,.45) !important;border-radius:999px !important}
#tpNewCancel{background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;border-radius:999px !important;box-shadow:none !important}

/* ==================== build 343: Happenings and Circles (UI audit) ==================== */
/* one primary per page: Going (and Join / Ask / Accept) glow red; Maybe and Share are purple; Delete, Leave and No are the muted-red outline */
.hap-panel .hp-rsvp [data-rsvp="maybe"],.hap-panel .hp-rsvp .hp-clear,.hap-panel .hp-share,.circ-panel .hp-share,.circ-panel [data-cinvite],.circ-panel [data-cedit],
.circ-panel [data-cdecline]{background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;box-shadow:none !important;border-radius:999px !important}
.hap-panel [data-hapdel],.circ-panel [data-cdel],.circ-panel [data-cleave],.circ-panel [data-creq][data-yes="0"]{background:linear-gradient(180deg,#240a0a,#0c0000) !important;border:1px solid #7a2a2a !important;color:#e07a7a !important;box-shadow:none !important;border-radius:999px !important}
.circ-panel .cc-join,.circ-panel [data-creq][data-yes="1"]{background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;color:#ffe1dc !important;box-shadow:0 0 8px rgba(200,50,40,.45) !important;border-radius:999px !important}
.hap-panel .hp-rsvp .btn.on[data-rsvp="maybe"]{border-color:#9a6bd0 !important;color:#f0dcff !important;background:linear-gradient(180deg,#3a2650,#1a0f26) !important}
.hp-share{margin-right:auto}
/* "Not going" no longer drops to a line of its own on a phone */
@media (max-width:500px){.hap-panel .hp-rsvp{display:flex;gap:6px}.hap-panel .hp-rsvp .btn{flex:1 1 0;min-width:0;padding:0 8px !important;font-size:13px !important}}
/* people who said Maybe are labelled, not only faded */
.hp-maybe-tag{display:block;font:italic 11px "IM Fell English",Georgia,serif;color:#b99ad8;margin-top:-2px}
/* card second lines may wrap rather than cut off */
.hp-card .hp-sub{white-space:normal !important;overflow:visible !important;text-overflow:clip !important}

/* ==================== build 344: the room, the Game Room and the Pit (UI audit) ==================== */
/* the room box counts down its last twenty characters */
.msg-left{position:absolute;right:92px;bottom:6px;font:italic 11px Georgia,serif;color:#b99ad8;pointer-events:none}
.msg-left.none{color:#e07a7a}.msg-left.hidden{display:none}
/* the bell's way to everything */
.bell-all{display:block;width:100%;margin-top:4px;padding:9px 12px;min-height:36px;background:none;border:0;border-top:1px solid rgba(201,162,74,.25);color:var(--gold,#c9a24a);font:13px "IM Fell English",Georgia,serif;text-align:right;cursor:pointer}
.bell-all:hover{color:var(--gold-hi,#f0d78a)}
/* the Game Room's note can be closed, and offers the UNO table it suggests */
.gr-note{position:relative;padding-right:38px !important}
.gr-note .gr-newtable{margin:8px 6px 0 0;min-height:32px}
.gr-note-x{position:absolute;top:4px;right:4px;width:30px;height:30px;background:none;border:0;color:inherit;opacity:.7;cursor:pointer;font-size:14px}
.gr-note-x:hover{opacity:1}
/* "Challenge someone" games are a list, not buttons that do nothing */
.gr-duel-list > span{cursor:default !important;background:none !important;box-shadow:none !important;border-style:dashed !important}
/* the Pit's "Slow down" is a warning, not a whisper */
.pt-note.pt-warn{color:#ff8a80 !important;font-style:normal !important;font-weight:600}

/* ==================== build 345 (layout): Happenings and Circles (UI audit) ==================== */
/* build 345 (layout): boxes on these pages (Who's coming, The Wall, Waiting to join, Members) kept the profile page's 16px side margins,
   so they sat narrower than everything above them. Here they run the full width like the rest of the page. */
.hap-panel .pf-sec,.circ-panel .pf-sec{margin-left:0;margin-right:0}

/* build 345 (layout): circle photos were two huge squares a row on a phone. Now three square thumbnails across, like the profile photos. */
.circ-panel .cc-grid{grid-template-columns:repeat(3,1fr);gap:4px}
@media (min-width:600px){.circ-panel .cc-grid{grid-template-columns:repeat(4,1fr)}}
@media (min-width:900px){.circ-panel .cc-grid{grid-template-columns:repeat(5,1fr)}}
.circ-panel .cc-grid .pf-th{border-radius:6px;aspect-ratio:1/1}

/* build 345 (layout): the five circle tabs wrapped, leaving Members alone on a second line. They stay on one line and slide sideways,
   with a soft fade on the right so it is clear there is more; each tab is at least 34px tall to tap. */
.circ-panel .cc-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;padding:2px 24px 8px 0;margin-right:-16px;
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)}
.circ-panel .cc-tabs .pf-chip{flex:none;min-height:34px;padding:0 12px;font-size:13px;display:inline-flex;align-items:center;gap:4px;scroll-snap-align:start;white-space:nowrap}
@media (min-width:641px){.circ-panel .cc-tabs{-webkit-mask-image:none;mask-image:none;margin-right:0;padding-right:0}}

/* build 345 (layout): on the Room tab on a phone the cover, the about text and the kind line took ~600px, pushing "Say something" under the bottom bar.
   On that tab the header shrinks to the name and buttons, and the talk box stretches to fill what is left, so the input always sits just above the bottom bar. */
@media (max-width:640px){
  .circ-panel #circBody:has(> .cc-body > .cc-room){display:flex;flex-direction:column;padding-bottom:8px}
  .circ-panel #circBody:has(> .cc-body > .cc-room) > *{flex:none}
  .circ-panel #circBody:has(> .cc-body > .cc-room) > .hp-cover,
  .circ-panel #circBody:has(> .cc-body > .cc-room) > .pf-bio,
  .circ-panel #circBody:has(> .cc-body > .cc-room) .hp-kind,
  .circ-panel #circBody:has(> .cc-body > .cc-room) .hp-hostline{display:none}
  .circ-panel #circBody:has(> .cc-body > .cc-room) > .hp-top{margin-bottom:4px}
  .circ-panel #circBody:has(> .cc-body > .cc-room) .hp-h2{font-size:22px;margin:0 0 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .circ-panel #circBody:has(> .cc-body > .cc-room) > .hp-rsvp{margin:0 0 4px}
  .circ-panel #circBody:has(> .cc-body > .cc-room) > .cc-body{flex:1 1 auto;min-height:220px;display:flex;flex-direction:column}
  .circ-panel .cc-body > .cc-room{flex:1 1 auto;height:auto;min-height:140px}
  .circ-panel .cc-body > .cc-say{flex:none}
}

/* build 345 (layout): now the members box is full width, a phone would squeeze two narrow columns and cut names short; one clean column instead */
@media (max-width:640px){.circ-panel .cc-members{grid-template-columns:1fr}}
@media (min-width:641px){.circ-panel .cc-members{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}

/* build 345 (layout): "Waiting to join" rows: the name and the Let in / No buttons share the top line; the person's note sits underneath across the full width. */
.circ-panel .cc-reqrow{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:8px;row-gap:2px}
.circ-panel .cc-reqrow > .who{grid-column:1;grid-row:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.circ-panel .cc-reqrow > .cc-inv-acts{grid-column:2;grid-row:1;display:flex;gap:6px}
.circ-panel .cc-reqrow > .cc-note{grid-column:1/-1;grid-row:2}
.circ-panel .cc-reqrow .cc-inv-acts .btn{min-height:34px;min-width:0;padding:0 12px}

/* build 345 (layout): photo viewer. The caption hugged the left edge and floated far below the picture; now picture and caption sit together
   in the middle of the screen, caption straight under the photo with room on both sides. */
.cc-lb{justify-content:center}
.cc-lb .pf-lb-top{position:absolute;top:0;left:0;right:0;z-index:2;padding-top:calc(8px + env(safe-area-inset-top))}
.cc-lb .pf-lb-stage{flex:0 1 auto}
.cc-lb .pf-lb-stage img{max-height:calc(100dvh - 190px)}
.cc-lb .pf-lb-cap{flex:none;min-width:0;padding:10px 16px 0;text-align:center;line-height:1.4;max-width:640px;margin:0 auto;box-sizing:border-box;width:100%}
.cc-lb .pf-lb-acts{padding:10px 16px}
.cc-lb .pf-lb-acts .btn{height:34px;line-height:34px;font-size:12px}

/* build 345 (layout): calendar days are buttons now. Picked day = gold; days gone by are dimmed; a month with nothing on shows one week. */
.hap-panel button.hp-day{font-family:Georgia,serif;cursor:pointer;min-height:32px}
.hap-panel .hp-day.past{opacity:.42}
.hap-panel .hp-day.past.has{opacity:.6}
.hap-panel .hp-day.sel,.hap-panel .hp-day.sel.today{opacity:1;background:linear-gradient(180deg,#5a4214,#241805) !important;border-color:var(--gold) !important;color:#fff3cf !important;box-shadow:0 0 10px rgba(201,162,74,.45) !important}
.hap-panel .hp-day.sel i{background:#fff3cf !important}
.hap-panel .hp-day:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.hap-panel .hp-cal-week{margin-bottom:4px}
.hp-cal-more{text-align:center;margin:0 0 12px}
.hp-cal-more .pf-hint,.hp-showing .pf-hint{min-height:32px}
.hp-showing{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font:14px "IM Fell English",Georgia,serif;color:var(--bone);margin:0 0 10px}
.hp-showing b{color:var(--gold)}

/* build 345 (layout): new-event form. "An event / A notice" was two small chips that barely read as a choice; now it is a two-part switch of
   two big halves, each saying what it is for (the picked half glows purple). "Post it" (and "Save") is the red glowing primary; Cancel stays quiet. */
.hp-kinds{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:8px 0 4px}
.hp-kinds .pf-chip{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-height:56px;padding:6px 8px;border-radius:10px;border:1px solid #4a3560 !important;background:#0a050e !important;color:#b99ad8 !important;font-size:14px;text-align:center}
.hp-kinds .pf-chip b{font-weight:700}
.hp-kinds .pf-chip span{font-size:12px;opacity:.85;line-height:1.25}
.hp-kinds .pf-chip.on{border-color:#9a6bd0 !important;background:linear-gradient(180deg,#3a2650,#1a0f26) !important;color:#f0dcff !important;box-shadow:0 0 0 1px #9a6bd0 inset,0 0 8px rgba(160,110,230,.35)}
.hp-form #hpfOk{background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;color:#ffe1dc !important;box-shadow:0 0 8px rgba(200,50,40,.45) !important;border-radius:999px !important}
.hp-form #hpfCancel{border-radius:999px}
/* build 345: the month under a card's date was 10px; "✓ Going · 12" wrapped at 360 */
.hp-date span{font-size:11px !important}
@media (max-width:380px){.hap-panel .hp-rsvp .btn{font-size:12px !important;letter-spacing:.5px}}

/* ==================== build 346 (layout): Threads, from the UI audit ====================
   House style: red glow pill = the one thing a page is for, purple pill = the other buttons, muted red outline =
   danger. Nothing here is smaller than 11px, and nothing tappable on a phone is under 32px. */

/* build 346 (layout): "Start a New Thread" is the board page's main button, so it wears the red glow pill at
   every width -- on a computer it was the bracket text "[Start a New Thread]", which read as a heading */
.tp-list.ib #tpNewBtn.tp-new{background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;border-radius:999px !important;
box-shadow:0 0 8px rgba(200,50,40,.45) !important;color:#ffe1dc !important;height:38px;min-height:38px;padding:0 20px;gap:0}
.tp-list.ib #tpNewBtn.tp-new:hover{border-color:#e0453a !important;box-shadow:0 0 12px rgba(224,69,58,.6) !important}
.tp-list.ib .ib-ctl .tp-new::before,.tp-list.ib .ib-ctl .tp-new::after{content:none}
.tp-list.ib #tpNewBtn .tp-new-label{font:700 13px Cinzel,Georgia,serif;letter-spacing:1.2px;color:#ffe1dc !important;text-transform:none;text-decoration:none !important}
.tp-list.ib #tpNewBtn .tp-new-label::before{content:"＋ "}
@media (min-width:641px){
  /* the pill sits centred on its own line under the board's title, where the bracket text was */
  .tp-list.ib .ib-ctl .tp-new{flex:0 0 auto;margin:2px auto 6px}
  .tp-list.ib .ib-ctl::after{content:"";order:0;flex:0 0 100%;height:0}
  .tp-list.ib #ibRefresh .ib-ri{display:none}
}

/* build 346 (layout): "View Thread" under a phone tile was a one-off black box; it is the site's purple pill now */
.tp-list.ib .ib-vt{background:linear-gradient(180deg,#1f1526,#0a050e);border:1px solid #4a3560;color:#b99ad8;border-radius:999px;
font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;padding:0 16px;min-height:34px;box-shadow:none}
.tp-list.ib .ib-vt:hover{border-color:#9a6bd0;color:#f0dcff}

/* build 346 (layout): the "Latest replies" label only matters on a phone, where replies are full-width cards */
.ib-latest{display:none}

/* build 346 (layout): catalog. A thread without a picture was a big empty box with a spool in it; now it is a
   compact card of its own words. Titles stop at three lines with "…" instead of being cut mid-word. */
.tp-list.ib .tp-item.ib-cc.ib-cc-txt{align-self:start;align-items:stretch;width:140px;justify-self:center;box-sizing:border-box;padding:9px 10px 8px;text-align:left;
background:#2a1f16;border:1px solid #5c4526;border-radius:4px;box-shadow:0 2px 8px rgba(0,0,0,.5)}
@media (max-width:640px){.tp-list.ib .tp-item.ib-cc.ib-cc-txt{width:100%}}
.tp-list.ib .tp-item.ib-cc.ib-cc-txt:hover{border-color:var(--gold)}
.ib-cc-txt .ib-cch{order:0}
.ib-cc-txt .ib-ccp{order:1;margin-top:2px}
.ib-cc-txt .ib-cnt{order:2;margin-top:5px}
.ib-cc-txt .ib-ccw{order:3}
.ib-cch{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.ib-cc-txt .ib-cch{-webkit-line-clamp:4}

/* build 346 (layout): the "Yogg Squad © 2026" line under Threads is a solid strip of its own, and the list stops
   well above it, so the last thread's button is never half-hidden behind it */
.threads-panel .tp-watermark{background:#0b0805;border-top:1px solid #3a2c1c;opacity:1;color:#8a7b62;padding:4px 8px 5px}
.threads-panel .tp-list.ib .ib-scroll{padding-bottom:40px;scroll-padding-bottom:40px}

/* build 346 (layout): the new-thread form has a title and a ✕, and each label stays with its dropdown */
.tp-newhd{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:-2px 0 6px}
.tp-newttl{font:700 16px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold-hi)}
.tp-newx{flex:none;width:32px;height:32px;border-radius:50%;border:1px solid #4a3560;background:linear-gradient(180deg,#1f1526,#0a050e);color:#b99ad8;
font:14px Georgia,serif;line-height:30px;padding:0;cursor:pointer}
.tp-newx:hover,.tp-newx:focus-visible{border-color:#9a6bd0;color:#f0dcff;outline:none}
.tp-field{display:inline-flex;align-items:center;gap:8px;flex:0 1 auto;min-width:0;white-space:nowrap}
.tp-newmeta{gap:8px 16px}
.tp-newmeta .tp-field .tp-sel{min-width:0;max-width:none;min-height:32px;font-size:13px}
@media (max-width:640px){
  /* on a phone each field is a line of its own: the label on the left, its dropdown filling the rest */
  .tp-field{flex:1 1 100%}
  .tp-field .tp-newlbl{flex:0 0 52px}
  .tp-newmeta .tp-field .tp-sel{flex:1 1 auto;width:auto;max-width:none;height:36px}
}

/* build 346 (layout): the thread's share button says "Share", as a purple pill like Share everywhere else */
.tp-detail .tp-hd .tp-share{width:auto;height:32px;padding:0 13px;border-radius:999px;display:inline-flex;align-items:center;gap:5px;
background:linear-gradient(180deg,#1f1526,#0a050e);border:1px solid #4a3560;color:#b99ad8;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;line-height:1}
.tp-detail .tp-hd .tp-share:hover,.tp-detail .tp-hd .tp-share:focus-visible{border-color:#9a6bd0;color:#f0dcff;background:linear-gradient(180deg,#2c1e36,#110918)}
.tp-detail .tp-hd .tp-share span{display:inline;gap:0}
.tp-detail .tp-hd .tp-share span::before,.tp-detail .tp-hd .tp-share span::after{content:none}
/* the share dialog's Cancel was a flat, square, full-width gold bar; it is the standard rounded Cancel now */
.pick-modal > .pick-cancel{display:block;width:auto;min-height:34px;margin:10px auto 0;padding:0 22px;border-radius:999px !important;
background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;box-shadow:none !important}
.pick-modal > .pick-cancel:hover{border-color:#9a6bd0 !important;color:#f0dcff !important}

/* build 346 (layout): the phone board page. Before, the picker, a big title, a row of three buttons, a centred
   New Thread button and the two filters took about 290px -- a third of the screen -- before the first thread.
   Now: the sticky picker bar also carries Follow (it follows the board picked there); the big title goes, because
   the picker already names the board; the board's note is one small line; New Thread (red), Catalog and ↻ share
   one row; the two filters are the last row. Chosen over keeping a small title line (mock B), which showed the
   board's name twice. */
@media (max-width:640px){
  .tp-list.ib .ib-bar{padding:5px 8px;gap:8px}
  .tp-list.ib .ib-bar select{height:36px}
  .tp-list.ib .ib-bar .tp-sub{flex:none}
  .tp-list.ib.ib-v-home .ib-bar .tp-sub{display:none}
  .tp-list.ib .ib-head{padding:6px 10px 0}
  .tp-list.ib .ib-head .ib-btitle{display:none}
  .tp-list.ib .ib-bsub{font-size:12px;margin:0}
  .tp-list.ib .ib-board > .ib-ctl{flex-wrap:wrap;gap:8px 6px;padding:8px 8px 0;justify-content:flex-start}
  .tp-list.ib .ib-ctl .tp-new{order:0;flex:1 1 auto;margin:0;min-width:0}
  .tp-list.ib #tpNewBtn.tp-new{height:36px;min-height:36px;padding:0 12px}
  .tp-list.ib .ib-ctl .ib-links{order:1;flex:0 0 auto;gap:6px;flex-wrap:nowrap}
  /* Catalog, Follow, ↻ (and Bottom on a thread) are the purple secondary pill */
  .tp-list.ib .ib-lk,.tp-detail.ib .ib-lk{background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;border-radius:999px !important;
  color:#b99ad8 !important;font:700 12px Cinzel,Georgia,serif !important;letter-spacing:.5px !important;padding:0 12px !important;min-height:36px;height:36px;white-space:nowrap}
  .tp-list.ib .ib-lk.on{border-color:#9a6bd0 !important;color:#f0dcff !important}
  .tp-list.ib #ibRefresh{min-width:36px;padding:0 !important;font-size:17px !important}
  .tp-list.ib #ibRefresh .ib-rw{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  .tp-list.ib .ib-ctl .tp-tags{margin:0;gap:6px}
  .tp-list.ib .tp-tags select{height:34px}
  .tp-list.ib .ib-board > .ib-hr{display:none}
  .tp-list.ib .ib-board > .ib-ctl{margin-bottom:10px}
}

/* build 346 (layout): on a phone the last two replies under a thread looked exactly like new threads. Now the
   thread and its replies are one framed card: a dashed line and a "Latest replies" label, then the replies as
   slim indented rows. Chosen over indenting the replies on a gold rule outside the card (mock A), where the
   View Thread strip still sat between a thread and its own replies like a divider. */
@media (max-width:640px){
  .threads-panel .tp-list.ib .ib-thread{margin:0 8px 12px;border:1px solid #5c4526;border-radius:6px;overflow:hidden;background:#1a130d}
  .threads-panel .tp-list.ib .ib-thread .tp-item.ib-op{border-top:0 !important}
  .ib-latest{display:block;padding:7px 12px 2px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1.5px;text-transform:uppercase;color:#a8977a;border-top:1px dashed #5c4526}
  .tp-list.ib .ib-prevs{padding:0 0 4px 12px}
  .threads-panel .tp-list.ib .ib-prevs .ib-post.ib-reply{margin:4px 0 0 !important;padding:0 0 0 10px;background:none !important;border:0 !important;border-left:2px solid #5c4526 !important}
  .threads-panel .tp-list.ib .ib-prevs .ib-post > .ib-pi{padding:0 10px 0 0;background:none !important;border-bottom:0 !important}
  .tp-list.ib .ib-prevs .ib-reply .ib-msg{margin:0 10px 6px 0;font-size:14px}
}

/* build 346 (layout): the phone thread page had "‹ Threads" in the header and a Return button, the board's name
   in the header and again as a big title, and a Return / Catalog / Bottom row -- about 100px. Return and the
   title go; the reply count, Catalog and Bottom share one slim row. Pills chosen over plain text links (mock B)
   so they match the board page's buttons. */
@media (max-width:640px){
  .ib-thead .ib-btitle,.ib-thead [data-ibact="ret"]{display:none !important}
  .ib-thead .ib-ctl{margin:0;padding:6px 8px;flex-wrap:nowrap;justify-content:space-between}
  .ib-thead .ib-count{order:0;flex:1 1 auto;text-align:left;padding:0}
  .ib-thead .ib-links{order:1;flex:0 0 auto;gap:6px}
  .tp-detail.ib .ib-thead .ib-lk{min-height:32px;height:32px}
  .ib-thead .ib-hr{margin:0 0 6px}
}

/* build 346 (layout): the desktop board bar showed ids (nynj, canadaeast) as 14px-tall links. It shows short
   names as rounded 30px chips now, each group of boards kept together when the bar wraps, with a wider gap
   between groups. Chosen over the same names in 4chan-style [ a / b ] brackets (mock A), which wrapped into a
   ragged second line and read as small print. */
@media (min-width:641px){
  .tp-list.ib .ib-nav{display:flex;flex-wrap:wrap;justify-content:center;gap:6px 22px;padding:8px 12px}
  .tp-list.ib .ib-ng{display:inline-flex;gap:4px;white-space:nowrap}
  .tp-list.ib .ib-nav a{display:inline-flex;align-items:center;min-height:30px;padding:0 10px;border:1px solid #3a2c1c;border-radius:999px;font-size:13px;margin:0}
  .tp-list.ib .ib-nav a:hover{border-color:var(--gold-lo)}
  .tp-list.ib .ib-nav a.cur{border-color:#9a6bd0;color:#f0dcff;background:rgba(154,107,208,.18)}
}
/* build 346: with the red New Thread pill now always on the board, the empty-state button steps back to purple (one primary per screen) */
.tp-emptybtn{background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;box-shadow:none !important}
/* build 346: on a phone the thread header has no room for the word; ➦ alone keeps the header its old height (hdstyle.js) */
@media (max-width:500px){.tp-detail .tp-hd .tp-share .tp-share-w{display:none}.tp-detail .tp-hd .tp-share{width:32px;padding:0;justify-content:center}}

/* ==================== build 347 (layout): chat room + whispers ==================== */
/* build 347 (layout): item 1 -- on a computer the Messages dock is fixed to the site's frame, not to
   the screen's corner. app.js placeDockOnFrame() measures the frame and sets the --dk-* numbers:
   closed, the bar sits at the right end of the frame's bottom toolbar; open, the panel covers the
   chat log and nothing else (never Send, the Online list, or the Ballot Box / Pit panels out in the
   gutters). The full-page takeovers keep their own !important corner rules, which still win here. */
@media (min-width:501px){
  .dm-dock.dm-framed{left:auto;top:auto;right:var(--dk-r);bottom:var(--dk-b);width:var(--dk-w);height:var(--dk-h)}
  .dm-dock.dm-framed.collapsed{right:var(--dk-bar-r);bottom:var(--dk-bar-b);width:190px;height:auto}
  .win>.status.dk-reserve{padding-right:104px} /* build 376: room for the small Messages bar (80px + 14px edge + 10px gap) when the buttons would otherwise sit under it */
  /* not enough room left in the toolbar row for the word: envelope, count and arrow only */
  .dm-dock.dm-framed.collapsed.dk-compact{width:auto}
  .dm-dock.dm-framed.collapsed.dk-compact .dm-bar-title{display:none}
  /* the roulette bubble used to step left of a corner panel; the panel is inside the frame now */
  .gc-root.dm-framed-root.dm-open .roulette-toggle-fab,.gc-root.dm-framed-root.dm-open.dm-thread .roulette-toggle-fab{right:12px}
  /* build 347 (layout): item 6 -- on a narrow computer screen the tools stay under the box, now 32px
     tall (were 28) and with Send its own size beside the box instead of stretched across the rest */
  .im .icomp{grid-template-columns:auto auto auto auto 1fr auto;grid-template-areas:"ta ta ta ta ta send" "emo media games mic . ."}
  .im .icomp .btn.emo,.im .icomp .btn.media,.im .icomp .btn.games,.im .icomp .btn.mic{height:32px}
}
/* build 347 (layout): item 6 -- once the frame is full size (760px) the open whisper is ~560px wide, so
   it takes the phone's layout: tools in one row left of the box, then Send. One layout for most people. */
@media (min-width:760px){
  .im .icomp{grid-template-columns:auto auto auto auto 1fr auto;grid-template-areas:none}
  .im .icomp > *{grid-area:auto !important}
  .im .icomp .btn.emo,.im .icomp .btn.media,.im .icomp .btn.games,.im .icomp .btn.mic{height:auto}
}

/* build 347 (layout): item 3 -- the whisper header's Back, Buzz and Collapse were 26x20 / 22x20 boxes
   holding "‹", "⚡" and "–", which mean nothing to a first-timer and were easy to miss-tap into each
   other. Now 32px-tall purple pills (the house "secondary" button) with words: "⚡ Buzz", "Hide". */
.im .bar .x,.im .bar .buzz,.im .bar .back{display:inline-flex;align-items:center;justify-content:center;gap:4px;
  height:32px;min-width:32px;width:auto;padding:0 10px;line-height:1;border-radius:16px;
  font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:#e2c4ff;border:1px solid #7a4bb0;background:linear-gradient(180deg,#3a2a48,#110918)}
.im .bar .back{width:32px;padding:0;font-size:20px}
.im .bar .buzz{font-size:13px}
.im .bar .bl{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px}
.im .bar{gap:6px}

/* build 347 (layout): item 4 -- each inbox row shows when its last line was, on the right of the name */
.im-tab .tline{display:flex;align-items:baseline;gap:8px;min-width:0}
.im-tab .tline .nm{flex:1;min-width:0}
.im-tab .tago{flex:none;font-size:11px;color:var(--ash);font-variant-numeric:tabular-nums}
.im-tab.unread .tago{color:#e2c4ff}

/* build 347 (layout): item 5 -- the Online list. Unread whispers are an envelope and a count after the
   name, not a purple diamond (the diamond is status only, as in the Friends list); your own row says
   "(you)" so it is clear why it is greyed and does nothing when tapped. */
.users .list .uw-tag{display:inline-block;margin:0 2px 0 4px;padding:0 5px;border-radius:9px;font:700 11px Georgia,serif;line-height:16px;
  color:#fff;background:#4a2a66;border:1px solid #9a6bd0;vertical-align:1px}
.users .list .you-tag{font-size:11px;font-style:italic;color:var(--ash)}
/* both tags sit straight after the name, before the level badge. The desktop column is only 160px,
   so on a row that carries a tag the level badge steps out there (cut in half by the row's "…" it
   read as a broken box); the phone list is full width and keeps it. */
@media (min-width:501px){#ulist > div.has-tag .lvl{display:none}}

.users .list div.uw-flash{animation:tabflash 1s ease-in-out 2}
@media (prefers-reduced-motion:reduce){.users .list div.uw-flash{animation:none}}

/* build 347 (layout): item 6 -- whisper Send is the red primary pill, same as the room's Send
   (#send), instead of purple. The tool buttons stay where they are on each size: in one row with
   the box on a phone (full-screen, room to spare), under the box on a computer (the panel is only
   ~360px wide, and in a row the box would shrink to ~80px). */
.im .icomp .btn:last-child{background:linear-gradient(180deg,#5a1d19,#1f0000);border:1px solid #c8342a;color:#ffe1dc;border-radius:14px;
  box-shadow:0 0 10px rgba(200,50,40,.5);text-shadow:0 1px 0 #000}
.im .icomp .btn:last-child:hover,.im .icomp .btn:last-child:focus-visible{border-color:#e0453a;color:#fff;outline:none;box-shadow:0 0 12px rgba(224,69,58,.6)}

/* build 347 (layout): item 7 -- the phone header's ⚙, 🔔 and purse were 26px tall. 32px now; the title
   bar is 34px inside, so they still fit without making it taller. */
@media (max-width:500px){
  .title-tools .cell,.title-tools .bell-toggle-fab.in-title.ready{width:32px;height:32px}
  .title-tools .purse-chip.in-title{height:32px}
}

/* build 347 (layout): item 8 -- a long room line wrapped back to the far left, under the timestamp.
   The time/flag/picture/name (.mhd) and the words (.mbody) now sit side by side (app.js renderRoom),
   so wrapped lines start under the first word. The words need at least 110px beside the name; when a
   very long name leaves less than that (a small screen), the words drop to their own full-width line
   under it rather than being squeezed into a sliver. */
.log .mrow{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:4px}
.log .mrow .mhd{flex:0 1 auto;min-width:0}
.log .mrow .mbody{flex:1 1 60px;min-width:0} /* build 347: 60px, so a short line with a "new" tag still fits beside the name at 360 (firstweek.js) */

/* build 347 (layout): item 9 -- the empty Messages panel gets a button (purple pill, secondary) that
   goes to the Online list */
.dm-empty .dm-find{margin-top:14px;min-height:36px;padding:0 16px;border-radius:18px;cursor:pointer;font:700 12px Cinzel,Georgia,serif;letter-spacing:1px;font-style:normal;
  color:#e2c4ff;border:1px solid #7a4bb0;background:linear-gradient(180deg,#3a2a48,#110918);box-shadow:0 0 8px rgba(166,122,209,.35)}
.dm-empty .dm-find:hover,.dm-empty .dm-find:focus-visible{color:#fff;border-color:#e2c4ff;outline:none;box-shadow:0 0 12px rgba(200,150,255,.6)}
/* build 347: with a whisper open over the room on a computer, the column grip is half under the panel and has nothing to resize; it steps away (taps24 desk/whisper) */
.gc-root.dm-framed-root.dm-open .users .uz{display:none}

/* ==================== build 348 (layout): the Game Room and the Pit (UI audit) ==================== */
/* build 348 (layout): one look per job. Join, every "Sit down" (UNO and Hold'em alike) and Call wear the red glow;
   No thanks and Raise / Bet are the purple second choice; Fold is the muted red outline, because it gives something up. */
.gr-join,.gr-hdsit,.gr-hd-acts .btn.gr-hd-call{background:linear-gradient(180deg,#5a1d19,#1f0000) !important;border:1px solid #c8342a !important;color:#ffe1dc !important;
border-radius:999px !important;box-shadow:0 0 8px rgba(200,50,40,.45) !important;text-shadow:0 1px 0 #000}
.gr-join:hover,.gr-hdsit:hover,.gr-hd-acts .btn.gr-hd-call:hover{border-color:#e0453a !important;color:#fff !important}
.gr-noinv,.gr-hd-acts .btn.gr-hd-raise-btn{background:linear-gradient(180deg,#1f1526,#0a050e) !important;border:1px solid #4a3560 !important;color:#b99ad8 !important;
border-radius:999px !important;box-shadow:none !important;text-shadow:0 1px 0 #000}
.gr-noinv:hover,.gr-hd-acts .btn.gr-hd-raise-btn:hover{border-color:#9a6bd0 !important;color:#e2c4ff !important}
.gr-hd-acts .btn.gr-hd-fold{background:linear-gradient(180deg,#240a0a,#0c0000) !important;border:1px solid #7a2a2a !important;color:#e07a7a !important;border-radius:999px !important;box-shadow:none !important}
.gr-hd-acts .btn.gr-hd-fold:hover{border-color:#c8342a !important;color:#ff9c9c !important}

/* build 348 (layout): the lobby row -- game and host on the first line, Hold'em's stakes on a line of their own */
.gr-row-hd .gr-row-stakes{flex-basis:100%;margin-top:-2px}

/* build 348 (layout): the table header (name, Invite, Leave) stays pinned to the top while you scroll, so Leave --
   and its 4-second "Forfeit and leave?" -- is always in reach. Below 900px the game and the table chat are one column,
   so the game wrapper steps aside (display:contents) and the header stays pinned over the chat too. */
.gr-thd{position:sticky;top:-12px;z-index:5;margin:-12px 0 8px;padding:8px 0;background:linear-gradient(180deg,#0d0a08 70%,rgba(13,10,8,.94));border-bottom:1px solid var(--gold-lo)}
@media (max-width:899px){.gr-table{display:block}.gr-game{display:contents}.gr-table > .gr-chat{margin-top:12px}.gr-thd{margin:-12px -14px 8px;padding:8px 14px}}
/* build 348 (layout): the round / stakes / hand line sits under the table's name as its own small line */
.gr-thd-r{display:block;margin-top:2px;font:400 11px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase}

/* build 348 (layout): Hold'em's buttons. Fold and Call on the first row; "Set: Min · Pot · Max" -- which only fill in the box --
   read as small dashed chips with a label, and the box plus Raise go under them. 34px tall on a phone. */
.gr-hd-raise{flex-basis:100%;gap:6px}
.gr-hd-presets{flex-basis:100%;justify-content:center;align-items:center;gap:6px}
.gr-hd-setlbl{font:italic 12px "IM Fell English",Georgia,serif;color:var(--ash)}
.gr-hd-acts .gr-hd-presets .btn.gr-hd-amt{height:28px;padding:0 12px;border-radius:999px;border:1px dashed #6a5088;background:none;color:#b99ad8;font:12px Georgia,serif !important;letter-spacing:0;text-transform:none;box-shadow:none}
.gr-hd-acts .gr-hd-presets .btn.gr-hd-amt:hover{border-style:solid;color:#e2c4ff}
.gr-hd-acts > .btn{min-width:96px}
@media (max-width:500px){.gr-hd-acts .btn,.gr-hd-in{height:34px}.gr-hd-acts .gr-hd-presets .btn.gr-hd-amt{height:32px}}

/* build 348 (layout): the bet on a seat says "bet 4", and D / SB / BB are spelled out once under the seats */
.gr-seat .hd-bet{font:700 11px Georgia,serif;letter-spacing:0;padding:0 8px}
.gr-hd-legend{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:center;gap:4px 14px;margin-top:-2px;font:12px Georgia,serif;color:var(--ash)}
.gr-hd-legend > span{display:inline-flex;align-items:center;gap:5px}
.gr-hd-legend .hd-btn{width:18px;height:18px;font-size:11px}

/* build 348 (layout): the Pit page. The "nobody here" note now sits inside the water, in front, with one line on how people get in. */
.pit-tank .pt-water > .pt-empty{z-index:3;flex-direction:column;gap:8px;padding:0 24px;text-align:center}
.pit-tank .pt-empty b{font-weight:400}
.pit-tank .pt-empty-s{display:none}
.gc-root.pit-open .pit-tank .pt-empty{color:#a9c6d4;text-shadow:0 1px 2px #000}
.gc-root.pit-open .pit-tank .pt-empty b{font-size:16px;color:#dbe8ef}
.gc-root.pit-open .pit-tank .pt-empty-s{display:block;max-width:320px;font:italic 13px/1.4 "IM Fell English",Georgia,serif}
/* build 348 (layout): open pit votes, with Yes / No, in a strip under the page header */
.pit-tank .pt-votes,.pit-tank .pt-mine{display:none}
.gc-root.pit-open .pit-tank .pt-votes:not(.hidden){display:block;order:1;width:100%;box-sizing:border-box;padding:6px 12px;background:linear-gradient(180deg,#1f1526,#0d0812);border-bottom:1px solid #4a3560;position:relative;z-index:2}
.pt-votes .ptv-one{max-width:760px;margin:0 auto;padding:4px 0;font:13px/1.35 Georgia,serif;color:var(--bone)}
.pt-votes .ptv-one + .ptv-one{border-top:1px solid rgba(154,107,208,.25)}
.pt-votes .ptv-b{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;margin-top:3px;font-size:12px}
.pt-votes .ptv-clock{color:#e2c4ff;font-variant-numeric:tabular-nums}
.pt-votes .ptv-btns{display:inline-flex;gap:8px;margin-left:auto}
.pt-votes .sys-act{min-height:32px;padding:0 14px}
/* build 348 (layout): if you're in the Pit yourself, your time and Climb out sit right under the tank */
.gc-root.pit-open .pit-tank .pt-mine:not(.hidden){display:flex;order:1;flex-wrap:wrap;align-items:center;justify-content:center;gap:6px 12px;width:100%;box-sizing:border-box;padding:8px 12px;
background:#071015;border-bottom:1px solid #1f4658;font:13px Georgia,serif;color:#dbe8ef}
.pt-mine .ptm-t b{font-variant-numeric:tabular-nums;color:#fff}
.pt-mine .ptm-note{font:italic 13px "IM Fell English",Georgia,serif;color:#a9c6d4}
.pt-mine .pb-climb{min-height:34px;padding:0 16px}
/* build 348 (layout): each fish shows its time left under its name */
.pit-tank .pt-fish .pt-left{display:block;font:11px Georgia,serif;color:#a9c6d4;text-shadow:0 1px 0 #000,0 0 4px #000;font-variant-numeric:tabular-nums;white-space:nowrap}
/* build 348 (layout): the header wears the 8-ball the menu uses (the 🕳️ emoji drew as a grey smudge), and the Pit's colour is
   the water's blue instead of a grey that made its "‹ Chat" look switched off next to the Game Room's green one */
.tp-hd .pt-hd-ico{display:inline-block;width:22px;height:22px;vertical-align:-5px;margin-right:7px;image-rendering:pixelated}
.pit-tank .tp-hd{--gold:#4f9fc4;--gold-hi:#a8dcf2;--gold-lo:#1f4658;--hd-acc:#4f9fc4;--hd-acc-b1:#17394a;--hd-acc-b2:#08161d;--hd-acc-ink:#dff3fb}
/* build 348 (layout): the dealer button on a seat is readable (it was a 9px letter on a 16px dot) */
.gr-seat-hd .hd-btn{width:18px;height:18px;font-size:11px}
/* build 349: name suggestions under a prompt field (circle Invite) -- tap one to invite them */
.prompt-sug{display:flex;flex-direction:column;margin-top:6px;max-height:220px;overflow-y:auto;border:1px solid #2a2620;border-radius:4px;background:#0b0705}
.prompt-sug.hidden{display:none}
.prompt-sug-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:36px;padding:6px 10px;text-align:left;background:none;border:none;border-bottom:1px solid #2a2620;
font:14px "IM Fell English",Georgia,serif;color:var(--bone);cursor:pointer}
.prompt-sug-row:last-child{border-bottom:none}
.prompt-sug-row:hover,.prompt-sug-row:focus-visible{background:rgba(201,162,74,.18);color:var(--gold-hi)}
.prompt-sug-note{font:italic 12px Georgia,serif;color:var(--ash);white-space:nowrap}
.prompt-sug-none{padding:8px 10px;font:italic 13px Georgia,serif;color:var(--ash)}
@media (pointer:coarse){.prompt-sug-row{min-height:44px}}
/* build 349: finished set-up steps fold into one quiet line */
.hm-setup-done{display:flex;align-items:center;gap:8px;min-height:30px;font:13px "IM Fell English",Georgia,serif;color:var(--ash)}
.hm-setup-done .hm-setup-ic{color:#8fc98f;font:700 15px Georgia,serif}
.hm-setup-done .hm-setup-l{white-space:normal;line-height:1.3;padding:4px 0}
.hm-setup-done + .hm-setup-row{border-top:1px solid #2a2119}
/* build 349: on phones the set-up card shows only the next step; "N more" opens the rest */
@media (max-width:999px){
  .hm-setup:not(.open) .hm-setup-row.later{display:none}
  .hm-setup-more{display:block;margin:6px 0 0;min-height:36px;padding:4px 0;background:none;border:0;color:var(--gold-hi);font:13px "IM Fell English",Georgia,serif;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
  .hm-setup.open .hm-setup-more{display:none}
  .hm-setup-foot{display:flex;align-items:center;justify-content:space-between;gap:8px}
  .hm-setup-foot .hm-setup-hide{margin:6px 0 0 auto}
}
@media (min-width:1000px){ .hm-setup-more{display:none} }
/* build 349: whisper tools between 501 and 759px wide. The panel is a size container here, so the layout follows the
   panel, not the screen: 460px or wider it takes the one-row layout phones and big screens use (tools, box, Send);
   narrower (a ~350px panel), the tools stay under the box as before -- labelled pills were tried and pushed Send off
   the panel's edge, since four labels plus Send need ~370px. */
@media (min-width:501px) and (max-width:759px){ .im{container-type:inline-size} }
@container (min-width:460px){
  .im .icomp{grid-template-columns:auto auto auto auto 1fr auto;grid-template-areas:none}
  .im .icomp > *{grid-area:auto !important}
  .im .icomp .btn.emo,.im .icomp .btn.media,.im .icomp .btn.games,.im .icomp .btn.mic{height:auto}
}
/* build 349: the 🚩 on every room line. Phones: gone from the line -- hold the line and pick 🚩 Report (the same menu as
   Reply). Computers: it keeps its place but only shows while the pointer is on that line or it has keyboard focus, so a
   screen of chat is no longer a column of grey flags. Whisper lines keep theirs (they have no hold menu). */
.rpicker .rp-report{grid-column:1 / -1;width:auto;height:26px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:#f0b3ab;
  background:linear-gradient(180deg,#2a1210,#110605);border:1px solid #6b2a22;border-radius:3px;margin-bottom:2px}
.rpicker .rp-report[hidden]{display:none}
.rpicker.has-report .rp-reply:not([hidden]){grid-column:1 / 3}
.rpicker.has-report .rp-reply:not([hidden]) ~ .rp-report{grid-column:3 / 5}
.rpicker .rp-report:hover,.rpicker .rp-report:focus-visible{color:#fff;border-color:#c8342a;box-shadow:0 0 8px rgba(200,50,40,.5);outline:none}
@media (hover:none){ .log .rpt-msg{display:none} }
@media (hover:hover){
  .log .m .rpt-msg{visibility:hidden}
  .log .m:hover .rpt-msg,.log .m:focus-within .rpt-msg,.log .rpt-msg:focus-visible{visibility:visible}
}
/* build 350b: the header's left group gets Roulette after Games. Here, after the build-226 order rules, because the same
   selectors earlier in the file lose to those (Games and Roulette both came out order -1, and Roulette sat first). */
@media (min-width:760px){
  .win > .title > #homeBtn{order:-4} .win > .title > #threadToggleBtn{order:-3} .win > .title > #gameRoomBtn{order:-2} .win > .title > #rouletteToggleBtn{order:-1}
}
/* ==================== build 352: the Roulette page ====================
   The standard page bar (‹ Chat + name) instead of the square "Back to chat" at the bottom; the chat's Today box
   and the top-five list stay in the gutter and never show on this page; the hint is readable. */
.roulette-panel > .rp-hd{display:none}
.gc-root.mobile-roulette-open .roulette-panel > .rp-hd{display:flex;align-self:stretch;position:sticky;top:0;z-index:2;margin:0 0 8px;width:auto;
  background:linear-gradient(180deg,#1a130c,#0b0805);border-bottom:1px solid var(--gold-lo)}
.gc-root.mobile-roulette-open .roulette-panel{padding-top:0 !important}
.gc-root.mobile-roulette-open .roulette-panel > .rp-hd + *{margin-top:auto}
.gc-root.mobile-roulette-open .roulette-panel > .rp-hd .ico-wheel{display:inline-block;width:22px;height:22px;vertical-align:-5px;margin-right:7px}
.gc-root.mobile-roulette-open .roulette-panel > :is(.td-box,.rp-back){display:none !important} /* the Contest's top five stays under the wheel, as since build 318 */
.gc-root.mobile-roulette-open .rp-hint{color:#c9b48a;font-size:12px;opacity:1}
.rp-blurb .rp-b2{display:block;margin-top:8px;font-size:.92em;color:var(--ash)}
.gc-root.mobile-roulette-open .rp-blurb{max-width:400px;margin-left:auto;margin-right:auto;line-height:1.45}
/* build 352: on every size the page scrolls instead of clipping (a 720px-high laptop ran the fortune into the footer),
   the bar runs edge to edge, the wheel gives way on short screens, and the footer sits under the fortune in the flow
   (relative, not static: its 24px tap strip is an absolute ::after, and static let it anchor to the page -- a strip across the wheel) */
.gc-root.mobile-roulette-open .roulette-panel{overflow-y:auto;justify-content:flex-start;padding-left:0 !important;padding-right:0 !important}
.gc-root.mobile-roulette-open .roulette-panel > .room-watermark{position:relative !important;margin:14px auto auto;transform:none;flex:none}
.gc-root.mobile-roulette-open .rp-wheel{width:min(236px,32vh);height:min(236px,32vh)}
.gc-root.mobile-roulette-open .roulette-panel > :not(.rp-hd){padding-left:16px;padding-right:16px;box-sizing:border-box}
.gc-root.mobile-roulette-open .roulette-panel > .rp-wheel{padding:0;width:min(236px,32vh,70vw) !important;height:min(236px,32vh,70vw) !important}
/* build 352: the visitors' teaser column keeps to the first line of the description; the rest pushed its hint into the footer */
.gc-root:not(.mobile-roulette-open) .rp-blurb .rp-b2{display:none}
/* build 352: the teaser column's footer sat on top of "Click the wheel" (older than this build). It is position:relative
   (for its tap strip) but kept the room footer's bottom:34px / right:10px, which as relative offsets lifted it into the
   line above. In the column it just follows the hint. */
#rouletteWatermark{right:auto;bottom:auto;top:auto;margin-top:12px}

/* ==================== build 353: one look for every pop-up (owner picked "A's look with C's phone behaviour") ====================
   Every dialog is .modal inside .modal-overlay and every small menu is .nmenu, so these rules restyle all of them at once:
   a warm dark card with soft corners and one thin gold line, the title on the left with a rule under it, labels that read
   like a form (not centred capitals), 42px fields, pill buttons with the main one red on the right. Mock-ups:
   tests/mockup-popups.js, tests/popvars/. */
/* shared by all three: labels read left to right like a form, not centred shouting */
.modal{text-align:left}
.modal .pfe-lbl{text-align:left;text-transform:none;letter-spacing:.2px}
.modal .cc-door{text-align:left}
.modal .save-actions{display:flex;justify-content:flex-end;gap:10px;flex-wrap:wrap}
.nmenu button{display:flex;align-items:center;gap:10px;min-height:40px}
/* A: lamplit card -- one warm dark card, soft corners, one hairline, the name up top with a line under it */
.modal-overlay{background:rgba(0,0,0,.72);backdrop-filter:blur(3px)}
.modal{background:linear-gradient(180deg,#1b140d,#120d08) !important;border:1px solid rgba(201,162,74,.5) !important;border-radius:14px !important;
  box-shadow:0 24px 70px rgba(0,0,0,.9),inset 0 1px 0 rgba(255,230,180,.07) !important;padding:18px 20px 16px !important;outline:none !important}
.modal-hd{font:700 17px Cinzel,Georgia,serif !important;letter-spacing:1px !important;color:#f0d79a !important;text-shadow:none !important;text-align:left !important;
  padding:0 0 12px !important;margin:0 0 12px !important;border-bottom:1px solid #33271b !important}
.modal .modal-body{font:15px "IM Fell English",Georgia,serif !important;color:#e6d8bc !important;text-align:left !important}
.modal .pfe-lbl{font:600 13px Georgia,serif !important;color:#d8c49a !important;margin:14px 0 5px !important}
.modal .pfe-dim{font:italic 12px Georgia,serif;color:#8f836c}
.modal .sunk,.modal input,.modal select,.modal textarea{border-radius:9px !important;min-height:42px;background:#0a0705 !important;border:1px solid #3d3024 !important;box-shadow:none !important;padding:8px 12px !important;font-size:15px !important}
.modal .sunk:focus,.modal input:focus,.modal select:focus{border-color:#c9a24a !important;outline:none !important;box-shadow:0 0 0 3px rgba(201,162,74,.18) !important}
.modal .pf-chip{border-radius:999px !important;font:600 13px Georgia,serif !important;letter-spacing:0 !important;text-transform:none !important;padding:7px 14px !important;background:#0f0b07 !important;border:1px solid #3d3024 !important;color:#d8c9a8 !important}
.modal .pf-chip.on{background:#2a1f10 !important;border-color:#c9a24a !important;color:#f5dfa4 !important;box-shadow:none !important}
.modal .cc-door{border-radius:11px !important;border:1px solid #3d3024 !important;background:#0f0b07 !important;padding:11px 14px !important}
.modal .cc-door.on{border-color:#c9a24a !important;background:#221a0f !important}
.modal .save-actions{margin-top:18px !important;padding-top:14px;border-top:1px solid #2b2117}
.modal .save-actions .btn{border-radius:999px !important;min-height:40px;padding:0 18px !important;font:700 13px Cinzel,Georgia,serif !important;letter-spacing:.6px !important;
  background:transparent !important;border:1px solid #5a4630 !important;color:#e0cfa8 !important;box-shadow:none !important}
.modal .save-actions .btn:last-child{background:linear-gradient(180deg,#6b221c,#2a0806) !important;border-color:#d0463a !important;color:#fff0ea !important;box-shadow:0 0 12px rgba(200,50,40,.35) !important}
.nmenu{background:linear-gradient(180deg,#1b140d,#120d08) !important;border:1px solid rgba(201,162,74,.5) !important;border-radius:12px !important;padding:6px !important;box-shadow:0 18px 50px rgba(0,0,0,.9) !important}
.nmenu .hd{justify-content:flex-start !important;font:700 11px Cinzel,Georgia,serif !important;letter-spacing:1.6px !important;color:#bfa670 !important;padding:8px 10px 9px !important;border-bottom:1px solid #33271b !important}
.nmenu button{border-radius:8px !important;padding:8px 10px !important;font:15px "IM Fell English",Georgia,serif}
.nmenu button:hover,.nmenu button:focus-visible{background:rgba(201,162,74,.12) !important;border-color:transparent !important}
/* on phones every dialog and small menu rises from the bottom as a sheet, in thumb reach; buttons full width, the main one on top.
   The photo cropper keeps the middle of the screen (it needs the height). */
@media (max-width:500px){
  .modal-overlay:not(.ph-crop){align-items:flex-end !important;padding:0 !important}
  .modal-overlay:not(.ph-crop) > .modal{max-width:100% !important;width:100% !important;border-radius:20px 20px 0 0 !important;border-bottom:none !important;
    padding-top:26px !important;padding-bottom:calc(16px + env(safe-area-inset-bottom)) !important;position:relative;max-height:88vh !important;overflow:auto}
  .modal-overlay:not(.ph-crop) > .modal::before{content:"";position:absolute;top:9px;left:50%;width:40px;height:4px;margin-left:-20px;border-radius:2px;background:#5a4630}
  .modal .save-actions{flex-direction:column-reverse}
  .modal .save-actions .btn{width:100%}
  .nmenu.open{left:8px !important;right:8px !important;top:auto !important;bottom:calc(8px + env(safe-area-inset-bottom)) !important;width:auto !important;max-width:none !important;border-radius:16px !important}
}
/* build 353: the Save / bug-report / ban forms use plain <label>s rather than .pfe-lbl -- same form look */
.modal label:not(.cc-door):not(.pf-chip){display:block;text-align:left !important;font:600 13px Georgia,serif !important;letter-spacing:.2px !important;text-transform:none !important;color:#d8c49a !important;margin:14px 0 5px}
/* build 355 (COPPA): the "I'm 13 or older" tick on a new character. Hidden when this device already has a character
   (the #snNote line shows then) -- a returning player isn't asked again. */
.login label.age-row{display:flex;align-items:flex-start;justify-content:flex-start;gap:9px;box-sizing:border-box;width:100%;max-width:var(--age-w,240px);margin:12px auto 2px;font:13px "IM Fell English",Georgia,serif;letter-spacing:0;text-transform:none;color:#e2c4ff;cursor:pointer;text-align:left;line-height:1.35}
.login label.age-row input{-webkit-appearance:auto;appearance:auto;color-scheme:dark;accent-color:#9a6bd0;width:18px !important;height:18px !important;min-height:0 !important;margin:1px 0 0 !important;padding:0 !important;flex:none;cursor:pointer;background:none !important;border:none !important;box-shadow:none !important}
.login label.age-row .terms-link{font:inherit;color:#e2c4ff;text-decoration:underline;text-underline-offset:2px;background:none;border:0;padding:0;cursor:pointer}
#snNote:not(.hidden) ~ #ageRow{display:none}
@media (pointer:coarse){ .login label.age-row{min-height:44px;align-items:center} .login label.age-row input{width:22px !important;height:22px !important} }
.bp-blurb .bp-fine{display:block;margin-top:3px;font-size:11px;opacity:.85}
/* build 355: with the real fonts now served from the site, a whisper line is a pixel shorter and the next line took the
   bottom row of the flag's 24x24 invisible target (taps24: 24x23). The flag sits above its neighbours. */
.im .ilog .rpt-msg{z-index:1}
.log .rpt-msg::after,.im .ilog .rpt-msg::after{width:26px;height:26px} /* build 355: 24px centred on a half-pixel measured 23 rows */

/* ==================== build 356: edit, unsend, silence, paste a picture (app.js "build 356") ==================== */
/* the hold menu: every action is half a row, so Reply | Edit and Copy | Unsend (or Reply | Report and Copy) sit in pairs */
.rpicker .rp-act{grid-column:span 2;width:auto;height:28px;margin-bottom:2px;border-radius:3px;
  font:700 11px Cinzel,Georgia,serif;letter-spacing:.3px;white-space:nowrap;
  color:var(--gold);background:linear-gradient(180deg,#281f15,#110c07);border:1px solid var(--gold-lo)}
.rpicker .rp-act[hidden]{display:none}
.rpicker .rp-act.rp-report,.rpicker .rp-act.rp-unsend{color:#f0b3ab;background:linear-gradient(180deg,#2a1210,#110605);border-color:#6b2a22}
.rpicker .rp-act:hover,.rpicker .rp-act:focus-visible{color:var(--gold-hi);border-color:var(--gold);box-shadow:0 0 8px rgba(201,162,74,.5);outline:none}
.rpicker .rp-act.rp-report:hover,.rpicker .rp-act.rp-unsend:hover,.rpicker .rp-act.rp-report:focus-visible,.rpicker .rp-act.rp-unsend:focus-visible{color:#fff;border-color:#c8342a;box-shadow:0 0 8px rgba(200,50,40,.5)}
.rpicker.acts-only .rp-emo{display:none}
.rpicker.acts-only{grid-template-columns:repeat(4,36px)}
/* an edited line, an unsent one */
.m .edited{margin-left:5px;font-size:11px;font-style:italic;color:var(--muted,#a89a86);opacity:.85}
.m button.m-hist{display:inline-block;min-height:24px;min-width:24px;padding:0 2px;background:none;border:0;cursor:pointer;
  font:inherit;color:inherit;text-decoration:underline dotted;text-underline-offset:3px;vertical-align:baseline}
.m button.m-hist.edited{font-size:11px;font-style:italic}
.m .unsent-txt{font-style:italic;color:var(--muted,#a89a86)}
.reply-bar.editing{border-color:var(--gold)}
/* a silenced conversation: a bell with a line through it beside the name, and a grey badge */
.im-tab.hushed .nm::after,.im.hushed .bar .nm::after{content:' \1F515';font-size:11px}
.im-tab.hushed .badge{filter:grayscale(1);opacity:.75}
/* a pasted or dropped picture, shown before it goes */
.ask-img{display:block;max-width:100%;max-height:40vh;margin:10px auto 0;border:1px solid var(--gold-lo);border-radius:4px}
#askBody.ask-pre{max-height:50vh;overflow:auto}
.drop-on{outline:2px dashed var(--gold);outline-offset:-4px}

/* ==================== build 357: the phone keyboard and an open whisper (app.js "build 357") ====================
   When the keyboard comes up, the phone shrinks only what you can SEE (the visual viewport), not the page, and slides the
   page up to show the box you are typing in -- which carried the whisper's header off the top of the screen. While the
   keyboard is up and the cursor is in the whisper, the whisper is laid over exactly the part of the screen you can see. */
@media (max-width:500px){
  .gc-root.signed-on.kb-dm .dm-dock:not(.collapsed){top:calc(var(--vv-top, 0px) + 4px);bottom:calc(var(--vv-b, 0px) + 4px);height:calc(var(--vv-h, 100vh) - 8px);transition:none}
}

/* ==================== build 358: link cards, search, the NEW line, last seen, pins, forwarding (app.js "build 358") ====================
   The looks the owner picked from tests/shots/b358-*.png: Links C, Search A + B, New A, Last seen A, Pin A, Forward A. */
/* a link card: picture at the side, title (two lines at most), the site's name */
.lp{display:flex;margin:6px 0 2px;max-width:300px;min-height:64px;border:1px solid var(--gold-lo,#6b5530);border-radius:6px;overflow:hidden;
  background:linear-gradient(180deg,#1d160f,#0e0a06);text-decoration:none;color:inherit}
.lp .lp-img{flex:none;width:92px;position:relative;background:linear-gradient(135deg,#5a1d19,#2a1a3a 60%,#0d0a14)}
.lp .lp-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.lp.vid .lp-img::after{content:"\25B6";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-size:13px;color:#fff;background:rgba(200,30,30,.9);border-radius:8px;padding:2px 8px}
.lp .lp-tx{display:flex;flex-direction:column;justify-content:center;gap:2px;min-width:0;padding:6px 9px}
.lp .lp-t{font:700 13px "IM Fell English",Georgia,serif;color:var(--bone,#e8dcc8);line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.lp .lp-d{font:11px Georgia,serif;color:#9a8b73;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lp:hover,.lp:focus-visible{border-color:var(--gold,#c9a24a);outline:none}
/* forwarded */
.fwd-tag{display:block;font:italic 11px "IM Fell English",Georgia,serif;color:#9a8b73;margin:1px 0}
/* the NEW line */
.new-line{display:flex;align-items:center;gap:8px;margin:10px 4px 6px;font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold,#c9a24a);text-transform:uppercase}
.new-line::before,.new-line::after{content:"";flex:1;height:1px;background:var(--gold,#c9a24a)}
/* the pinned bar under the header */
.im .pin-bar{display:flex;align-items:center;gap:8px;width:auto;margin:6px 8px;padding:7px 10px;min-height:36px;box-sizing:border-box;flex:none;
  border:1px solid var(--gold-lo,#6b5530);border-radius:6px;background:linear-gradient(180deg,#221a10,#110c07);
  font:13px "IM Fell English",Georgia,serif;color:var(--bone,#e8dcc8);text-align:left;cursor:pointer}
.im .pin-bar b{font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold,#c9a24a);flex:none;text-transform:uppercase}
.im .pin-bar .pb-t{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.im .pin-bar i{font-style:normal;color:#9a8b73;flex:none}
.im .pin-bar:hover,.im .pin-bar:focus-visible{border-color:var(--gold,#c9a24a);outline:none}
/* find inside one conversation, and search across all of them */
.im .find-bar,.dm-search{display:flex;align-items:center;gap:6px;flex:none;margin:6px 8px;padding:6px 8px;border:1px solid var(--gold-lo,#6b5530);border-radius:6px;background:#0b0806}
.im .find-bar.hidden,.dm-results.hidden{display:none}
.im .find-bar input,.dm-search input{flex:1;min-width:0;height:34px;box-sizing:border-box;background:#050200;border:1px solid #3a3026;color:var(--bone,#e8dcc8);
  font:16px "IM Fell English",Georgia,serif;padding:0 9px;border-radius:4px}
.im .find-bar .fb-n,.dm-search .ds-n{font:11px Georgia,serif;color:#9a8b73;white-space:nowrap}
.im .find-bar button{flex:none;width:32px;height:32px;padding:0;background:#1a130c;border:1px solid var(--gold-lo,#6b5530);color:var(--gold,#c9a24a);border-radius:4px;cursor:pointer}
mark.fhl{background:rgba(201,162,74,.45);color:#fff;border-radius:2px;padding:0 1px}
.m.find-cur mark.fhl{background:#c9a24a;color:#1a1208}
.dm-inbox.searching #imTray,.dm-inbox.searching #frqSection,.dm-inbox.searching #dmEmpty{display:none !important}
.dm-results{padding:0 6px 6px}
.dm-results .ds-row{display:flex;flex-direction:column;gap:2px;width:100%;box-sizing:border-box;padding:9px 10px;min-height:44px;text-align:left;cursor:pointer;
  background:none;border:0;border-bottom:1px solid #2a2118;color:var(--bone,#e8dcc8);font:13px "IM Fell English",Georgia,serif}
.dm-results .ds-row:hover,.dm-results .ds-row:focus-visible{background:rgba(201,162,74,.08);outline:none}
.dm-results .ds-top{display:flex;justify-content:space-between;gap:8px}
.dm-results .ds-top b{font:700 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold,#c9a24a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dm-results .ds-top span{font:11px Georgia,serif;color:#8f836c;flex:none}
.dm-results .ds-sn{color:#cfc3ae;overflow-wrap:anywhere}
.dm-results mark{background:rgba(201,162,74,.35);color:#fff;border-radius:2px;padding:0 1px}
.dm-results .ds-none{padding:14px 10px;font:italic 13px "IM Fell English",Georgia,serif;color:#9a8b73}
/* six actions now: a little more room so "↪ Forward" fits its half-row (b356.js measures it) */
.rpicker{grid-template-columns:repeat(4,38px)}
.rpicker .rp-emo{justify-self:center}
.rpicker .rp-act{letter-spacing:0;padding:0 3px}
.rpicker.acts-only{grid-template-columns:repeat(4,38px)}
/* on a phone the header was full: Find keeps its 🔍 and drops the word (the button says "Find in this chat" to a screen reader) */
@media (max-width:500px){ .im .bar .find{width:32px;padding:0} .im .bar .find .bl{display:none} }

/* build 360: reactions under whisper and group lines -- the room's pills, on their own row under the words */
.im .ilog .m > .reactions{margin:3px 0 1px}
.im .ilog .m > .reactions:empty{display:none}

/* ==================== build 361 ==================== */
/* forwards are a quote card (look 2Y): "↪ Tony wrote" on top, the words under it, one gold rule down the left */
.im .m.is-fwd .fwd-qh{display:block;font:italic 11px "IM Fell English",Georgia,serif;color:#9a8b73;margin:2px 0 0;padding:4px 8px 1px;border-left:3px solid #c9a24a;background:rgba(201,162,74,.07);border-radius:0 8px 0 0}
.im .m.is-fwd .fwd-qh b{font-style:normal;color:#c9b089}
.im .m.is-fwd .mtxt{display:block;padding:1px 8px 5px;border-left:3px solid #c9a24a;background:rgba(201,162,74,.07);border-radius:0 0 8px 0;margin-bottom:2px}
.im .m.is-fwd.fwd-wait .mtxt,.im .m.is-fwd.fwd-wait .lp{visibility:hidden}
.im .m.is-fwd.fwd-hide .mtxt,.im .m.is-fwd.fwd-hide .lp{display:none}
.im .m.is-fwd .fwd-show{display:block;box-sizing:border-box;width:100%;text-align:left;margin:0 0 2px;padding:3px 8px 6px;border:0;border-left:3px solid #c9a24a;background:rgba(201,162,74,.07);border-radius:0 0 8px 0;cursor:pointer;font:italic 12px "IM Fell English",Georgia,serif;color:#c9a24a}
.im .m.is-fwd .fwd-show span{display:inline-block;border:1px dashed #6b5733;border-radius:8px;padding:2px 10px}
.im .m.is-fwd .fwd-show:focus-visible{outline:none}.im .m.is-fwd .fwd-show:focus-visible span{outline:2px solid #c9a24a;outline-offset:1px}
/* the whisper header on phones (look B): 🔍, ⚡ Buzz / 👥 People go into ⋯; Hide becomes an arrow */
.im .bar .more{display:none}
@media (max-width:500px){
  .im .bar .buzz{display:none !important}
  .im .bar .more{display:inline-flex;align-items:center;justify-content:center;flex:none;width:32px;height:32px;padding:0;border-radius:50%;border:1px solid #7a4bb0;background:none;color:#c9a3e6;font:700 18px/1 Georgia,serif;cursor:pointer}
  .im .bar .x{width:32px !important;min-width:32px;padding:0 !important}
  .im .bar .x .bl{display:none}
  .im .bar .x::before{content:"▾";font-size:16px;line-height:1}
}

/* ==================== build 362: the Messages tray stays on a profile page (computers) ====================
   The page hid the whole dock (display:none, v134), so on a computer the tray vanished the moment you opened
   someone's page. From 501px it now stays where the Game Room keeps it: the same pill, bottom right, and a
   whisper opens in the tray over the page (z-index 45 over the page's 40). Phones still close the page first. */
@media (min-width:501px){
  .gc-root.signed-on.profile-open:not(.no-dms) .dm-dock:not(.hidden){display:flex !important}
}
/* the open tray over a page is 260px by the chat's own formula (made for sitting beside the room), which cut the header
   ("Hid…") and left the box you type in 114px wide on a profile page and 18px in the Game Room (measured at 1280).
   Over a full page there is no room column to leave space for, so it opens 460px wide (the room's own is 554). */
@media (min-width:501px){
  .gc-root:is(.profile-open,.gameroom-open,.home-open,.hap-open,.circ-open,.pit-open,.leaderboard-open,.admin-open,.mobile-threads-open,.mobile-roulette-open) .dm-dock:not(.collapsed){width:min(460px,calc(100vw - 16px)) !important;max-width:none}
}

/* ==================== build 363: the Messages tray on EVERY page ====================
   The owner: "i also want the messaging tray to be available on ALL pages", and on a phone the bottom bar's Messages
   button did nothing on a profile page. Profile, Home, Circles, Happenings and the Pit each hid the dock outright
   (display:none !important, one rule per page). Now: computers keep the tray on all of them (the pill in the corner,
   the chat opening over the page); phones show it when opened from the bottom bar, a whisper button or a toast
   (the folded pill stays hidden on phones, as it is in the room -- the bottom bar's Messages is the way in). */
@media (min-width:501px){
  .gc-root.signed-on:is(.profile-open,.home-open,.hap-open,.circ-open,.pit-open):not(.no-dms) .dm-dock:not(.hidden){display:flex !important}
}
@media (max-width:500px){
  .gc-root.signed-on:is(.profile-open,.home-open,.hap-open,.circ-open,.pit-open):not(.no-dms) .dm-dock:not(.hidden):not(.collapsed){display:flex !important}
}

/* ==================== build 365: room lines -- the words on their own line (owner picked B, everywhere) ====================
   Build 347 put the name and the words side by side so a long line wrapped under its first word instead of back under
   the timestamp. On a phone (and a thin window) a long name plus its level badge took half the width, and the words ran
   down a narrow strip on the right: "text from messages in the main chat is being pushed all to the right" (the owner,
   29 Sept 03:19). Mock-ups docs/mockups/mk-room-390.png / mk-room-617.png; he picked B at every width: time, picture and
   name on the first line, the words under them, starting under the picture. The time gets a fixed width so every line's
   words start in the same place; the colon after the name goes (it pointed at nothing). */
.log .mrow .mhd .t{display:inline-block;min-width:44px;margin-right:6px}
.log .mrow .mbody{flex:1 1 100%;padding-left:50px;box-sizing:border-box}
.log .mrow .who-c{display:none}

/* ==================== build 366: 16px in every typing box on a touch screen, pop-ups included ====================
   Build 353's one pop-up look set `.modal input/select/textarea{font-size:15px !important}`, which outranked the
   touch rule above (16px, so iPhone Safari does not zoom the page when a box is tapped). Every text box inside a
   pop-up -- report, friend-request hello, the page editor, an admin's email login box -- zoomed iPhones from build
   353 on. tests/loginbox.js had caught it, but it was never in the sweep list; it is now, with a site-wide check
   in tests/b366.js. */
@media (hover:none) and (pointer:coarse){
  :is(.modal,.gc-root) :is(input:not([type=file]),select,textarea,input.sunk,select.sunk,textarea.sunk){font-size:16px !important} /* :is() takes the strongest name inside it (textarea.sunk), so this outranks .modal .sunk (the bug/idea boxes) without touching .sunk panels that are not typing boxes */
}

/* ==================== build 367: the owner's pixel icons ====================
   32x32 art at 32px, drawn with hard pixel edges (no smoothing). The phone's purse chip is only 32px tall, so its coin
   is 16px there (still sharp on a phone screen, where one art pixel lands on at least one device pixel). */
.pxi{width:32px !important;height:32px !important;image-rendering:pixelated;image-rendering:crisp-edges;display:inline-block;vertical-align:middle;flex:none;pointer-events:none;-webkit-user-drag:none;user-select:none}
.bnav .ic img{image-rendering:pixelated}
.bnav .ic img[src*="/px/"]{width:32px;height:32px}
.purse-chip.in-title .pxi{width:16px !important;height:16px !important}
/* the active bottom-bar tab lifts its icon 2px and grew it 12% (build 344); 12% of 32px is 36px, which draws the
   owner's pixel art with uneven pixels. The lift stays; the growth goes, for pixel icons only. */
.bnav button.on .ic:has(img[src*="/px/"]){transform:translateY(-2px)}
/* on full pages the Messages pill shrinks to its envelope in the corner (build 309 design). With the letter at 32px it
   grew from 41x43 to 58x54 and covered a Circles card in a thin window (run16.js). There it is 16px, as the phone
   purse coin is, which puts the pill back at its old size. In the room it stays 32px (the approved mock-up). */
.gc-root:is(.home-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.pit-open,.profile-open,.mobile-threads-open,.mobile-roulette-open) .dm-dock.collapsed .dm-bar-ico .pxi{width:16px !important;height:16px !important}

/* build 368: the owner's last three pixel icons (Ballot Box scroll, Settings gear, More pearls), link cards in the
   main room, and group chats in "Forward to…" */
.more-dots .pxi,.more-gear .pxi{display:block}
.log .mbody .lp{margin:5px 0 2px;max-width:340px}
.pick-row .pick-gic{flex:none;width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center}
.pick-row.pick-grp .pick-nm{font-weight:700}
.log .m.has-lp .mbody a.lp-src{display:none}
.bnav-sheet button .ic img[src*="/px/"]{width:32px;height:32px;image-rendering:pixelated}

/* build 373: "save your character before the upgrade" -- the ribbon above the typing box (guests only), and the popup's
   list of what a guest would lose. Mock-ups approved by the owner 29 Sept ("do all 3"). */
.save-ribbon{grid-column:1 / -1;display:flex;align-items:center;gap:10px;padding:7px 10px;margin:0 0 6px;border:1px solid var(--gold-hi);background:linear-gradient(180deg,rgba(224,182,74,.18),rgba(224,182,74,.08));color:var(--bone);font-size:13px;line-height:1.35;border-radius:3px}
.save-ribbon b{color:var(--gold-hi)}
.save-ribbon .sr-t{flex:1;min-width:0}
.save-ribbon .sr-go{font:700 11px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--gold);background:rgba(0,0,0,.35);border:1px solid var(--gold-lo);border-radius:4px;padding:3px 10px;cursor:pointer;white-space:nowrap}
.save-ribbon .sr-go:hover,.save-ribbon .sr-go:focus-visible{color:var(--gold-hi);border-color:var(--gold);outline:none}
.save-ribbon .sr-x{background:none;border:0;color:var(--bone);opacity:.7;font-size:16px;cursor:pointer;padding:0 4px;line-height:1}
.save-ribbon .sr-x:hover,.save-ribbon .sr-x:focus-visible{opacity:1;outline:none}
.ask-when{display:inline-block;margin-bottom:8px;padding:2px 8px;border:1px solid var(--gold-hi);border-radius:10px;font-size:12px;color:var(--gold-hi)}
.ask-stakes{margin:10px 0 2px;padding:8px 10px;border:1px dashed rgba(224,182,74,.55);border-radius:3px;line-height:1.6}
.ask-stakes b{color:var(--gold-hi)}
@media (max-width:500px){.save-ribbon{font-size:12px;gap:6px;padding:6px 8px}}
.ask-after{margin-top:8px}

/* ==================== build 384: the new layout (tablet and desktop, opt-in) ====================
   From the research report "Gypsy Chat UX redesign" and the owner's pick (30 Sept 2026, option A with B's whisper pane):
   from 600px wide, a labelled rail down the left (the phone's own bottom bar, redrawn), the room filling the screen with
   the people list on the right, every page opening beside the rail, and Messages as a right-hand pane in landscape
   (a sheet over the lower half in portrait). Behind Settings → "New layout" (html.lay2) until the owner makes it the
   default. Phones (under 600px) are untouched. */
@media (min-width:600px) and (min-height:520px){
  html.lay2 .gc-root.signed-on{--rail:88px;padding:0 0 0 var(--rail);justify-content:stretch;min-height:100dvh}
  html.lay2 .gc-root.signed-on .win{max-width:none;height:100dvh;display:flex;flex-direction:column}
  html.lay2 .gc-root.signed-on .win > .body{flex:1;min-height:0;grid-template-columns:1fr max(var(--users-w,160px),240px);grid-template-rows:1fr auto auto auto;padding:10px 12px}
  html.lay2 .gc-root.signed-on .win > .body .log{height:auto;min-height:0}
  html.lay2 .gc-root.signed-on .win > .body .users{min-height:0}
  /* the rail */
  html.lay2 .gc-root.signed-on .bnav{display:flex;flex-direction:column;position:fixed;left:0;top:0;bottom:0;width:var(--rail);z-index:46;padding:10px 6px;gap:4px;box-sizing:border-box;
    background:linear-gradient(180deg,#1d150e,#0a0704);border-right:1px solid var(--gold-lo);box-shadow:4px 0 14px rgba(0,0,0,.6)}
  html.lay2 .bnav button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;min-height:66px;padding:8px 2px 7px;border:0;border-radius:12px;background:none;
    color:#b9a988;font:700 11px Cinzel,Georgia,serif;letter-spacing:.4px;cursor:pointer;position:relative;-webkit-tap-highlight-color:transparent}
  html.lay2 .bnav button .ic{height:32px;display:flex;align-items:center;justify-content:center;font-size:26px;line-height:1}
  html.lay2 .bnav button .ic img{width:32px;height:32px;object-fit:contain;image-rendering:pixelated}
  html.lay2 .bnav button .lb{white-space:nowrap}
  html.lay2 .bnav button:hover{color:var(--gold-hi);background:rgba(196,154,82,.08)}
  html.lay2 .bnav button.on{color:var(--gold-hi);background:rgba(196,154,82,.14);box-shadow:inset 0 0 0 1px var(--gold-lo)}
  html.lay2 .bnav button:focus-visible{outline:2px solid var(--gold-hi);outline-offset:-2px}
  html.lay2 .bnav button.news::after{content:"";position:absolute;top:8px;left:calc(50% + 12px);width:9px;height:9px;border-radius:50%;background:#e0b04a;box-shadow:0 0 0 2px #140e09}
  html.lay2 .bnav .bnav-badge{position:absolute;top:4px;left:calc(50% + 6px);min-width:18px;height:18px;border-radius:9px;background:#c8342a;color:#fff;font:700 10px/18px Georgia,serif;text-align:center;padding:0 5px;box-sizing:border-box;border:2px solid #000}
  html.lay2 .bnav .bnav-badge.hidden{display:none}
  html.lay2 #bnavChat{order:1}html.lay2 #bnavMessages{order:2}html.lay2 #bnavGames{order:3}html.lay2 #bnavThreads{order:4}html.lay2 #bnavHome{order:5}html.lay2 #bnavMore{order:6;margin-top:auto}
  /* More: a panel beside the rail instead of a bottom sheet */
  html.lay2 .gc-root.signed-on .bnav-sheet{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;position:fixed;left:calc(var(--rail) + 8px);bottom:10px;width:360px;z-index:47;box-sizing:border-box;padding:10px 12px 14px;
    background:linear-gradient(180deg,#221810,#120c08);border:1px solid var(--gold-lo);border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.7)}
  html.lay2 .bnav-sheet h4{grid-column:1/-1;margin:2px 4px 4px;font:700 11px Cinzel,Georgia,serif;letter-spacing:2px;color:#8f7446;text-transform:uppercase}
  html.lay2 .bnav-sheet button{display:flex;flex-direction:column;align-items:center;gap:5px;padding:12px 4px;border-radius:12px;border:1px solid #3a2c1c;background:#1a130d;color:var(--bone);font:13px Georgia,serif;position:relative;cursor:pointer;min-height:44px}
  html.lay2 .bnav-sheet button:hover{background:#241a11}
  html.lay2 .bnav-sheet button .ic{font-size:24px;height:28px;display:flex;align-items:center}
  html.lay2 .bnav-sheet button .ic img{width:28px;height:28px;object-fit:contain}
  html.lay2 .bnav-sheet button i{font-style:normal;font-size:10px;color:#8f836c}
  html.lay2 .bnav-sheet .bnav-dot{position:absolute;top:8px;right:10px;width:8px;height:8px;border-radius:50%;background:#e0b04a}
  html.lay2 .gc-root.signed-on .bnav-dim{display:block;position:fixed;left:var(--rail);right:0;top:0;bottom:0;background:rgba(0,0,0,.45);z-index:46}
  /* the title bar's own Home / Threads / Games buttons: the rail has them */
  html.lay2 .gc-root.signed-on .win > .title #homeBtn,html.lay2 .gc-root.signed-on .win > .title #threadToggleBtn,html.lay2 .gc-root.signed-on .win > .title #gameRoomBtn{display:none !important}
  /* every page opens beside the rail */
  html.lay2 .gc-root.signed-on.mobile-threads-open .threads-panel,html.lay2 .gc-root.signed-on.admin-open .admin-panel,html.lay2 .gc-root.signed-on.leaderboard-open .leaderboard-panel,
  html.lay2 .gc-root.signed-on.mobile-roulette-open .roulette-panel,html.lay2 .gc-root.signed-on.gameroom-open .gameroom-panel,html.lay2 .gc-root.signed-on.pit-open .pit-tank,
  html.lay2 .gc-root.signed-on.profile-open .profile-panel,html.lay2 .gc-root.signed-on.home-open .home-panel,html.lay2 .gc-root.signed-on.hap-open .hap-panel,
  html.lay2 .gc-root.signed-on.circ-open .circ-panel{left:var(--rail);right:0;width:auto;max-width:none}
  /* Messages: the rail opens and shuts it, so the closed bar goes; open, it is a sheet over the lower half (portrait) */
  html.lay2 #dmDock.collapsed{display:none !important} /* an ID: the pages bring the closed bar back as a bubble with their own !important rules */
  html.lay2 .dm-dock:not(.collapsed){left:var(--rail,88px);right:0;top:auto;bottom:0;width:auto;height:58dvh;border-radius:16px 16px 0 0;border:0;border-top:2px solid var(--gold);box-shadow:0 -10px 30px #000}
}
@media (min-width:1200px) and (min-height:520px){ html.lay2 .gc-root.signed-on .win > .body{grid-template-columns:1fr max(var(--users-w,160px),280px)} }
/* landscape tablet and desktop: Messages is a pane on the right, the room beside it */
@media (min-width:840px) and (min-height:520px){
  html.lay2 .dm-dock:not(.collapsed){left:auto;top:0;bottom:0;right:0;width:min(440px,40vw);height:auto;border-radius:0;border-top:0;border-left:2px solid var(--gold-lo);box-shadow:-6px 0 20px rgba(0,0,0,.6)}
  html.lay2:has(#dmDock:not(.collapsed):not(.hidden)) .gc-root.signed-on:not(.no-dms){padding-right:min(440px,40vw)}
}
/* under 1400px the people list steps aside while a whisper is open (the room keeps its width) */
@media (min-width:840px) and (max-width:1399px) and (min-height:520px){
  html.lay2:has(#dmDock:not(.collapsed):not(.hidden)) .gc-root.signed-on:not(.no-dms) .win > .body{grid-template-columns:1fr}
  html.lay2:has(#dmDock:not(.collapsed):not(.hidden)) .gc-root.signed-on:not(.no-dms) .win > .body .users{display:none}
}
.lay-hint{display:none}

/* build 384, reviewer fixes */
@media (min-width:600px) and (min-height:520px){
  /* 1: a page hides the room behind it (the plain rule above outranked every page's own .win{display:none}) */
  html.lay2 .gc-root.signed-on:is(.home-open,.mobile-threads-open,.gameroom-open,.pit-open,.profile-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.mobile-roulette-open) .win{display:none}
  /* 2: the wide-screen side columns (Today, the Ballot Box, the Pit) sat over the full-width room: off, except as their own page */
  html.lay2 .gc-root.signed-on:not(.mobile-roulette-open) .roulette-panel,html.lay2 .gc-root.signed-on .ballot-panel,html.lay2 .gc-root.signed-on:not(.pit-open) .pit-tank{display:none !important}
  html.lay2 .gc-root.signed-on #ballotBtn{display:flex}
  /* 3: Messages opened over a page keeps the new layout's size, not the old 460px panel */
  html.lay2 .gc-root:is(.home-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.pit-open,.profile-open,.mobile-threads-open,.mobile-roulette-open,.gameroom-open) .dm-dock:not(.collapsed){left:var(--rail,88px) !important;right:0 !important;width:auto !important;max-width:none !important}
  /* 6: the Ballot Box scroll clears the wider people list */
  html.lay2 .gc-root.signed-on .bp-mscroll{right:calc(max(var(--users-w,160px),240px) + 34px)}
  /* 14: notches and home indicators */
  html.lay2 .gc-root.signed-on .bnav{padding-top:calc(10px + env(safe-area-inset-top));padding-bottom:calc(10px + env(safe-area-inset-bottom))}
  html.lay2 .gc-root.signed-on .win{padding-bottom:env(safe-area-inset-bottom);padding-top:env(safe-area-inset-top)}
  html.lay2 .dm-dock:not(.collapsed){padding-bottom:env(safe-area-inset-bottom)}
  /* 16: the title bar keeps only what the rail and More do not have */
  html.lay2 .gc-root.signed-on .win > .title #rouletteToggleBtn,html.lay2 .gc-root.signed-on .win > .title #pitBtn{display:none !important}
  /* 15: banners centre on the area beside the rail */
  html.lay2 body:has(.gc-root.signed-on) .update-banner{left:calc(88px + 8px)}
}
@media (min-width:1200px) and (min-height:520px){ html.lay2 .gc-root.signed-on .bp-mscroll{right:calc(max(var(--users-w,160px),280px) + 34px)} }
@media (min-width:840px) and (min-height:520px){
  html.lay2 .dm-dock:not(.collapsed){padding-top:env(safe-area-inset-top)}
  html.lay2 .gc-root:is(.home-open,.hap-open,.circ-open,.leaderboard-open,.admin-open,.pit-open,.profile-open,.mobile-threads-open,.mobile-roulette-open,.gameroom-open) .dm-dock:not(.collapsed){left:auto !important;width:min(440px,40vw) !important}
  /* 12: alerts stay clear of the Messages pane's buttons */
  html.lay2:has(#dmDock:not(.collapsed):not(.hidden)) .toasts{right:calc(min(440px,40vw) + 10px)}
}
@media (min-width:840px) and (max-width:1399px) and (min-height:520px){
  html.lay2:has(#dmDock:not(.collapsed):not(.hidden)) .gc-root.signed-on .bp-mscroll{right:18px}
}

/* ==================== build 385: the new layouts by default; Me; Readings; colours ====================
   The same five places on every screen (Chat, Messages, Games, Threads, Me), Me as your own picture; Me holds Home,
   the places that were under More, Readings and Settings. Colours from the approved mock-up (tests/shots/colour-compare.png):
   a hue per place, a jewel tone per name, the hour card on dark parchment. All text colours 4.5:1 or better. */
#bnavMe{display:none}
html.lay2 .bnav #bnavMe{display:flex}
html.lay2 .bnav #bnavHome,html.lay2 .bnav #bnavMore{display:none !important}
.bnav .ic .bnav-ava{width:28px;height:28px;min-width:28px;border-radius:50%;object-fit:cover;image-rendering:auto;display:inline-flex;align-items:center;justify-content:center;
  font:700 12px/1 Cinzel,Georgia,serif;color:#1a1208;background:#e6b25a;border:2px solid #000;box-shadow:0 0 0 1px var(--gold-lo);box-sizing:border-box}
.bnav button.on .ic .bnav-ava{box-shadow:0 0 0 2px var(--pc,var(--gold-hi))}
html.lay2{--ash:#9a8e7b;--sys:#9a8e7b}
html.lay2 #bnavChat{--pc:#e0a23c}html.lay2 #bnavMessages{--pc:#e8708a}html.lay2 #bnavGames{--pc:#46c58f}html.lay2 #bnavThreads{--pc:#a684e6}html.lay2 #bnavMe{--pc:#e8c46a}
html.lay2 .bnav button.on{color:var(--pc,var(--gold-hi))}
html.lay2 .bnav:has(#bnavChat.on) .bnav-ind{background:#e0a23c}html.lay2 .bnav:has(#bnavMessages.on) .bnav-ind{background:#e8708a}
html.lay2 .bnav:has(#bnavGames.on) .bnav-ind{background:#46c58f}html.lay2 .bnav:has(#bnavThreads.on) .bnav-ind{background:#a684e6}html.lay2 .bnav:has(#bnavMe.on) .bnav-ind{background:#e8c46a}
@media (min-width:600px) and (min-height:520px){
  html.lay2 #bnavMe{order:5}
  html.lay2 .bnav button .ic .bnav-ava{width:32px;height:32px;min-width:32px;font-size:13px}
  html.lay2 .bnav button.on{background:rgba(196,154,82,.12);background:color-mix(in srgb,var(--pc,#c49a52) 15%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--pc,#c49a52) 55%,transparent)}
}
/* names: each person their own jewel tone (set by app.js as --nc); your own name and admins keep theirs */
html.lay2 .log .them b.who:not(.admin),html.lay2 .log .sys b.who:not(.admin),html.lay2 .tp-posts .tp-post b.who:not(.admin),html.lay2 .gr-line:not(.me) b.who:not(.admin),
html.lay2 .hm-body b.who:not(.admin){color:var(--nc,var(--them))}
/* the hour of prayer in the room: dark parchment with a gold edge, not a bright card at night; off entirely when the switch says so */
html.lay2 .m.scripture{background:linear-gradient(180deg,#221a12,#1a140e);color:var(--bone);border:1px solid #4a3a24;outline:0;border-radius:10px;box-shadow:inset 3px 0 0 #8a6a34,0 2px 10px rgba(0,0,0,.5)}
html.lay2 .m.scripture .sc-hd{color:#d9b56a}html.lay2 .sc-theme{color:#a89676}html.lay2 .m.scripture .sc-body{color:var(--bone)}html.lay2 .sc-red{color:#e8806f}html.lay2 .m.scripture .sc-ref{color:#b8955a;opacity:1}
html.no-hours .log .m.scripture{display:none}
/* Me */
html.lay2 #homePanel.me-sub #homeFilter{display:none}
.me-top{display:flex;flex-direction:column}
.me-hd{display:flex;align-items:center;gap:14px;padding:6px 2px 12px}
.me-hd .me-ava{width:58px;height:58px;min-width:58px;border-radius:50%;object-fit:cover;display:inline-flex;align-items:center;justify-content:center;font:700 22px Cinzel,Georgia,serif;
  color:#1a1208;background:#e6b25a;border:2px solid #000;box-shadow:0 0 0 1px var(--gold-lo);box-sizing:border-box}
.me-id{min-width:0}
.me-nm{font:700 17px Cinzel,Georgia,serif;color:var(--gold-hi);letter-spacing:1px;overflow-wrap:anywhere}
.me-row{display:flex;gap:10px;align-items:center;margin-top:6px;flex-wrap:wrap}
.me-coins{display:inline-flex;align-items:center;gap:5px;font:700 12px Cinzel,Georgia,serif;color:var(--gold-hi)}
.me-coins img{width:20px;height:20px;image-rendering:pixelated}
.me-page{margin-left:auto;flex:none;min-height:40px;padding:0 14px;border-radius:20px;border:1px solid var(--gold-lo);background:#17110c;color:var(--gold-hi);font:700 12px Cinzel,Georgia,serif;white-space:nowrap;cursor:pointer}
.me-places{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:6px;padding:2px 0 12px;border-bottom:1px solid rgba(107,80,36,.6);max-width:760px}
.me-place{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:4px;min-height:64px;padding:8px 1px;border-radius:10px;border:1px solid #33271b;
  background:#120d09;color:var(--bone);font:700 10px/1.15 Cinzel,Georgia,serif;text-align:center;cursor:pointer;min-width:0}
@media (max-width:500px){ .me-places{gap:4px} .me-place{font-size:8.5px;letter-spacing:0} }
.me-place:hover{background:#1c150f}
.me-place .ic{height:30px;display:flex;align-items:center;justify-content:center;font-size:24px}
.me-place .ic img{width:30px;height:30px;object-fit:contain;image-rendering:pixelated}
.me-place .bnav-dot{position:absolute;top:6px;right:6px;width:8px;height:8px;border-radius:50%;background:#e0b04a}
.me-seg{display:flex;gap:6px;padding:12px 0;max-width:520px}
.me-tab{flex:1;min-height:42px;border-radius:21px;border:1px solid #3a2c1d;background:#110c08;color:#9a8e7b;font:700 13px Cinzel,Georgia,serif;cursor:pointer;white-space:nowrap;padding:0 6px}
.me-tab.on{color:#1a1208;border-color:var(--gold);background:linear-gradient(180deg,#f1d98a,#b88f3e)}
.me-tab:focus-visible,.me-place:focus-visible,.me-set:focus-visible,.me-switch:focus-visible,.me-page:focus-visible,.hs-ava:focus-visible,.hs-all:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px}
.me-tabbody{display:flex;flex-direction:column;gap:12px}
.me-col{display:flex;flex-direction:column;gap:12px;min-width:0}
.me-card{border:1px solid #3a2c1d;border-radius:12px;background:#15100c;padding:12px 14px}
.me-card h3{margin:0 0 8px;font:700 12px Cinzel,Georgia,serif;letter-spacing:1.5px;color:var(--gold);text-transform:uppercase}
.me-swrow{display:flex;align-items:center;gap:12px}
.me-swrow b{font-weight:normal;font-size:16px;color:var(--bone)}
.me-swrow small{display:block;font-size:13px;color:#9a8e7b;margin-top:3px}
.me-switch{margin-left:auto;flex:none;width:54px;height:32px;border-radius:16px;border:1px solid #4a3a24;background:#2a2016;position:relative;cursor:pointer;padding:0}
.me-switch::after{content:"";position:absolute;left:4px;top:4px;width:22px;height:22px;border-radius:50%;background:#9a8e7b;transition:transform .15s}
.me-switch.on{background:#4f9a4f;border-color:#5aa15a}.me-switch.on::after{transform:translateX(23px);background:#fff}
@media (prefers-reduced-motion:reduce){.me-switch::after{transition:none}}
.me-day{font:700 15px Cinzel,Georgia,serif;color:var(--gold-hi)}
.me-today .sun-title{font-style:italic;margin:4px 0 0;color:var(--bone)}
.me-today .sun-refs{margin-top:10px}
.me-src{font-size:12px;color:#9a8e7b;margin-top:8px}
.me-hour{display:flex;gap:12px;padding:10px 0;border-top:1px solid #241b13}
.me-hour:first-of-type{border-top:0}
.me-hr{width:56px;flex:none;font:700 12px Cinzel,Georgia,serif;color:#9a8e7b;padding-top:2px}
.me-hr i{display:block;font-style:normal;font-size:10px;color:#d6b8ff;letter-spacing:1px;text-transform:uppercase;margin-top:2px}
.me-hb{min-width:0}
.me-hn{font:700 13px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold-hi)}
.me-th{font-size:13px;color:#9a8e7b;font-style:italic}
.me-vs{margin-top:6px;font-size:15.5px;line-height:1.5;color:var(--bone)}
.me-vs .sc-red{color:#e8806f}
.me-ref{display:block;margin-top:4px;font:700 10.5px Cinzel,Georgia,serif;letter-spacing:1px;color:var(--gold)}
.me-hour.me-now{margin:4px -8px;padding:10px 8px;border-radius:10px;background:#1d1520;border:1px solid #5b3f78}
.me-hour.me-later{opacity:.6}
.me-sets{padding-top:10px;padding-bottom:4px}
.me-set{display:flex;align-items:center;gap:12px;width:100%;min-height:48px;padding:6px 2px;border:0;border-top:1px solid #241b13;background:none;color:var(--bone);font:16px "IM Fell English",Georgia,serif;text-align:left;cursor:pointer}
.me-sets > h3 + .me-set,.me-sets > .me-set:first-child{border-top:0}
.me-set .ic{width:28px;flex:none;display:flex;align-items:center;justify-content:center;font-size:20px}
.me-set .ic img{width:24px;height:24px;object-fit:contain}
.me-set .ic .ava,.me-set .ic .ava-fallback{width:26px;height:26px;min-width:26px;border-radius:50%;font-size:12px}
.me-sl{min-width:0}
.me-chev{margin-left:auto;color:#9a8e7b;font-size:20px}
@media (max-width:360px){ .me-places{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (min-width:1000px){
  html.lay2 #homeBody.hm-body{align-content:start} /* the page is taller than its content: no stretching the header's row */
  html.lay2 #homeBody.hm-body > .me-top{grid-column:1/-1;grid-row:1}
  html.lay2 #homeBody.hm-body > .hm-main,html.lay2 #homeBody.hm-body > .hm-side{grid-row:2}
  html.lay2 #homeBody.hm-body > .me-tabbody{grid-column:1/-1;grid-row:2}
  .me-readings{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;align-items:start}
  .me-settings{max-width:640px}
}
/* the phone's "Here now" strip; the folded people drawer it replaces steps aside ("All" unfolds it) */
.here-strip{display:none}
@media (max-width:500px){
  html.lay2 .gc-root.signed-on .here-strip{display:flex;align-items:center;gap:8px;padding:5px 10px;border-bottom:1px solid rgba(107,80,36,.5);background:#0d0906;flex:none;min-height:46px;box-sizing:border-box}
  html.lay2 .gc-root.signed-on.users-folded #users{display:none !important}
  html.lay2 .gc-root.signed-on .win > .title #moreBtn{display:none !important}
  .hs-lbl{font:700 11px Cinzel,Georgia,serif;color:#9a8e7b;letter-spacing:1px;white-space:nowrap;text-transform:uppercase}
  .hs-avs{display:flex;gap:4px;overflow:hidden;flex:1;min-width:0}
  .hs-ava{flex:none;width:36px;height:36px;padding:2px;border:0;background:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center}
  .hs-ava .ava,.hs-ava .ava-fallback{width:32px;height:32px;min-width:32px;border-radius:50%;font-size:13px;margin:0}
  .hs-all{flex:none;min-height:34px;padding:0 12px;border-radius:17px;border:1px solid var(--gold-lo);background:#17110c;color:var(--gold-hi);font:700 11px Cinzel,Georgia,serif;letter-spacing:1px;text-transform:uppercase;cursor:pointer}
}
details.me-hour > summary{list-style:none;display:flex;gap:12px;cursor:pointer;min-height:40px;align-items:flex-start}
details.me-hour > summary::-webkit-details-marker{display:none}
details.me-hour{display:block}
details.me-hour .me-hn::after{content:" ▸";color:#9a8e7b;font-size:11px}
details.me-hour[open] .me-hn::after{content:" ▾"}
details.me-hour .me-vs{margin-left:68px}
details.me-hour > summary:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px;border-radius:6px}
/* build 386: the classic layout is the default again. The hours switch shows everywhere (Readings is on Home in both layouts); the Layout switch is hidden — the rail stays as a hidden opt-in (gc_layout = 'new') for the owner to try again later */
#layBtn,#statusPopover #layBtn{display:none !important}
#homePanel.me-sub #homeFilter{display:none}
.hm-classic .me-seg{max-width:360px;padding:8px 0 10px}
@media (min-width:1000px){ #homeBody.hm-body > .me-top.hm-classic{grid-column:1/-1;grid-row:1} #homeBody.hm-body > .hm-main,#homeBody.hm-body > .hm-side{grid-row:2} #homeBody.hm-body > .me-tabbody{grid-column:1/-1;grid-row:2} #homeBody.hm-body{align-content:start} }
html:not(.lay2) .hm-side > .hm-sec.hm-sun{display:none}

/* >>> build 387 >>> */
/* ==================== build 387 (1 Oct 2026): C12 + polish ====================
   The owner chose "C1 layout with C2 palette" and the dark reading card, then a polish pass across the
   whole site (research: docs/research/retro-chat-aesthetic-polish.md). Paint only: every border keeps its
   width, so nothing on the page moves -- tests/b387.js checks the boxes against build 386.
   1. three golds, three text tints, two purple lines (decorative / control edge)
   2. the title in metallic gold instead of a glow; the Messages button is the room's one glow
   3. one thin gold frame, brighter at the top, on the window and its side columns (the classic layout)
   4. the reading card dark everywhere: gold heading, softened red words, set like a rubric
   5. edges lit from above, one focus ring, and the decorative glows switched off (the generated list) */
:root{--gold:#d9b56a;--text-2:#a89a7f;--text-3:#8f8371;--hair:#5a4890;--edge:#7464ad;--frame-hi:#a8823c;--frame-lo:#4f3b1b}
html.gc-night{--gold:#d6a560}

/* 1. text that was too faint to read: timestamps and the typing-box hints */
.log .t,.im .ilog .t,.tp-posts .tp-post .t,.gr-line .t,.pt-line .t,.hm-txt .t{color:var(--text-2)}
:where(textarea,input)::placeholder{color:var(--text-3)}
.compose textarea::placeholder,.bp-compose textarea::placeholder,.im .icomp textarea::placeholder{color:var(--text-3)}
/* the page behind the window: warm near-black, not pure black, so the window's shadow has something to fall on */
.gc-root{background:radial-gradient(ellipse at 50% 0%,#1d150e 0%,#060403 70%)}

/* 2. the title: polished gold, lit from the top, no haze */
.title .name{color:var(--gold);background-image:linear-gradient(180deg,#f3e2b3 0%,#e6c98a 34%,#d9b56a 50%,#c49c4a 72%,#d9b56a 100%);
-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-shadow:none !important;filter:drop-shadow(0 1px 0 rgba(0,0,0,.7))}

/* 3. the classic window and its side columns: one thin gold line, bright along the top and fading down.
   Drawn with three background layers inside the old 3px border (gold at the outer 1px, the window colour
   in the 2px inside it), so the border keeps its width and nothing inside shifts. */
html:not(.lay2) .win[role="application"],html:not(.lay2) #ballotPanel{border:3px solid transparent;outline:0;
background:linear-gradient(180deg,var(--stone-2),var(--stone)) padding-box,
linear-gradient(180deg,#120d09,#0b0806) 1px 1px/calc(100% - 2px) calc(100% - 2px) no-repeat border-box,
linear-gradient(180deg,var(--frame-hi) 0,var(--gold-lo) 120px,var(--frame-lo) 400px) border-box}
html:not(.lay2) .gc-root:not(.mobile-roulette-open) #roulettePanel,html:not(.lay2) .gc-root:not(.pit-open) #pitTank{border-style:solid;border-color:transparent;outline:0;
background:linear-gradient(180deg,#070505,#000) padding-box,
linear-gradient(180deg,#0a0706,#030202) 1px 1px/calc(100% - 2px) calc(100% - 2px) no-repeat border-box,
linear-gradient(180deg,var(--frame-hi) 0,var(--gold-lo) 120px,var(--frame-lo) 400px) border-box}
/* on a phone the window is tall and the line would fade to almost nothing down the sides, so it stays at the middle gold */
@media (max-width:500px){html:not(.lay2) .win[role="application"]{background:linear-gradient(180deg,var(--stone-2),var(--stone)) padding-box,
linear-gradient(180deg,#120d09,#0b0806) 1px 1px/calc(100% - 2px) calc(100% - 2px) no-repeat border-box,
linear-gradient(180deg,var(--frame-hi) 0,var(--gold-lo) 120px) border-box}}
html:not(.lay2) .win[role="application"]{box-shadow:0 8px 30px #000}
html:not(.lay2) .gc-root:not(.mobile-roulette-open) #roulettePanel,html:not(.lay2) #ballotPanel,html:not(.lay2) .gc-root:not(.pit-open) #pitTank{box-shadow:0 8px 30px #000 !important}
html:not(.lay2) .win[role="application"]::before,html:not(.lay2) .win[role="application"]::after,html:not(.lay2) .win[role="application"] > .corner{display:none}
html:not(.lay2) .win[role="application"] > .title{background:#120d09;border-bottom-color:#3a2c1d;box-shadow:none}
@media (max-width:500px){html:not(.lay2) .win[role="application"] > .title{box-shadow:0 4px 12px rgba(0,0,0,.6)}}

/* the log and the people list sit in the window instead of in boxes of their own; a purple hairline divides them */
html:not(.lay2) .win #log.sunk{border-color:transparent !important;box-shadow:none !important}
html:not(.lay2) .win #users.sunk{border-color:transparent !important;border-left-color:var(--hair) !important;box-shadow:none !important}
@media (max-width:500px){html:not(.lay2) .win #users.sunk{border-left-color:transparent !important;border-top-color:var(--hair) !important}}
html:not(.lay2) .users .hd{background:linear-gradient(180deg,#1b1424,#120d19) !important;border-bottom-color:var(--hair) !important;box-shadow:inset 0 1px 0 rgba(214,184,255,.11)}
html:not(.lay2) .users .hd.frhd{border-top-color:var(--hair) !important}
html:not(.lay2) .users .hint{border-top-color:#2a2016}

/* the room's name bar */
html:not(.lay2) .pit-bowl{border-color:var(--hair) !important;background:linear-gradient(180deg,#1b1424,#120d19) !important;border-radius:8px;box-shadow:inset 0 1px 0 rgba(214,184,255,.11) !important}
html:not(.lay2) .pit-bowl .pb-one:not(.me){border-color:var(--hair) !important}

/* the typing row: edges you can see (3:1), one corner size, light from above */
html:not(.lay2) #emoBtn,html:not(.lay2) #gifBtn{border-color:var(--edge) !important;background:#15101c !important;border-radius:8px !important;
box-shadow:inset 0 1px 0 rgba(205,193,166,.10),0 1px 0 rgba(5,3,2,.6) !important}
html:not(.lay2) #emoBtn:is(:hover,:focus-visible),html:not(.lay2) #gifBtn:is(:hover,:focus-visible){border-color:#9a86d6 !important}
html:not(.lay2) #msg{border-color:var(--edge) !important;background:#050302 !important;border-radius:8px !important;
box-shadow:inset 0 1px 2px rgba(0,0,0,.6),inset 0 -1px 0 rgba(205,193,166,.05) !important}
html:not(.lay2) #msg:focus{border-color:#9a86d6 !important;box-shadow:inset 0 1px 2px rgba(0,0,0,.6),0 0 0 2px rgba(122,79,208,.28) !important}
html:not(.lay2) #send{border-radius:8px !important;box-shadow:inset 0 1px 0 rgba(255,220,200,.18),0 1px 0 rgba(5,3,2,.6) !important}

/* the bottom bar: plain, with warm brown buttons */
html:not(.lay2) .win .status{border-top-color:#3a2c1d !important;background:transparent !important;box-shadow:none !important}
@media (min-width:501px){
html:not(.lay2) .win .status > button.cell:not(.dmbtn){border-color:#3a2c1d !important;background:#120d09 !important;border-radius:8px !important;
box-shadow:inset 0 1px 0 rgba(205,193,166,.10),0 1px 0 rgba(5,3,2,.6) !important}
html:not(.lay2) .win .status > button.cell:not(.dmbtn):hover{background:#1b1611 !important}
html:not(.lay2) .win .status > button.cell:active{transform:translateY(1px)}
/* Messages: the one thing in the room that glows -- a tight halo and two soft blooms in its own purple.
   The border goes from 3px double to 2px solid, so 1px of padding keeps the inside where it was. */
html:not(.lay2) #dmDock.collapsed.dm-framed{border:2px solid #7a4fd0 !important;padding:1px !important;outline:0 !important;border-radius:12px !important;background:#1c1328 !important;
box-shadow:inset 0 1px 0 rgba(214,184,255,.12),0 0 0 1px rgba(122,79,208,.25),0 0 6px rgba(122,79,208,.35),0 0 18px rgba(122,79,208,.18) !important}
/* the bar inside keeps its new-whisper flash (an animation, so no !important here) */
html:not(.lay2) #dmDock.collapsed.dm-framed #dmBar{background:#1c1328;text-shadow:0 1px 0 #000;border-radius:10px;position:relative}
}

/* the whisper window's typing row gets the same visible edges as the room's */
.im .icomp textarea{border-color:var(--edge) !important;border-radius:8px}
.im .icomp .btn:not(:last-child):not(.on){border-color:var(--edge) !important}
.im .icomp .btn{border-radius:8px}
.bp-compose textarea,#tpReplyBody{border-color:var(--edge)}
/* the purple names and headers that still had a haze */
.users .hd,.pit-bowl .pb-title,.im .bar .nm{text-shadow:0 1px 0 #000}
#dmBar:focus-visible{outline-offset:-3px !important}

/* other people's new lines fade up into the room (your own appear at once: you pressed Enter, you know) */
@keyframes gcMsgIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
/* (the whisper windows already ink new lines in, build 326; this is only the room) */
.log > .m.them:last-child{animation:gcMsgIn .18s ease-out backwards}
/* unread whispers: the Messages button breathes, slowly, until they are read */
@keyframes gcPillPulse{0%,100%{opacity:.25}50%{opacity:.8}}
@media (min-width:501px){
/* drawn inside the bar: the dock clips anything outside its own edge */
html:not(.lay2) #dmDock.collapsed.dm-framed:has(#dmBarBadge:not(.hidden)) #dmBar::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
box-shadow:inset 0 0 14px rgba(160,110,230,.7);opacity:.25;animation:gcPillPulse 2.4s ease-in-out infinite}
}
@media (prefers-reduced-motion:reduce){
.log > .m.them:last-child{animation:none}
html:not(.lay2) #dmDock.collapsed.dm-framed:has(#dmBarBadge:not(.hidden)) #dmBar::after{animation:none;opacity:.6}
}

/* 4. the reading card, dark everywhere it appears (the room, and the hour that is now on Readings) */
:is(html.lay2,html) .m.scripture{background:#14101c;color:var(--bone);border:1px solid var(--hair);outline:0;border-radius:8px;
box-shadow:inset 0 1px 0 #1f1b24,0 1px 0 rgba(5,3,2,.7),0 2px 4px rgba(5,3,2,.4)}
:is(html.lay2,html) .m.scripture .sc-hd{color:var(--gold);font:700 12px Cinzel,Georgia,serif;letter-spacing:.12em;column-gap:2px;flex-wrap:wrap}
:is(html.lay2,html) .m.scripture .sc-theme{color:#bfae8e;font:italic 14px "IM Fell English",Georgia,serif;font-size:14px !important;letter-spacing:0;opacity:1}
:is(html.lay2,html) .m.scripture .sc-body{color:var(--bone)}
:is(html.lay2,html) .m.scripture .sc-red,.me-vs .sc-red{color:#f09a8a}
:is(html.lay2,html) .m.scripture .sc-ref{color:var(--text-2);opacity:1;font:700 11px Cinzel,Georgia,serif;letter-spacing:.1em}
.me-hour.me-now{background:#14101c;border-color:var(--hair);box-shadow:inset 0 1px 0 #1f1b24}

/* 5. light from above on the cards and menus, everywhere: the top edge one step lighter than the rest */
.me-card{border-top-color:#4d3b27}
.modal-overlay > .modal,div.nmenu{border-top-color:rgba(232,211,162,.72) !important}
.gr-open,.gr-row,.gr-quick{border-top-color:#8a6a34}
.tp-hd{box-shadow:0 1px 0 #000,inset 0 1px 0 rgba(255,240,210,.06)}

/* one focus ring for everything you can tab to (text boxes keep their own lit edge instead) */
:where(button,a,summary,select,[role="button"],[tabindex]:not(input):not(textarea)):focus-visible{outline:2px solid #b48cff !important;outline-offset:2px}

/* the decorative glows, switched off (generated by tools/b387_build.py from the rules on these lines of build 386) */
.users .list div.f-online{text-shadow:0 1px 0 #000}
.tp-new{text-shadow:0 1px 0 #000}
.thread-toggle-fab{box-shadow:0 0 0 1px #000,0 4px 16px #000}
.rp-title{text-shadow:0 2px 0 #000,0 -1px 0 #000}
.bp-title{text-shadow:0 2px 0 #000,0 -1px 0 #000}
.gameroom-toggle-fab{box-shadow:0 0 0 1px #000,0 4px 16px #000}
.gr-quick .gr-quickseat{box-shadow:0 0 0 1px #000}
.hap-panel .hp-nav{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.hap-panel .hp-new{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.circ-panel #circNew,.circ-panel .cc-join{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.circ-panel [data-circback]{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.hap-panel [data-hapback]{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.hap-panel .hp-rsvp [data-rsvp="going"],.hap-panel .hp-rsvp [data-rsvp="maybe"],.hap-panel .hp-wall button[type=submit],.hap-panel [data-hapdel]{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
#tpNewBtn.tp-new,#tpReplySend,.pf-act[data-act="wave"],.pf-act[data-act="gift"],.pf-act[data-act="friend"],.pf-act[data-act="add"],.pf-wall button[type=submit],.pf-comp button[type=submit],
.gr-quickseat,.gr-sit,#ballotCast{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
.tp-listings-chip,.sun-ref,.sys-act{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
#send{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
#travelForm #trvOk{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.tpx-line h2{text-shadow:0 1px 0 #000}
@media (max-width:860px){.tpx-line .tp-new{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55),0 6px 18px rgba(0,0,0,.6)}}
#join{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.win{box-shadow:0 0 0 2px var(--gold),0 0 0 3px #000,inset 0 0 0 1px #000}
.tp-list.ib .ib-btitle,.ib-thead .ib-btitle{text-shadow:0 1px 0 #000}
#tpNewSubmit{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
.circ-panel .cc-join,.circ-panel [data-creq][data-yes="1"]{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
.hp-form #hpfOk{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
.tp-list.ib #tpNewBtn.tp-new{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
.im .icomp .btn:last-child{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55)}
.gr-join,.gr-hdsit,.gr-hd-acts .btn.gr-hd-call{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
.modal .save-actions .btn:last-child{box-shadow:inset 0 1px 0 rgba(255,220,200,.16),0 1px 2px rgba(0,0,0,.55) !important}
/* <<< build 387 <<< */
/* >>> build 390: Patron of the Room -- nameplate (style B, purple glow) + lantern + the Settings card (look P2) >>> */
.pat-mark:empty{display:none}
.pat-mark{white-space:nowrap}
.pat-lan{display:inline-block;width:9px;margin-left:3px;vertical-align:-2px;filter:drop-shadow(0 0 4px rgba(240,168,50,.75))}
.pat-lan svg{display:block;width:100%;height:auto;overflow:visible}
.pat-lan .gl-s{fill:none;stroke:#cf9852;stroke-width:1.2}
.pat-lan .gl-g{fill:#cf9852}
.pat-lan .nl-glass{fill:rgba(240,168,50,.22)}
.pat-plate{display:inline-block;margin-left:5px;padding:0 6px;border-radius:8px;border:1px solid #8a6fd0;color:#e6d6ff;
  background:linear-gradient(180deg,rgba(138,111,208,.28),rgba(138,111,208,.08));box-shadow:0 0 6px rgba(195,60,255,.5),0 0 14px rgba(195,60,255,.22);
  font:600 9.5px/15px Cinzel,Georgia,serif;letter-spacing:.8px;text-transform:uppercase;white-space:nowrap;vertical-align:1px;text-decoration:none}
.log .m b.who:hover .pat-plate,.log .m b.who:focus-visible .pat-plate{text-decoration:none}
/* People list rows are narrow: the lantern only, never the plate */
.users .list .pat-plate{display:none}
/* the Settings card */
.pat-modal{max-width:380px !important}
.pat-since{font:italic 13px Georgia,serif;color:#bfa670;margin:0 0 10px}
.pat-pv{background:#0a0705;border:1px solid #3d3024;border-radius:10px;padding:10px 12px;font:15px "IM Fell English",Georgia,serif;color:#e6d8bc;line-height:1.6}
.pat-pv b.who{font:400 12px Cinzel,Georgia,serif;letter-spacing:.5px;color:var(--them)}
.pat-pv .t{color:#a89a7f;font-size:11px;margin-right:4px}
.modal label.pat-lbl{display:block;margin:14px 0 5px}
.modal select.pat-sel{width:100%;appearance:none;-webkit-appearance:none;color:#e6d8bc;font:600 13px Cinzel,Georgia,serif !important;letter-spacing:.6px;
  background:#0a0705 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23c9a24a' fill='none' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 12px center !important}
#patronBox .modal label.pat-row{display:flex !important;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;margin:0 !important;border-top:1px solid #2b2117;font:15px "IM Fell English",Georgia,serif !important;color:#e6d8bc !important;cursor:pointer;min-height:44px}
.modal select.pat-sel + label.pat-row{margin-top:12px !important}
.modal label.pat-row small{display:block;font:italic 12px Georgia,serif;color:#8f836c}
.modal input.pat-sw{-webkit-appearance:none;appearance:none;flex:none;width:44px !important;min-height:0 !important;height:26px;padding:0 !important;margin:0;border-radius:13px !important;
  background:#2a2118 !important;border:1px solid #5a4630 !important;position:relative;cursor:pointer;transition:background-color .15s}
.modal input.pat-sw::after{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#8f836c;transition:transform .15s}
.modal input.pat-sw:checked{background:#3a2a5c !important;border-color:#8a6fd0 !important}
.modal input.pat-sw:checked::after{transform:translateX(18px);background:#e6d6ff;box-shadow:0 0 6px rgba(195,60,255,.6)}
.modal input.pat-sw:focus-visible{outline:2px solid #b9a3f0;outline-offset:2px}
.pat-pitch{font:15px "IM Fell English",Georgia,serif;color:#e6d8bc;line-height:1.45;margin-bottom:12px}
.pat-pitch ul{margin:8px 0 0 18px;padding:0}.pat-pitch li{margin:3px 0}
.pat-dim{font:italic 12px Georgia,serif;color:#8f836c;margin-top:10px}
.pat-modal .btn[disabled]{opacity:.65;cursor:default}
@media (pointer:coarse){.modal select.pat-sel{font-size:16px !important}}  /* review: under 16px an iPhone zooms in */
@media (prefers-reduced-motion:reduce){.modal input.pat-sw,.modal input.pat-sw::after{transition:none}}
/* the Founders "coming soon" pitch: Settings chip, the once-per-person room card, the full page */
.fdr-soon{display:inline-block;margin-left:6px;padding:0 7px;border-radius:8px;font:italic 600 10px/15px Georgia,serif;color:#f5d48a;border:1px solid #8a6a2c;background:rgba(240,168,50,.12);vertical-align:1px;letter-spacing:0;text-transform:none}
.fdr-pin{position:relative;margin:4px 0 10px;border:1px solid rgba(201,162,74,.55);border-radius:12px;background:linear-gradient(180deg,#221a10,#140f09);padding:12px 44px 12px 14px;box-shadow:0 0 18px rgba(240,168,50,.12),inset 0 1px 0 rgba(255,230,180,.08)}
.fdr-pin h4{margin:0 0 4px;font:700 13px Cinzel,Georgia,serif;letter-spacing:1px;color:#f0d79a}
.fdr-pin p{margin:0 0 10px;font:14px "IM Fell English",Georgia,serif;color:#e6d8bc;line-height:1.4}
.fdr-pin .fdr-x{position:absolute;top:2px;right:2px;width:44px;height:44px;border:0;background:none;color:#a89a7f;font-size:20px;cursor:pointer;border-radius:50%}
.fdr-pin .fdr-x:focus-visible,.fdr-pin-go:focus-visible,.fdr-go:focus-visible,.fdr-back:focus-visible,.fdr-ccpick button:focus-visible{outline:2px solid #b9a3f0;outline-offset:2px}
.fdr-pin-go,.fdr-go{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 18px;border-radius:999px;font:700 12px Cinzel,Georgia,serif;letter-spacing:.6px;border:1px solid #d0463a;color:#fff0ea;background:linear-gradient(180deg,#6b221c,#2a0806);box-shadow:0 0 12px rgba(200,50,40,.35);cursor:pointer}
.fdr-go[disabled]{border-color:#5a8a5a;background:linear-gradient(180deg,#24401f,#0f1c0c);box-shadow:none;color:#d6f0d0;cursor:default}
.modal-overlay.fdr-ov{z-index:65;align-items:stretch !important;justify-content:center;padding:0 !important}
.fdr-pg{position:relative;display:flex;padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right);flex-direction:column;width:100%;max-width:760px;height:100%;background:linear-gradient(180deg,#140f0a,#0a0806);color:#e6d8bc;font:15px "IM Fell English",Georgia,serif;border-left:1px solid #33271b;border-right:1px solid #33271b}
@media (min-width:800px){.modal-overlay.fdr-ov{padding:24px 0 !important}.fdr-pg{height:calc(100% - 0px);border:1px solid #33271b;border-radius:14px;overflow:hidden}}
.fdr-top{flex:none;display:flex;align-items:center;gap:10px;padding:10px 12px calc(10px) ;padding-top:calc(10px + env(safe-area-inset-top));border-bottom:1px solid #2b2117}
.fdr-back{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:999px;border:1px solid #5a4630;color:#e0cfa8;background:transparent;font:22px Georgia,serif;cursor:pointer}
.fdr-ttl{font:700 15px Cinzel,Georgia,serif;letter-spacing:1px;color:#f0d79a}
.fdr-scroll{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding-bottom:12px}
.fdr-hero{padding:22px 18px 16px;text-align:center;border-bottom:1px solid #2b2117;background:radial-gradient(ellipse at 50% 0%,rgba(240,168,50,.16),transparent 70%)}
.fdr-big{width:34px;margin:0 auto 8px;filter:drop-shadow(0 0 10px rgba(240,168,50,.7))}
.fdr-big svg{display:block;width:100%;height:auto}.fdr-big .gl-s{fill:none;stroke:#cf9852;stroke-width:1.2}.fdr-big .gl-g{fill:#cf9852}.fdr-big .nl-glass{fill:rgba(240,168,50,.22)}
.fdr-hero h2{margin:0 0 6px;font:700 22px Cinzel,Georgia,serif;letter-spacing:1.2px;color:#edc99e;background:linear-gradient(180deg,#fff3d6,#edc99e 40%,#cf9852);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.fdr-hero p{margin:0 auto;max-width:320px;line-height:1.45}
.fdr-badge{display:inline-block;margin-top:12px;padding:3px 12px;border-radius:999px;font:600 11px Cinzel,Georgia,serif;letter-spacing:1.2px;color:#f5d48a;border:1px solid #8a6a2c;background:rgba(240,168,50,.1)}
.fdr-sec{padding:14px 16px 4px}
.fdr-sec h3,.fdr-free h3{margin:0 0 10px;font:700 12px Cinzel,Georgia,serif;letter-spacing:1.6px;color:#bfa670}
.fdr-f{display:flex;gap:12px;padding:10px 0;border-top:1px solid #241b12}
.fdr-cols > .fdr-f:first-child,.fdr-sec > .fdr-f:first-of-type{border-top:0}
.fdr-ic{flex:none;width:34px;height:34px;border-radius:10px;display:flex;align-items:center;justify-content:center;background:#0f0b07;border:1px solid #3d3024;font-size:17px}
.fdr-f > div:last-child{min-width:0;flex:1}
.fdr-f > div > b{display:block;font:700 13px Cinzel,Georgia,serif;letter-spacing:.6px;color:#f0d79a;margin-bottom:2px}
.fdr-f > div > span{display:block;line-height:1.4}
.fdr-ex{margin-top:6px;padding:6px 9px;border-radius:8px;background:#0a0705;border:1px solid #2b2117;font-size:14px;line-height:1.6}
.fdr-ex .t{color:#a89a7f;font-size:11px;margin-right:4px}
.fdr-ex b.who{font:400 12px Cinzel,Georgia,serif;color:var(--them);letter-spacing:.5px}
.fdr-cards{margin-top:8px}
.fdr-ccpick{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.fdr-ccpick button{min-height:36px;padding:0 11px;border-radius:999px;border:1px solid #3d3024;background:#0f0b07;color:#d8c9a8;font:600 10.5px Cinzel,Georgia,serif;letter-spacing:.6px;cursor:pointer}
.fdr-ccpick button[aria-selected="true"]{border-color:#cf9852;color:#f5dfa4;background:#2a1f10}
@media (pointer:coarse){.fdr-ccpick button{min-height:44px}}
.fdr-free{margin:10px 16px 0;padding:12px 14px;border-radius:12px;border:1px solid #2f4a2f;background:rgba(90,161,90,.07)}
.fdr-free h3{color:#9fcf9f}
.fdr-free ul{margin:0;padding-left:18px;line-height:1.5}
.fdr-promise{margin:14px 16px 0;font:italic 13px Georgia,serif;color:#a89a7f;line-height:1.45}
.fdr-cta{flex:none;display:flex;flex-direction:column;align-items:stretch;gap:6px;padding:10px 16px calc(12px + env(safe-area-inset-bottom));border-top:1px solid #2b2117;background:#0a0806}
.fdr-cta small{text-align:center;font:italic 12px Georgia,serif;color:#8f836c}
@media (min-width:800px){.fdr-cols{display:grid;grid-template-columns:1fr 1fr;gap:0 22px}.fdr-cols > .fdr-wide{grid-column:1 / -1}.fdr-wide .fdr-cc{max-width:420px}.fdr-cols > .fdr-f:nth-child(2){border-top:0}.fdr-cta{flex-direction:row;justify-content:center;align-items:center;gap:14px}}
html.fdr-open,html.fdr-open body{overflow:hidden}
/* <<< build 390 <<< */
/* >>> build 391: calling cards (designs: public/js/cards.js, each card in its own shadow root) >>> */
.cc-host{position:absolute;top:0;left:0;width:390px;height:150px;transform-origin:0 0}
.fdr-cc,.cc-frame,.pf-ccband{position:relative;overflow:hidden;width:100%;height:150px;border-radius:12px}
.pf-ccband{border-radius:0;background:#07050a}
.profile-panel .pf-band.cc-hid{display:none !important}
.profile-panel .pf-band.cc-hid + .pf-plate{margin-top:-36px !important}
.cc-count{margin-left:auto;font:600 12px Cinzel,Georgia,serif;letter-spacing:1px;color:#bfa670}
.cc-intro{margin:12px 16px 0;font:italic 14px Georgia,serif;color:#a89a7f}
.cc-grid{display:grid;gap:22px;padding:14px 16px 24px}
@media (min-width:800px){.cc-grid{grid-template-columns:1fr 1fr;gap:22px 18px}}
.cc-item{display:flex;flex-direction:column;gap:6px;min-width:0}
.cc-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cc-meta b{font:700 13px Cinzel,Georgia,serif;letter-spacing:.6px;color:#f0d79a}
.cc-r{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;padding:1px 7px;border-radius:8px;border:1px solid #3d3024;color:#c9c6be}
.cc-r.Rare{color:#8fb4ff;border-color:#3b4f7a}.cc-r.Legendary{color:#ffb547;border-color:#7a5a24}
.cc-f{font:700 10px Cinzel,Georgia,serif;letter-spacing:1px;padding:1px 7px;border-radius:8px;color:#2a1606;background:linear-gradient(180deg,#e8c47a,#a8742a)}
.cc-item.locked .cc-host{filter:grayscale(.65) brightness(.55)}
.cc-lock{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-size:26px;opacity:.9;pointer-events:none}
.cc-item.on .cc-frame{box-shadow:0 0 0 2px #cf9852,0 0 16px rgba(240,168,50,.35)}
.cc-how{font:14px "IM Fell English",Georgia,serif;color:#cdbf9f}
.cc-acts{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.cc-btn{min-height:40px;padding:0 16px;border-radius:999px;font:700 12px Cinzel,Georgia,serif;letter-spacing:.6px;cursor:pointer;border:1px solid #5a4630;color:#e0cfa8;background:transparent}
.cc-btn.cc-eq{border-color:#d0463a;color:#fff0ea;background:linear-gradient(180deg,#6b221c,#2a0806)}
.cc-btn[disabled]{opacity:.6;cursor:default}
@media (pointer:coarse){.cc-btn{min-height:44px}}
.cc-btn:focus-visible{outline:2px solid #b9a3f0;outline-offset:2px}
.cc-on{font:700 12px Cinzel,Georgia,serif;letter-spacing:.6px;color:#9fcf9f}
.cc-prog{display:flex;align-items:center;gap:10px;width:100%}
.cc-bar{flex:1;height:8px;border-radius:4px;background:#1d1610;border:1px solid #3d3024;overflow:hidden}
.cc-bar i{display:block;height:100%;background:linear-gradient(90deg,#8a5a1c,#e8c47a)}
.cc-prog span{flex:none;font:13px Georgia,serif;color:#bfae8a}
.cc-new .cc-new-card{margin:4px 0 10px;max-width:390px}
/* <<< build 391 <<< */

/* >>> build 392: friends in common >>> */
/* the page: a line under "Here since", same voice as the meta line, tappable */
.mf-line{display:flex;align-items:center;gap:8px;margin-top:6px;padding:4px 0;border:0;background:none;color:var(--pf-ink);font:13px "IM Fell English",Georgia,serif;cursor:pointer;text-align:left;max-width:100%;min-height:30px}
.mf-line b{color:var(--pf-gold-hi);font-weight:700;white-space:nowrap}
.mf-line .mf-txt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mf-line .mf-names{color:var(--pf-dim)}
.mf-line .mf-chev{color:var(--pf-gold);flex:none}
.mf-line:hover b,.mf-line:focus-visible b{text-decoration:underline}
.mf-stack{display:inline-flex;align-items:center;flex:none}
.mf-stack .mf-ava{width:22px;height:22px;font-size:10px;margin:0 0 0 -7px;border:1.5px solid var(--pf-gold);box-shadow:0 0 0 1.5px #0e0a07;border-radius:50%;object-fit:cover}
.mf-stack .mf-ava:first-child{margin-left:0}
.nmenu.mf-menu{max-height:min(60vh,420px);overflow-y:auto}
.nmenu .mf-item{display:flex;align-items:center;gap:8px;min-width:0}
.nmenu .mf-item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nmenu .mf-item .mf-ava{width:24px;height:24px;font-size:11px;flex:none;border-radius:50%;object-fit:cover}
.nmenu .mf-item.mf-dim{color:var(--ash);font-style:italic}
/* the request rows */
.frq-name .frq-mutual{display:block;font:12px/1.3 "IM Fell English",Georgia,serif;color:#cdb8e6;white-space:normal;margin-top:2px}
.frq-name .frq-mutual.none{color:var(--ash)}
/* the name card */
.nmenu .pc-line.pc-mutual{display:block;white-space:normal;overflow-wrap:anywhere;text-transform:none;letter-spacing:0;font:13px/1.3 "IM Fell English",Georgia,serif}
.nmenu .pc-line.pc-mutual b{color:var(--gold);font-weight:700}
.profile-panel .pf-meta+.mf-line{margin-top:6px}
/* <<< build 392 <<< */

/* >>> build 393 >>> paid Founders: the join / manage area and the "coming to Founders" list */
.fdr-go2{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 18px;border-radius:999px;font:700 12px Cinzel,Georgia,serif;letter-spacing:.6px;border:1px solid #8a6a2c;color:#f5d48a;background:rgba(240,168,50,.08);cursor:pointer}
.fdr-go2:focus-visible{outline:2px solid #b9a3f0;outline-offset:2px}
.fdr-go2[disabled],.fdr-go[disabled]#fdrJoin{opacity:.7;cursor:progress}
.fdr-cta .fdr-terms{font:12px/1.4 Georgia,serif;font-style:normal;color:#a89a7f;max-width:520px;margin:0 auto}
.fdr-status{margin:0 0 2px;text-align:center;font:13px/1.4 Georgia,serif;color:#f0d79a}
.fdr-status.late{color:#ffb4a8}
.fdr-later h3{color:#8f836c}
.fdr-later-note{margin:-4px 0 6px;font:italic 12px/1.4 Georgia,serif;color:#8f836c}
.fdr-later .fdr-f{opacity:.72}
.fdr-later .fdr-f > div > b{color:#cdbb8f}
@media (min-width:800px){.fdr-cta{flex-wrap:wrap}.fdr-cta .fdr-terms,.fdr-cta .fdr-status{flex-basis:100%}}
/* <<< build 393 <<< */
