/* =======================================================================
   info.css — the INFO REGISTER: one stylesheet for the no-game pages

   tonight.html proved this register on 2026-08-19 (see its header for the
   owner's ruling it answers). This file is that page's inline skin, lifted
   out so the pages joining it — the venue directory, the venue calendars,
   the act pages, the front door — read as ONE surface instead of three
   accidental ones (tonight's charcoal, board.html's ice-on-black,
   metrics' Trebuchet were three unrelated skins before this).

   THE RULES THE REGISTER KEEPS, from tonight.html's own header:
   opened on a phone, on one bar of signal. No framework, no webfont, no
   canvas, no WebGL. The rows paint from the baked book on the first
   frame. css/hud.css is linked separately by each page ONLY so the two
   fixed stickers (the paper, the map) render as stickers; everything else
   on an info page is this file.

   ============================ RESKIN HERE ==============================
   The token block below is THE ONE PLACE the owner recolours the whole
   register. Two candidate sets were mocked side-by-side on 2026-08-20
   (the bake-off the owner asked for): the CHARCOAL/GOLD set tonight.html
   shipped with is live; the ICE set (the homepage brand's own values,
   css/style.css) is recorded beside it, commented, so the swap is one
   block either way. Nothing below the token block names a colour.
   ======================================================================= */

:root {
  /* ---- live set: BLACK AND YELLOW (the homepage brand, css/style.css) ----
     2026-09-15, the owner, with his logo on the page: "use that theme
     everywhere make it the default for all UI's". The values are the ICE
     set below run through scripts/theme-gold.mjs's map — the same map the
     music page wears — so this block is still a transcription of
     css/style.css and not a palette of its own. The paragraph that follows
     is the 2026-08-31 ruling it superseded, kept for the reason it gives.
     ---- live set, as it was: ICE (the homepage brand, css/style.css) ----
     The owner, 2026-08-31: *"stop using the gold and black color scheme it
     should all be the frost milano main music website theme"*. That is this
     block, and it is the swap the bake-off above was staged for — these
     eleven values were already written and waiting, so this is a
     transcription and not a recolour anybody invented. Every one of them is
     css/style.css's own: --bg is --ice-deep, --accent is --ice-bright,
     --ink is --ice-white, --dim is --ice-light. ---- */
  --bg:         #0a0a0a;                    /* the page  (--ice-deep)   */
  --panel:      #1e1e1e;                    /* raised cards            */
  --ink:        #fff8dc;                    /* body text (--ice-white) */
  --dim:        #ffe873;                    /* secondary (--ice-light) */
  --accent:     #ffd800;                    /* times, badges, buttons (--ice-bright) */
  --accent-ink: #0a0a0a;                    /* text ON the accent      */
  --line:       rgba(255,232,115, .16);   /* hairlines               */
  --live-1:     #302800;                    /* ON NOW card gradient, top */
  --live-2:     #161400;                    /*  … bottom                 */
  --live-edge:  rgba(255,216,0, .45);    /* ON NOW card border        */
  --live-line:  rgba(255,216,0, .16);    /* rules inside the card     */

  /* ---- alternate set: charcoal/gold (what tonight.html shipped with,
          live until 2026-08-31 and kept so the swap stays one block) ----
  --bg:         #101216;
  --panel:      #191c21;
  --ink:        #ece7d9;
  --dim:        #9aa0a6;
  --accent:     #e8b64c;
  --accent-ink: #14161a;
  --line:       rgba(236, 231, 217, .14);
  --live-1:     #2a2113;
  --live-2:     #1b1a16;
  --live-edge:  rgba(232, 182, 76, .45);
  --live-line:  rgba(232, 182, 76, .16);
  ------------------------------------------------------------------- */
}

* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--ink);
       font: 400 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
            "Helvetica Neue", Helvetica, Arial, sans-serif;
       -webkit-text-size-adjust: 100%; padding-bottom: 104px; }
a { color: inherit; }

/* ⚠ THE TWO STICKERS OWN THE LEFT GUTTER. css/hud.css pins the paper at
   top-left (12,12, 46x44) and the fast-travel map at bottom-left (12,
   50x53) on EVERY walked page in town, and they are position:fixed. On a
   room that is a canvas nobody notices; on a page that is a column of
   text they sit straight on top of the reading. Measured, not guessed —
   the numbers above came off getBoundingClientRect on a 430-wide phone.
   So the column keeps out of that gutter rather than the stickers moving,
   because they are the same in every room and this page is the visitor. */
.wrap { max-width: 680px; margin: 0 auto; padding: 0 16px; }
/* ⚠ THE GUTTER IS GONE ON A PHONE, 2026-09-15 — owner: "it should use the
   full width and everything needs to be centered", first of the front door
   and then "fix the other ones". Under 760px this rule was
   `.wrap { padding-left: 74px; }`, and photographed at 390px it cost every
   register page a fifth of its screen: a 300px column beside a 74px band
   that held nothing but the two stickers. The column now takes the width
   and the stickers sit ON it, the way they sit on every walked room. What
   keeps the corners honest without the band:
     - the PAPER (top-left, 12px in, 44–54px tall): the shell nav is the one
       row that shares its band, so on a phone the nav starts below it and
       is centred — see .ibar's phone block.
     - the PILL (top-right, js/frost-signup.js): it parks itself on the
       title row and publishes its width as --fsg-dock-w; the h1 already
       kept that out of its right edge, and a CENTRED title keeps it out of
       both edges or the centre is off by half a pill — see the 834px block.
     - the MAP (bottom-left): body's 104px bottom padding keeps it off the
       last line at the end of the scroll; mid-scroll it overlaps the left
       edge as it does in every bar.
   creator.html's .cr-fallback and its cornered dock still carry their own
   74px: that page is a full-screen stage, not this column. */

/* ---- the shell nav. IN-FLOW on purpose, never fixed: the profile dock
   (js/frost-signup.js) measures pinned chrome to place itself, and a
   reading page should spend its pixels on the reading — the row scrolls
   away like a masthead does. js/info-nav.js builds it as .wrap's first
   child; a page never writes this markup by hand. ---- */
.ibar { display: flex; gap: 16px; align-items: baseline; flex-wrap: wrap;
        padding: 16px 0 0; font-size: 12px; letter-spacing: .12em;
        text-transform: uppercase; }
.ibar a { color: var(--dim); text-decoration: none; padding: 4px 0; }
.ibar a:hover { color: var(--ink); }
.ibar .ibar__brand { font-weight: 700; color: var(--ink); letter-spacing: .08em; }
/* PHONE: centred, and below the paper. The paper sticker (js/frost-news.js)
   is fixed at top 12 / left 12 and stands 54px tall (44 under 560px), and
   with the gutter gone the nav row is the one thing that shares its band —
   a centred row of six items reaches x≈30 on a 390px screen, under the
   paper. So the row starts under the sticker instead: 68px clears the
   bigger paper, 60px the phone one, and the whole header is centred with
   it — the register is left-set as a reading page on a desktop and centred
   on a phone, where the column is the screen. */
@media (max-width: 760px) {
  .ibar { justify-content: center; padding-top: 68px; }
  header.top { text-align: center; }
  .vlinks { justify-content: center; }   /* venue.html's MAP ↗ row is flex, so text-align cannot centre it */
}
@media (max-width: 560px) {
  .ibar { padding-top: 60px; }
}
/* ================= WHERE YOU ARE, AND THE ONE WAY THE REGISTER SAYS IT
   Owner, 2026-09-08: *"nothing really makes it obvious what the screen is
   doing or what the user should press make important things eye catching"*.
   The rule that came out of it, in his own terms: the picked option is
   SOLID and unmistakable, never a hairline.

   This used to be a 2px underline, and the register wore three different
   answers to one question at once — tonight.html a solid fill (the one
   that was right), these six pages an underline, and the front door a box
   DARKER than the links beside it, so "you are here" read as "this one is
   switched off". The register is one surface or it is not a register.

   THE CONTRACT, and scripts/register-highlight-check.mjs holds every skin
   to it: the current page has a SOLID accent background and ink that sits
   on the accent. A border, an underline or a text colour is not enough on
   its own — that is the defect, not the fix. ---- */
.ibar .ibar__cur { color: var(--accent-ink); background: var(--accent);
                   font-weight: 700; padding: 4px 9px; border-radius: 5px;
                   letter-spacing: .12em; }

header.top { padding: 20px 0 14px; }
h1 { margin: 0; font-size: 30px; line-height: 1.1; letter-spacing: -.01em; }
.when { color: var(--dim); font-size: 13px; letter-spacing: .09em;
        text-transform: uppercase; margin-top: 6px; }

/* ---- the one thing a person actually opened this for ---- */
.live { margin: 18px 0 4px; padding: 14px 16px; border-radius: 10px;
        background: linear-gradient(180deg, var(--live-1), var(--live-2) 70%);
        border: 1px solid var(--live-edge); }
.live h2 { margin: 0 0 8px; font-size: 11px; letter-spacing: .14em;
           text-transform: uppercase; color: var(--accent); }
.live .row { display: flex; gap: 10px; align-items: baseline;
             padding: 5px 0; border-top: 1px solid var(--live-line); }
.live .row:first-of-type { border-top: 0; }
.live .rm { font-weight: 700; }
.live .ac { color: var(--dim); }
.live .none { color: var(--dim); font-size: 14px; }

.count { margin: 22px 0 10px; font-size: 12px; letter-spacing: .1em;
         text-transform: uppercase; color: var(--dim); }

.room { border-top: 1px solid var(--line); padding: 15px 0; }
.room:last-child { border-bottom: 1px solid var(--line); }
.rhead { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; }
.rname { font-size: 18px; font-weight: 700; margin: 0; flex: 1 1 auto; }
.onair { flex: 0 0 auto; font-size: 10px; font-weight: 700; letter-spacing: .1em;
         background: var(--accent); color: var(--accent-ink);
         padding: 3px 7px; border-radius: 4px; }
.bill { margin-top: 8px; }
.slot { display: flex; gap: 12px; padding: 3px 0; align-items: baseline; }
.t { flex: 0 0 84px; color: var(--accent); font-size: 12px; font-weight: 700;
     letter-spacing: .02em; padding-top: 2px; }
.a { flex: 1 1 auto; }
.note { color: var(--dim); font-size: 13px; }
.go { display: inline-block; margin-top: 10px; padding: 7px 13px; border-radius: 6px;
      background: var(--accent); color: var(--accent-ink); font-weight: 700;
      font-size: 12.5px; letter-spacing: .05em; text-decoration: none; }
.go:active { filter: brightness(.9); }


footer.src { margin: 30px 0 10px; padding-top: 14px; border-top: 1px solid var(--line);
             color: var(--dim); font-size: 12px; line-height: 1.6; }
footer.src a { color: var(--dim); }
.empty { padding: 34px 0; color: var(--dim); }

/* ---- the venue directory (venues.html) ---- */
.dsearch { width: 100%; margin: 4px 0 6px; padding: 10px 12px;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line);
  border-radius: 8px; font: inherit; font-size: 15px; }
.dsearch::placeholder { color: var(--dim); }
.dir { border-top: 1px solid var(--line); }
.dir__row { display: flex; gap: 10px; align-items: baseline; padding: 11px 2px;
  border-bottom: 1px solid var(--line); color: inherit; text-decoration: none; }
.dir__row:active { background: var(--panel); }
.dir__name { font-weight: 700; flex: 1 1 auto; }
.dir__st { color: var(--dim); font-size: 12.5px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 40%; }
.badge { flex: 0 0 auto; font-size: 10px; font-weight: 700; letter-spacing: .1em;
  padding: 3px 7px; border-radius: 4px; }
.badge--tonight { border: 1px solid var(--live-edge); color: var(--accent); }
.badge--on { background: var(--accent); color: var(--accent-ink); }

/* ---- generic section head, the .live h2 register outside the card ---- */
.shead { font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
         color: var(--accent); margin: 26px 0 8px; }

/* ---- the venue page's header links (instagram, map, the board) ---- */
.vlinks { margin-top: 8px; display: flex; gap: 14px; flex-wrap: wrap;
          font-size: 12.5px; }
.vlinks a { color: var(--dim); text-decoration: none;
            border-bottom: 1px solid var(--line); padding-bottom: 1px; }
.vlinks a:hover { color: var(--ink); }

/* ---- listening links under a bill: the act, offered as a record ---- */
.listen { margin-top: 6px; font-size: 12.5px; color: var(--dim); }
.listen a { color: var(--accent); text-decoration: none; }

/* ================= tonight.html's DECIDING ROW =================
   The controls under the count, and the chips the ranking earns. The
   NEAR ME button is the one control on the page a thumb has to hit
   standing on a kerb, so it alone gets the 44px floor — the register's
   .go stays its reading-page size everywhere else. Chips reuse .onair's
   grammar; only STARTS SOON is drawn quieter (a future is a smaller
   claim than a present), and the crown is text, not a card — the top
   row's position already says it. */
.ctrls { display: flex; gap: 10px; margin: 2px 0 12px; flex-wrap: wrap; }
.ctrls .go { margin-top: 0; min-height: 44px; padding: 12px 18px;
             font-size: 13px; border: 0; font-family: inherit; cursor: pointer; }
.ctrls .go[aria-pressed="true"] { outline: 2px solid var(--live-edge);
                                  outline-offset: 1px; }
.soon { flex: 0 0 auto; font-size: 10px; font-weight: 700; letter-spacing: .1em;
        border: 1px solid var(--live-edge); color: var(--accent);
        padding: 3px 7px; border-radius: 4px; }
.dist { flex: 0 0 auto; color: var(--dim); font-size: 12px; font-weight: 700;
        letter-spacing: .04em; }
.crown { margin: 18px 0 -6px; color: var(--accent); font-size: 12px;
         font-weight: 700; letter-spacing: .14em; text-transform: uppercase; }

/* ================= tonight.html's MAP VIEW =================
   Downtown drawn from the project's own street survey, with the night
   standing on it. The image is the only sizing authority - markers are
   positioned in PERCENT of it, so the same numbers hold at every width
   and nothing has to be recomputed on resize. Pins are 30px of tappable
   target around a small dot: a phone thumb needs the target, the map
   needs the dot, and those are not the same rectangle. */
.lmap { position: relative; margin: 2px 0 14px; border: 1px solid var(--line);
        border-radius: 6px; overflow: hidden; background: var(--ink); }
/* THE BAR IS OUTSIDE THE SCROLL BOX and the map is inside it, so the coverage
   line, the zoom and the credit stay put while the map moves under them.
   The box is CAPPED because the frame is ~25 x 32 km: uncapped it would be
   thousands of pixels tall and bury the list it exists to serve. It pans BOTH
   ways now — it only ever scrolled down, back when the map was one screen wide
   and 1600px tall; at CLOSER it is six screens across as well.
   overscroll-behavior keeps a pan inside the map instead of dragging the page
   with it. */
.lmap__scroll { max-height: min(62vh, 520px); overflow: auto;
                -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.lmap__frame { position: relative; width: 100%; }
.lmap__img { display: block; width: 100%; height: auto; }
.lmap__marks { position: absolute; inset: 0; }
.lmap__pin { position: absolute; width: 30px; height: 30px; margin: -15px 0 0 -15px;
             padding: 0; border: 0; background: none; cursor: pointer;
             font-size: 11px; line-height: 30px; text-align: center; color: transparent; }
.lmap__pin::before { content: ""; position: absolute; left: 50%; top: 50%;
                     width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px;
                     border-radius: 50%; background: var(--dim); }
.lmap__pin--tonight::before { background: var(--accent); }
.lmap__pin--on::before { background: var(--accent); width: 13px; height: 13px;
                         margin: -6.5px 0 0 -6.5px; box-shadow: 0 0 0 2px var(--ink); }
/* THE PULSE EXPANDS A RING; IT DOES NOT FADE THE DOT. Fading the marker
   itself was the first attempt and it inverts the whole point — LIVE is
   the strongest claim on the map, and for half of every 1.6s cycle it was
   the FAINTEST thing on it, caught at 35% over a dark survey. The dot now
   stays solid at full strength and a ring travels outward from under it,
   so the eye is pulled toward the marker instead of losing it. */
/* LIVE and ON NOW are the SAME AMBER on purpose — that is this page's own
   vocabulary (both render as .onair badges; the camera's is marked by a ●,
   not by a second hue), and inventing a colour for the map alone would
   make the map disagree with the list beside it. --live-edge was the first
   choice here and was wrong twice over: it is a 45%-alpha BORDER token, so
   as a fill it read muddy, and washed-out amber against solid amber is a
   weaker distinction than no distinction at all. What separates LIVE on a
   map is MOTION — one venue in fifty has it, and nothing else here moves. */
.lmap__pin--live::before { background: var(--accent); width: 13px; height: 13px;
                           margin: -6.5px 0 0 -6.5px; box-shadow: 0 0 0 2px var(--ink); }
.lmap__pin--live::after { content: ""; position: absolute; left: 50%; top: 50%;
                          width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px;
                          border-radius: 50%; border: 2px solid var(--accent);
                          animation: lmpulse 1.6s ease-out infinite; }
@keyframes lmpulse { from { transform: scale(1); opacity: .85; }
                     to   { transform: scale(2.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .lmap__pin--live::after { animation: none; opacity: .5; } }
/* the bar under the map: the zoom, the coverage line, the credit. ODbL wants
   the attribution wherever the map is drawn, so it is here and not in a
   comment. */
.lmap__bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             padding: 6px 8px; border-top: 1px solid var(--line); }
.lmap__cap { flex: 1 1 auto; font-size: 11.5px; color: var(--dim); }
.lmap__zoom { flex: 0 0 auto; min-height: 34px; padding: 6px 12px; border: 0;
              border-radius: 4px; background: var(--accent); color: var(--accent-ink);
              font: 700 10px/1 inherit; letter-spacing: .1em; cursor: pointer;
              font-family: inherit; }
.lmap__attr { flex: 0 0 auto; font-size: 10.5px; color: var(--dim);
              text-decoration: none; }
.lmap__attr:hover { text-decoration: underline; }
/* at FIT the whole city is one screen wide and the downtown rooms pile up, so
   the dot is smaller — a tight cluster reads as "the night is here", which is
   true, where fifty fat dots read as a smear. */
.lmap:not(.lmap--close) .lmap__pin::before { width: 7px; height: 7px;
                                             margin: -3.5px 0 0 -3.5px; }
.lmap:not(.lmap--close) .lmap__pin--on::before,
.lmap:not(.lmap--close) .lmap__pin--live::before { width: 10px; height: 10px;
                                                   margin: -5px 0 0 -5px; }
/* a marker tap that lands on a row says so, briefly */
.room.hit { outline: 2px solid var(--accent); outline-offset: 2px; }
.blinks { margin-top: 4px; font-size: 11.5px; }
.blinks a { color: var(--dim); margin-right: 10px; }

/* ================= the month, one room =================
   Three DIFFERENT empties, told apart on purpose (see js/gig-answer.js
   dayCell): a BOOKED day is lit; a day that was READ with nothing filed
   for this room is plain; a day NO day page was ever read for is dashed
   and faded — unknown, not closed. The legend under the grid says so in
   words, because a code nobody can read is a decoration. */
.vcal { margin: 6px 0 8px; }
.vcal__bar { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
.vcal__label { font-weight: 700; font-size: 15px; flex: 1 1 auto; }
.vcal__bar button { background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px; padding: 6px 12px;
  font: inherit; font-size: 13px; cursor: pointer; }
.vcal__bar button:disabled { opacity: .35; cursor: default; }
.vcal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.vcal__hd { text-align: center; color: var(--dim); font-size: 10px;
            letter-spacing: .08em; padding: 2px 0; }
.vcal__day { min-height: 46px; border: 1px solid var(--line); border-radius: 8px;
             padding: 4px 5px; font-size: 11px; position: relative; }
.vcal__day--pad { border: none; }
.vcal__day--unread { border-style: dashed; opacity: .5; }
.vcal__day--booked { background: var(--panel); border-color: var(--live-edge);
                     cursor: pointer; }
.vcal__day--today { outline: 2px solid var(--accent); outline-offset: 1px; }
.vcal__day--past.vcal__day--booked { opacity: .65; }
.vcal__num { color: var(--dim); font-weight: 700; font-size: 11px; }
.vcal__day--booked .vcal__num { color: var(--accent); }
.vcal__count { position: absolute; top: 4px; right: 5px; color: var(--accent);
               font-weight: 700; font-size: 10px; }
.vcal__hl { margin-top: 3px; color: var(--ink); line-height: 1.25;
            overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
            -webkit-box-orient: vertical; }
@media (max-width: 520px) { .vcal__hl { display: none; }
                            .vcal__day { min-height: 38px; } }
.vcal__legend { color: var(--dim); font-size: 11.5px; margin-top: 10px;
                line-height: 1.6; }
.vcal__cap { margin: 10px 0 0; font-size: 12px; letter-spacing: .1em;
             text-transform: uppercase; color: var(--dim); }

/* ================= the front door's four doors =================
   index.html only. A visitor arriving cold gets four tap targets and
   no more: the listings, the 3D world, the 2D world, the music. They
   are BIG because the page is opened on a phone in a bar, and they are
   stacked rather than a grid because four side-by-side cards at 390px
   are four cards nobody can read.

   .door--world is the only one that costs a download, so it is the only
   one drawn as a filled card - the difference is the warning, not a
   decoration. Its own copy says "it is a game and a real download" in
   words; this makes the words visible before they are read.

   .door--flat is the 2D world, added 2026-08-30, and it needs NOTHING
   here: an outlined card is already the register's way of saying "this
   one costs you nothing", which is exactly what it is. It gets a colour
   of its own only in css/front-door.css, where every door has one. */
.doors { display: block; margin: 22px 0 4px; }
.door { display: block; margin: 10px 0; padding: 15px 16px; border-radius: 10px;
        border: 1px solid var(--line); background: var(--panel);
        text-decoration: none; color: inherit; }
.door:active { filter: brightness(1.15); }
.door b { display: block; font-size: 17px; letter-spacing: .01em; }
/* > span, not a descendant selector: .door__net is a span INSIDE this one,
   and a bare `.door span` styled it too - it came out on its own line by
   cascade accident rather than by decision. It reads better there, so it
   says so below in its own rule. */
.door > span { display: block; margin-top: 5px; color: var(--dim);
               font-size: 13.5px; line-height: 1.45; }
.door--world { border-color: var(--live-edge);
               background: linear-gradient(180deg, var(--live-1), var(--live-2) 70%); }
.door--world b { color: var(--accent); }
.door__net { display: block; margin-top: 2px; color: var(--dim); }

/* the directory is a SECOND errand, not a sub-link of the first door -
   see index.html's note where this line is written */
.doors__more { margin: -2px 0 14px; padding-left: 2px;
               color: var(--dim); font-size: 13px; }
.doors__more a { color: var(--accent); text-decoration: none; }

/* ================= THE PROFILE DOCK, ON A READING PAGE =================
   Chrome this file does not own (css/signup.css, js/frost-signup.js), asked
   to behave differently here because the page underneath it is a different
   shape. Both rules are scoped to body[data-info-shell], which js/info-nav.js
   sets — the scoping is what lets them out-specify signup.css's own defaults
   whichever order the two stylesheets happen to land in.

   1  THE CORNER, NOT THE MIDDLE. signup.css centres the pill on a fine
      pointer and only corners it on touch or under 700px, and for a WORLD
      page that is right: the middle of the top edge is empty sky and the
      corners have the HUD in them. A register page is the opposite — the
      middle of the top edge is the headline, and the right gutter is empty.
      Measured at 1200px on venue.html, the centred pill sat straight across
      "Central Machine Works Brewery & Beer Hall".

   2  AND THEN KEEP THE HEADLINE OUT OF IT. Cornering is only half: at phone
      width the column reaches the corner, so a long enough name still runs
      underneath. js/frost-signup.js measures the pill and publishes the room
      it needs as --fsg-dock-w; this reserves exactly that, and only up to
      834px, because above that the 680px column has stopped reaching the
      corner and a reserved gutter would just be a hole in the design. ---- */
body[data-info-shell] .fsg-dock { justify-content: flex-end; }

@media (max-width: 834px) {
  body[data-info-shell] h1 { padding-right: var(--fsg-dock-w, 0px); }
}
/* and on a phone the title is centred (header.top above), so the pill's
   width comes off BOTH sides — reserved on the right only, a centred title
   sits half a pill left of the screen's centre. 2026-09-15. */
@media (max-width: 760px) {
  body[data-info-shell] h1 { padding-left: var(--fsg-dock-w, 0px); }
}

@media (max-width: 420px) {
  h1 { font-size: 25px; }
  .t { flex-basis: 72px; font-size: 11.5px; }
  .door { padding: 13px 14px; }
  .door b { font-size: 16px; }
}

/* ===================== the watching surface =====================
   js/stream-player.js's cards, on live.html and anywhere else that mounts
   one later. It lives HERE and not in a page <style> for the reason the
   whole file exists: one skin for the register, reskinned in the token
   block above and nowhere else (scripts/info-shell-check.mjs §6).

   The box is 16:9 and the video is letterboxed inside it rather than
   cropped — a stage is wide and a camera on a wall is not framed for us. */
.sp-room { display: block; }
.sp-mount { margin: 10px 0 0; }
.sp-box {
  position: relative;
  background: #000;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
}
.sp-box.sp-live { border-color: var(--accent); }
.sp-video, .sp-frame {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  background: #000;
  object-fit: contain;
}
.sp-cap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 9px 12px;
  background: var(--panel);
  border-top: 1px solid var(--line);
}
/* a box with nothing playing in it is a caption and not a black rectangle:
   a dead-looking player reads as a broken camera and blames the venue */
.sp-box:not(.sp-live) .sp-cap { border-top: 0; }
.sp-head {
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--dim);
}
.sp-live .sp-head { color: var(--accent); }
.sp-note { font-size: 13px; color: var(--dim); }
.sp-bill { margin: 8px 0 0; font-size: 14px; color: var(--ink); }
.sp-bill .onair, .sp-bill .soon { margin-right: 6px; }

/* a landscape phone is a real reading position for this page and the video
   must not push the room's name off the top of it */
@media (max-height: 520px) and (orientation: landscape) {
  .sp-video, .sp-frame { aspect-ratio: auto; height: 62vh; }
}

/* tonight.html's ● WATCH badge is the same plate as ON NOW beside it, but it
   is a LINK to live.html — the only tappable thing in that row, so it says
   so rather than relying on a visitor trying it. */
a.onair { text-decoration: underline; text-underline-offset: 2px; }

/* ===================== me.html — YOUR PROFILE =====================
   The player's page, js/me-page.js. Five sections in one column; the
   grammar is the register's own (.shead, .go, .when, footer.src) and this
   block only adds the shapes those do not have: the face beside the name,
   a night row, a shelf of tiles, the home card, a key/value row.

   THE STAMP ROW IS THE BOARD'S OWN CARD (js/frost-board.js stampHTML, the
   one renderer scripts/board-stamp-check.mjs holds), and that file paints
   through --fb-* variables with the board's ice as their fallback. Mapping
   those variables onto this register's tokens is how the card wears THIS
   skin without a second copy of its markup or its rules. */
/* THE HEADLINE SHARES ITS ROW WITH NOTHING. The register reserves the
   sign-up pill's width on every h1 under 834px (above), and the pill's
   measurement in js/frost-signup.js assumes the headline is the column's
   full width the way it is on tonight.html. The first cut of this page put
   the face beside the name in a flex row: the squeezed h1 overflowed the
   body, the fixed dock stretched with it, the published reservation grew
   to 383px and the name printed one letter per line. So the name stands
   alone, and the face goes beside the "signed in" line under it. */
.me-top h1 { overflow-wrap: anywhere; }
.me-who { display: flex; gap: 14px; align-items: flex-start; margin: 2px 0 10px; }
.me-who__text { flex: 1 1 auto; min-width: 0; }
.me-face { flex: 0 0 auto; width: 84px; height: 164px; border-radius: 10px;
           background: var(--panel); border: 1px solid var(--line); overflow: hidden; }
.me-face canvas { display: block; width: 100%; height: 100%; }
.me-line { color: var(--dim); font-size: 13.5px; line-height: 1.45; margin: 8px 0; }
.me-who__text .me-line { margin-top: 4px; }
.me-empty { color: var(--dim); font-size: 14px; line-height: 1.5; margin: 4px 0 2px; }
.me-who .go { margin-top: 4px; border: 0; font-family: inherit; cursor: pointer;
              min-height: 44px; padding: 12px 18px; font-size: 13px; }
/* the two buttons under the name: SIGN IN (a guest) and EDIT YOUR LOOK (everyone)
   sit side by side and wrap on a narrow phone; the look one is the quieter of
   the pair, the panel colour, because signing in is the register's first ask */
.me-who .go + .go, .me-who .go.me-look { margin-right: 8px; }
.me-who .go.me-look { background: var(--panel); color: var(--ink); border: 1px solid var(--line);
                      display: inline-flex; align-items: center; }
a.me-face { display: block; text-decoration: none; }
a.me-face:active { filter: brightness(1.15); }

/* a night: the bar, how many, when last, and its card if it has one */
.me-night { border-top: 1px solid var(--line); padding: 12px 0; }
.me-night:last-child { border-bottom: 1px solid var(--line); }
.me-night__head { display: flex; gap: 12px; align-items: baseline; }
.me-night__name { flex: 1 1 auto; min-width: 0; font-weight: 700; font-size: 17px;
                  color: inherit; text-decoration: none; overflow-wrap: anywhere; }
.me-night__n { flex: 0 0 auto; color: var(--accent); font-weight: 700; font-size: 12px;
               letter-spacing: .06em; text-transform: uppercase; }
.me-night__meta { color: var(--dim); font-size: 12.5px; margin-top: 2px; }
.me-night .fb-stamp { margin: 10px 0 0;
  --fb-gold: var(--accent); --fb-bright: var(--ink); --fb-faint: var(--dim);
  --fb-faint2: var(--dim); --fb-edge: var(--live-edge); --fb-stripe: var(--panel); }

/* the shelf: pictures, names small under them, WORN as a corner mark */
.me-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); gap: 10px; }
.me-tile { display: block; position: relative; padding: 8px 6px 6px; border-radius: 10px;
           background: var(--panel); border: 1px solid var(--line);
           text-decoration: none; color: inherit; text-align: center; }
.me-tile:active { filter: brightness(1.15); }
.me-tile.is-worn { border-color: var(--live-edge); }
.me-tile__cv, .me-blob, .me-px, .me-tile__img { display: block; width: 64px; height: 64px; margin: 0 auto; }
/* the plain swatch is the DEFAULT: a creature's tile overrides it inline
   with color(srgb-linear …), and a browser that cannot parse that drops
   the declaration and shows this — a swatch, never an empty hole */
.me-blob { border-radius: 50%; background: var(--line); }
.me-blob--plain { background: var(--line); }
.me-px { display: grid; gap: 0; image-rendering: pixelated; }
.me-px i { display: block; }
.me-tile__img { object-fit: contain; image-rendering: pixelated; }
.me-tile__name { display: block; margin-top: 6px; font-size: 11px; color: var(--dim);
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.me-tile__worn { position: absolute; top: 6px; right: 6px; font-style: normal; font-size: 9px;
                 font-weight: 700; letter-spacing: .1em; background: var(--accent);
                 color: var(--accent-ink); padding: 2px 5px; border-radius: 4px; }

/* the home card: the facts the room ledger holds (the picture that used to
   open it came off on 2026-09-15 — js/me-page.js homeHTML says why) */
.me-home__facts { margin-top: 0; font-size: 13.5px; line-height: 1.5; }
.me-home__facts div:first-child { font-weight: 700; letter-spacing: .04em; }

/* a key/value row, the stats card's grammar at reading size */
.me-kv { display: flex; gap: 12px; justify-content: space-between; align-items: baseline;
         padding: 8px 0; border-top: 1px solid var(--line); }
.me-kv:last-child { border-bottom: 1px solid var(--line); }
.me-kv span { flex: 0 0 auto; color: var(--dim); font-size: 11.5px; letter-spacing: .1em;
              text-transform: uppercase; }
.me-kv b { text-align: right; min-width: 0; overflow-wrap: anywhere; }
.me-kv b i { font-style: normal; font-weight: 400; color: var(--dim); font-size: 12px; }

@media (max-width: 420px) {
  .me-face { width: 72px; height: 140px; }
  .me-grid { grid-template-columns: repeat(3, 1fr); }
}

/* =======================================================================
   THE CHARACTER CREATOR (creator.html) — the studio's mirror on its own page

   js/ms3d-creator.js draws its own chrome (the arc, the panel, the portrait
   plate) as a viewport-fixed overlay, .cas, written for a page that is one
   canvas. Here the page is a register page with a masthead in flow, so the
   stage and the overlay both start where the masthead ends: --cr-top is
   measured by js/creator-page.js off the .ibar's own box and set on :root,
   and 64px is only the value before the first measurement lands. The
   colours are the token block's; the mirror's own plates keep their ink.
   ======================================================================= */
.cr-page { overflow: hidden; padding-bottom: 0; height: 100vh; }
.cr-stage { position: fixed; left: 0; right: 0; bottom: 0; top: var(--cr-top, 64px);
            background: var(--panel); overflow: hidden; touch-action: none; }
.cr-stage canvas { display: block; width: 100%; height: 100%; }
/* the one paragraph shown when the page cannot draw him — no WebGL, no three,
   a stage that never came up — in the register's own voice, never a spinner */
.cr-fallback { position: fixed; left: 0; right: 0; top: var(--cr-top, 64px);
               margin: 0; padding: 20px 16px 0 74px; color: var(--dim);
               font-size: 14px; line-height: 1.5; display: none; }
.cr-page[data-cr-state="off"] .cr-fallback { display: block; }
.cr-page[data-cr-state="off"] .cr-stage { display: none; }
/* the mirror's overlay sits under the masthead here, not over it */
.cr-page .cas { top: var(--cr-top, 64px); }
/* ⚠ TWO THINGS THE FIRST PHONE FRAMES SHOWED, both at the size he sees them:
   1  the sign-up pill. The register corners it (flex-end, under the
      masthead) because a reading page's right gutter is empty; here the
      right gutter IS the mirror's panel, and the pill sat on the EXTRAS
      button in both orientations. Sent to the LEFT, clear of the paper
      sticker's 74px gutter, where the overlay draws nothing on a phone
      and the arc's top button starts lower on a desk.
   2  the YOU plate. The mirror parks it at bottom:84px for a room whose
      bottom-left is bare; on a register page the MAP sticker stands there
      and the plate sat on it in portrait. Lifted above the sticker —
      measured, the sticker's top stands 80px up on a 375px-tall phone, so
      the landscape value is 86 and not the mirror's own 52.
   ⚠ THE PILL'S SELECTOR CARRIES THE SHELL ATTRIBUTE ON PURPOSE. The
      register's own rule is `body[data-info-shell] .fsg-dock` (0,2,1) and a
      plain `.cr-page .fsg-dock` (0,2,0) loses to it — measured on the page:
      the padding landed and the pill stayed cornered on EXTRAS. */
body.cr-page[data-info-shell] .fsg-dock { justify-content: flex-start; padding-left: 74px; }
.cr-page .cas__you { bottom: 132px; }
@media (max-height: 450px) { .cr-page .cas__you { bottom: 86px; } }
