/* The hub — page-specific styles.
 *
 * Everything shared with other pages has already been promoted to
 * components.css. What remains is the member card's inner layout and the
 * consultation panel, neither of which appears anywhere else yet.
 *
 * When listing.php lands it will want the .m-* rules too. Promote them then,
 * across both pages at once — not one page at a time, which is how two copies
 * of a component quietly diverge.
 */

/* --- The member card --------------------------------------------------- */

.member { margin-bottom: 26px; }

.m-off { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.m-off .txt { flex: 1; min-width: 250px; }
.m-off .h { font-family: var(--disp); font-weight: 700; font-size: 15px; margin-bottom: 3px; }
.m-off .d { font-size: 11px; color: var(--ink-dim); line-height: 1.55; }

.m-on { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.m-lab { font-size: 8.5px; text-transform: uppercase; letter-spacing: .13em; color: var(--ink-dim); }
.m-val { font-family: var(--disp); font-weight: 700; font-size: 20px; line-height: 1.15; }
.m-item.t .m-val { color: var(--line); }
.m-item.p .m-val { color: var(--ok); }
.m-item.s .m-val { color: var(--drill); }
.m-id { font-size: 10px; color: var(--ink-dim); line-height: 1.5; }
.m-id b { color: var(--ink); font-family: var(--disp); }

/* The candidate's name, where there is one. Bigger than the reference below
   it, because the panel is called Candidate and the name is the answer -- the
   reference used to be the answer only because nothing ever wrote a name. */
.m-name { font-size: 15px; letter-spacing: .01em; }
.m-ref { font-family: var(--mono); color: var(--line); }
.m-cta { margin-left: auto; }

/* --- The consultation panel -------------------------------------------- */

.cons { padding: 18px; }

.cons-top {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 12px; flex-wrap: wrap; gap: 10px;
}
.cons-topic { font-size: 9.5px; text-transform: uppercase; letter-spacing: .11em; color: var(--line); }

.navwrap { display: flex; align-items: center; gap: 9px; }
.navbtn {
  background: transparent; border: 1px solid var(--line-dim); border-radius: 4px;
  color: var(--line); font-size: 10px; width: 24px; height: 24px;
  cursor: pointer; line-height: 1; padding: 0;
  transition: border-color .15s, background .15s;
}
.navbtn:hover:not(:disabled) { border-color: var(--line); background: rgba(94, 200, 216, .12); }
.navbtn:disabled { opacity: .22; cursor: not-allowed; }

.streakmini { display: flex; align-items: center; gap: 8px; }
.streak-n { font-family: var(--disp); font-weight: 700; font-size: 17px; color: var(--drill); }
.streak-w { font-size: 9px; color: var(--ink-dim); text-transform: uppercase; letter-spacing: .09em; }

.week { display: flex; gap: 4px; }
.day {
  width: 17px; height: 17px; border-radius: 3px;
  background: var(--panel-2); border: 1px solid var(--line-dim);
  display: flex; align-items: center; justify-content: center;
  font-size: 7px; color: var(--ink-dim);
}
.day.hit { background: var(--drill); border-color: var(--drill); color: #2A1200; font-weight: 700; }
.day.today { box-shadow: 0 0 0 2px var(--line); }

.daylabel { font-size: 9.5px; text-transform: uppercase; letter-spacing: .11em; color: var(--ink-dim); margin-bottom: 7px; }
.daylabel.future { color: var(--bad); }

.q { font-size: 15px; line-height: 1.5; margin: 0 0 15px; }

.opts { display: grid; gap: 8px; }
.opt {
  border: 2px solid var(--line-dim); border-radius: 6px; padding: 11px 14px;
  cursor: pointer; background: transparent; color: var(--ink);
  font-family: var(--mono); font-size: 12.5px; text-align: left; line-height: 1.4;
  transition: border-color .15s, background .15s, transform .08s;
}
.opt:hover:not(:disabled) { border-color: var(--line); background: rgba(94, 200, 216, .07); }
.opt:active:not(:disabled) { transform: translateY(1px); }
.opt:disabled { cursor: default; }
.opt.chosen { border-color: var(--ok); background: rgba(111, 231, 179, .10); color: var(--ok); font-weight: 600; }
.opt.dim { opacity: .38; }

.results { margin-top: 12px; }
.pending { font-size: 10.5px; color: var(--ink-dim); font-style: italic; line-height: 1.6; }

/* Aggregate result bars. The original had no styles for these at all, because
   there was no backend and index_2.html:471 said so rather than inventing a
   distribution. */
.bar-row { margin-bottom: 7px; }
.bar-top { display: flex; justify-content: space-between; font-size: 11px; gap: 12px; margin-bottom: 3px; }
.bar-top .lbl { color: var(--ink-dim); }
.bar-top .pct { font-family: var(--disp); font-weight: 700; color: var(--ink); }
.bar-track { height: 6px; background: var(--panel-2); border-radius: 3px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--line); border-radius: 3px; }
.bar-row.mine .bar-fill { background: var(--ok); }
.bar-row.mine .pct { color: var(--ok); }
.bar-note { font-size: 10px; color: var(--ink-dim); margin-top: 9px; line-height: 1.6; }

.cons-foot {
  margin-top: 13px; padding-top: 11px; border-top: 1px dashed var(--line-dim);
  font-size: 10.5px; color: var(--ink-dim); line-height: 1.6;
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
.cons-foot a { color: var(--line); }

/* --- Section banners --------------------------------------------------------
 *
 * The hub's whole content below the consultation. Two of them, deliberately
 * large: they are the only navigation on the page now, so they should look like
 * a decision rather than like a footer link.
 *
 * See nav_banner() in rl-lib/layout.php for why the hub stopped listing the
 * individual trainers and games.
 * ------------------------------------------------------------------------- */
.banners { display: grid; gap: 14px; margin-top: 26px; }

.banner {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 18px;
  padding: 22px 20px;
  border: 1px solid var(--line-dim);
  border-radius: 4px;
  background: var(--panel);
  text-decoration: none;
  color: inherit;
  transition: border-color .15s, background .15s, transform .1s;
}
/* Hover is now the whole of what hovering a banner does -- the fold that used
   to open under it came off once there was a live teaser in that space. So it
   says a bit more than it did: the border and the corner brackets both come up
   to full strength, not just the border. */
.banner:hover, .banner:focus-visible {
  border-color: var(--line); background: var(--panel-2);
}
.banner:focus-visible { outline: 1px solid var(--drill); outline-offset: 2px; }
.banner:hover .p-bl, .banner:hover .p-br { border-color: var(--drill); }
.banner:hover .banner-n { color: var(--line); }
/* Nudged rather than scaled: a scale transform on a 1px border blurs it. */
.banner:hover .banner-go { transform: translateX(4px); }

.banner .p-bl, .banner .p-br {
  content: ""; position: absolute; width: 11px; height: 11px;
  border-color: var(--line); border-style: solid;
}
.banner .p-bl { top: -1px; left: -1px; border-width: 2px 0 0 2px; }
.banner .p-br { bottom: -1px; right: -1px; border-width: 0 2px 2px 0; }

.banner-n {
  font-family: var(--disp); font-weight: 700; font-size: 30px;
  color: var(--line-dim); line-height: 1; letter-spacing: .02em;
}
.banner-body { display: block; }
.banner-t {
  display: block; font-family: var(--disp); font-weight: 700; font-size: 20px;
  letter-spacing: .02em; margin-bottom: 4px;
}
.banner-d { display: block; font-size: 11.5px; color: var(--ink-dim); line-height: 1.7; }
.banner-note {
  display: block; margin-top: 7px; font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--line);
}
.banner-go {
  font-family: var(--disp); font-size: 20px; color: var(--line);
  transition: transform .15s;
}

@media (max-width: 560px) {
  .banner { grid-template-columns: auto 1fr; gap: 12px; padding: 18px 15px; }
  /* The arrow is decoration and the whole card is the target, so on a phone it
     gives up its column rather than squeezing the copy into two words a line. */
  .banner-go { display: none; }
  .banner-t { font-size: 17px; }
}

/* --- Follow row -------------------------------------------------------------
 * The two real social links plus the mailbox, on the hub rather than only in
 * the footer. The .lk styles are duplicated from contact.css on purpose for
 * now: promoting a component belongs in CSS Pass C, which is done across all
 * pages at once, and doing it here for one row is how two copies of .tile
 * quietly diverged last time.
 * ------------------------------------------------------------------------- */
.follow {
  display: flex; justify-content: space-between; align-items: center;
  gap: 18px; flex-wrap: wrap;
  margin-top: 20px; padding: 16px 18px;
  border: 1px solid var(--line-dim); border-radius: 4px;
  background: var(--panel);
}
.follow-txt b { display: block; font-family: var(--disp); font-size: 14px; margin-bottom: 3px; }
.follow-txt span { font-size: 11px; color: var(--ink-dim); line-height: 1.6; }

.follow .links { display: flex; gap: 8px; flex-wrap: wrap; margin: 0; }
.follow .lk {
  font-family: var(--disp); font-weight: 700; font-size: 11.5px;
  text-decoration: none; padding: 9px 15px; border-radius: 6px;
  border: 2px solid var(--line); color: var(--line);
  background: rgba(94, 200, 216, .08);
  transition: transform .1s, filter .15s;
}
.follow .lk:hover { transform: scale(1.02); filter: brightness(1.25); }
.follow .lk.ig { border-color: #C96FA8; color: #C96FA8; background: rgba(201, 111, 168, .08); }
.follow .lk.mb { border-color: var(--ink-dim); color: var(--ink-dim); background: transparent; }

@media (max-width: 560px) {
  .follow { flex-direction: column; align-items: stretch; }
  .follow .links { justify-content: stretch; }
  .follow .lk { flex: 1; text-align: center; }
}


/* ===========================================================================
 * THE HERO — the candidate and the thought bubble
 *
 * The page used to open with the daily consultation at full size, which put
 * the one thing that takes ten seconds and cannot be practised at the top of a
 * site about practising. This opens with the only thing on it that is yours.
 * ========================================================================= */
.hero {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 22px;
  align-items: start;
  margin-bottom: 20px;
}

.hero-figure { display: flex; flex-direction: column; align-items: center; gap: 10px; }

.hero-face {
  width: 132px; height: 132px;
  border-radius: 10px;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--line-dim);
  overflow: hidden;
  /* A slow idle sway. Enough to read as alive, small enough not to be a
     distraction on a page you are trying to read. */
  animation: hero-idle 6s ease-in-out infinite;
}
.hero-face svg { display: block; width: 100%; height: 100%; }

@keyframes hero-idle {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}
/* Anyone who has asked their system not to animate things means it. */
@media (prefers-reduced-motion: reduce) {
  .hero-face { animation: none; }
}

/* --- the bubble ----------------------------------------------------------- */
.hero-body { min-width: 0; }

.bubble {
  position: relative;
  border: 1px solid var(--line-dim);
  border-radius: 10px;
  background: var(--panel);
  padding: 15px 17px 13px;
  cursor: pointer;
}
/* The tail, pointing back at the figure. Two triangles — the outer one is the
   border, the inner one covers it a pixel in. */
.bubble::before, .bubble::after {
  content: "";
  position: absolute; top: 26px; right: 100%;
  border: 9px solid transparent;
}
.bubble::before { border-right-color: var(--line-dim); }
.bubble::after  { border-right-color: var(--panel); margin-right: -1px; }

.bubble.in .bubble-t, .bubble.in .bubble-cta { animation: bubble-in .32s ease both; }
@keyframes bubble-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bubble.in .bubble-t, .bubble.in .bubble-cta { animation: none; }
}

.bubble-t {
  margin: 0;
  font-family: var(--disp);
  font-size: 16px; line-height: 1.55; letter-spacing: .01em;
}
.bubble-cta {
  display: inline-block;
  margin-top: 10px;
  font-size: 11px; letter-spacing: .05em;
  color: var(--line); text-decoration: none;
  border-bottom: 1px solid var(--line-dim);
  padding-bottom: 2px;
}
.bubble-cta:hover { border-bottom-color: var(--line); }

/* Colour-coded by what the nudge is about, so a returning visitor can tell at
   a glance whether it is the poll nagging or the knowledge test. */
.bubble[data-kind="poll"]      { border-left: 3px solid var(--drill); }
.bubble[data-kind="knowledge"] { border-left: 3px solid var(--line); }
.bubble[data-kind="train"]     { border-left: 3px solid var(--ok); }
.bubble[data-kind="arcade"]    { border-left: 3px solid var(--warn); }
.bubble[data-kind="account"]   { border-left: 3px solid var(--crit); }

.bubble-dots { display: flex; gap: 5px; margin-top: 12px; }
.bubble-dots .dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--line-dim); transition: background .2s;
}
.bubble-dots .dot.on { background: var(--line); }

/* --- the stats strip ------------------------------------------------------ */
.hero-stats {
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  margin-top: 13px; padding-left: 2px;
  font-size: 11px; color: var(--ink-dim);
}
.hero-stats .hs b {
  font-family: var(--disp); font-size: 15px; color: var(--ink);
  margin-right: 4px; font-variant-numeric: tabular-nums;
}
.hero-stats .hs.link { color: var(--line); text-decoration: none; }
.hero-stats .hs.link:hover { text-decoration: underline; }

/* --- the badge shelf ------------------------------------------------------ */
.hero-shelf {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  justify-content: center;
  width: 100%;
  padding: 8px 9px;
  border: 1px solid var(--ok); border-radius: 7px;
  background: rgba(111, 231, 179, .07);
}
.shelf-lab {
  width: 100%; text-align: center;
  font-size: 8.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ok);
}
.shelf-item {
  display: block;
  background: var(--panel-2); border-radius: 4px; padding: 2px;
  animation: shelf-pop .4s cubic-bezier(.2, 1.5, .4, 1) both;
}
@keyframes shelf-pop {
  from { opacity: 0; transform: scale(.4) rotate(-12deg); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .shelf-item { animation: none; }
}
.shelf-item svg { display: block; }
.shelf-go { width: 100%; text-align: center; font-size: 10px; color: var(--ok); text-decoration: none; }
.shelf-go:hover { text-decoration: underline; }
.shelf-x {
  position: absolute;
  background: none; border: 0; color: var(--ink-dim);
  font-size: 10px; cursor: pointer; padding: 2px 4px;
  align-self: flex-start; margin-left: auto;
}
.hero-shelf { position: relative; }
.shelf-x { position: absolute; top: 3px; right: 4px; }
.shelf-x:hover { color: var(--ink); }

@media (max-width: 620px) {
  .hero { grid-template-columns: 1fr; gap: 14px; }
  .hero-figure { flex-direction: row; align-items: flex-start; }
  .hero-face { width: 84px; height: 84px; }
  /* The tail points sideways at a figure that is now above, so it goes. */
  .bubble::before, .bubble::after { display: none; }
  .bubble-t { font-size: 14px; }
}

/* ===========================================================================
 * THE TEASER — one of the 488, graded on the server
 * ========================================================================= */
.teaser {
  border: 1px solid var(--line-dim); border-radius: 4px;
  background: var(--panel);
  padding: 16px 18px 18px;
  margin-bottom: 20px;
}
.tz-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; margin-bottom: 10px;
}
.tz-lab { font-size: 9.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--line); }
.tz-verdict { font-size: 10px; letter-spacing: .1em; text-transform: uppercase; }
.tz-verdict.ok { color: var(--ok); }
.tz-verdict.no { color: var(--drill); }

.tz-q {
  font-family: var(--disp); font-size: 15px; line-height: 1.55;
  margin: 0 0 13px;
}

.tz-opts { display: grid; gap: 7px; }
.tz-opt {
  text-align: left;
  font-family: var(--mono); font-size: 12px; line-height: 1.5;
  padding: 10px 13px;
  border: 1px solid var(--line-dim); border-radius: 5px;
  background: var(--panel-2); color: var(--ink);
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.tz-opt:hover:not(:disabled) { border-color: var(--line); background: rgba(94, 200, 216, .09); }
.tz-opt:disabled { cursor: default; }
.tz-opt.right { border-color: var(--ok); background: rgba(111, 231, 179, .1); color: var(--ok); }
.tz-opt.wrong { border-color: var(--crit); background: rgba(232, 84, 74, .09); color: var(--crit); }

.tz-after { margin-top: 13px; padding-top: 12px; border-top: 1px dashed var(--line-dim); }
.tz-e { font-size: 12px; line-height: 1.8; color: var(--ink-dim); margin: 0 0 9px; }
.tz-t {
  font-size: 11.5px; line-height: 1.75; margin: 0 0 9px;
  padding-left: 10px; border-left: 2px solid var(--drill); color: var(--drill);
}
.tz-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.tz-cta {
  font-family: var(--disp); font-weight: 700; font-size: 12.5px;
  color: var(--line); text-decoration: none;
}
.tz-cta:hover { text-decoration: underline; }
.tz-src { font-size: 10px; color: var(--ink-dim); }

/* ===========================================================================
 * THE CONSULTATION, as a strip
 *
 * Same panel, less of the page. It is still the only daily habit here, which
 * is why it keeps a heading and the streak week — but it is one question, and
 * one question does not need to open the site.
 * ========================================================================= */
.cons-strip { margin-top: 22px; }

.cs-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 9px;
}
.cs-n { font-family: var(--disp); font-weight: 700; font-size: 13px; color: var(--drill); }
.cs-t { font-family: var(--disp); font-weight: 700; font-size: 17px; }
.cs-t a { color: inherit; text-decoration: none; }
.cs-t a:hover { color: var(--line); }
.cs-streak {
  margin-left: auto;
  display: flex; align-items: center; gap: 8px;
  font-size: 10.5px; color: var(--ink-dim);
}
.cs-streak b {
  font-family: var(--disp); font-size: 15px; color: var(--ok);
  font-variant-numeric: tabular-nums;
}

/* Redundant now, and kept as the record of how the general rule got written.
   The shelf is `hidden` until there is something on it, and `display:flex`
   above beat that -- the browser's own `[hidden]{display:none}` is the
   lowest-priority rule there is -- so an empty bordered box appeared under
   every avatar. It was fixed here, per element, with a note saying the next
   person to add a `display` to a hideable element would hit the same thing.
   The next person was me, twice, in this file: .bubble-cons and .bubble-cta.
   base.css now carries `[hidden]{display:none!important}` and this line does
   nothing. */
.hero-shelf[hidden] { display: none; }

/* ===========================================================================
 * The one thing to do
 *
 * The teaser used to hang off the Training banner and a game card off the
 * Arcade banner, each indented 26px with a rail down the left saying "I belong
 * to the thing above me". There is one box now and it belongs to nothing: it
 * sits between the avatar and the four sections, as its own object.
 *
 * So the rail and the indent are gone, and it gets a border instead -- it has
 * to look like a panel in its own right rather than an annexe of something.
 * ========================================================================= */
.teaser {
  position: relative;
  margin: 20px 0 24px;
  padding: 15px 17px 13px;
  border: 1px solid var(--line-dim);
  border-left: 2px solid var(--drill);
  border-radius: 4px;
  background: var(--panel);
}

@media (max-width: 560px) {
  .teaser { padding: 13px 13px 11px; }
}

/* --- the teaser slot ------------------------------------------------------ */
.tz-more {
  display: inline-block;
  margin-top: 12px;
  font-size: 10.5px; color: var(--ink-dim); text-decoration: none;
  letter-spacing: .03em;
}
.tz-more:hover { color: var(--line); text-decoration: underline; }

/* --- an abstract-reasoning item ------------------------------------------- */
.tz-seq {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  margin: 0 0 13px;
}
.tz-cell {
  width: 58px; height: 58px;
  background: var(--panel-2);
  border: 1px solid var(--line-dim); border-radius: 4px;
}
.tz-cell svg { display: block; width: 100%; height: 100%; }
.tz-cell.q {
  display: grid; place-items: center;
  border-style: dashed;
  font-family: var(--disp); font-size: 20px; color: var(--line-dim);
}

.tz-figs { display: flex; gap: 7px; flex-wrap: wrap; }
.tz-fig {
  width: 58px; height: 58px; padding: 0;
  background: var(--panel-2);
  border: 1px solid var(--line-dim); border-radius: 4px;
  cursor: pointer;
  transition: border-color .12s, background .12s, transform .1s;
}
.tz-fig:hover:not(:disabled) { border-color: var(--line); transform: translateY(-2px); }
.tz-fig:disabled { cursor: default; }
.tz-fig svg { display: block; width: 100%; height: 100%; }
.tz-fig.right { border-color: var(--ok); background: rgba(111, 231, 179, .12); }
.tz-fig.wrong { border-color: var(--crit); background: rgba(232, 84, 74, .1); }

/* --- the explainer fragment: a coalition, in miniature -------------------- */
.tz-coal { margin: 0 0 12px; }
.tz-groups { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 11px; }
.tz-grp {
  font-family: var(--mono); font-size: 10px;
  padding: 6px 10px; border-radius: 4px; cursor: pointer;
  background: var(--panel-2); color: var(--ink-dim);
  border: 1px solid var(--line-dim);
  transition: background .12s, color .12s, border-color .12s;
}
.tz-grp:hover { border-color: var(--line); }
.tz-grp.on { color: #06131f; font-weight: 600; }

.tz-bar {
  position: relative;
  height: 16px; border-radius: 3px;
  background: var(--panel-2);
  border: 1px solid var(--line-dim);
  overflow: hidden;
}
.tz-fill { height: 100%; width: 0; transition: width .25s ease; background: var(--line); }
.tz-fill.over { background: var(--ok); }
/* The majority line. 361 of 720 is just past halfway, and the whole point of
   the widget is watching the fill cross it. */
.tz-thr {
  position: absolute; top: -3px; bottom: -3px;
  left: 50.14%;
  width: 2px; background: var(--warn);
}
.tz-count {
  display: flex; justify-content: space-between;
  margin-top: 6px; font-size: 10px; color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}
.tz-count b { color: var(--ink); font-family: var(--disp); font-size: 13px; }
.tz-count b.over { color: var(--ok); }

/* --- the jargon teaser -----------------------------------------------------
 * The term is the question and the definition is the trap: it is written to
 * sound exactly as official as the real ones, so it gets the same weight as
 * the knowledge question's stem rather than being greyed out as a caption.
 * ------------------------------------------------------------------------- */
.tz-term {
  font-family: var(--disp); font-weight: 700; font-size: 17px;
  margin: 0 0 5px; letter-spacing: .01em;
}
.tz-def {
  font-size: 12px; line-height: 1.7; color: var(--ink-dim);
  margin: 0 0 11px; max-width: 62ch;
}

/* --- the framed game -------------------------------------------------------
 *
 * What is left of the arcade slot. It was a .gz card with its own label, title
 * and blurb hanging under the Arcade banner; the game is one of the five things
 * the single teaser box can contain now, so the card, its heading and its own
 * "Play →" all went -- the teaser already has a label and a link.
 *
 * The height is authored per game in nav.php and set inline, because it is
 * data about that game rather than a property of the slot, and hub.js corrects
 * it from a ResizeObserver on the framed document.
 * ------------------------------------------------------------------------- */
.gz-frame {
  position: relative;
  border: 1px solid var(--line-dim);
  border-radius: 2px;
  background: var(--dark);
  overflow: hidden;
}
.gz-frame iframe {
  display: block;
  width: 100%; height: 100%;
  border: 0;
  /* Not a scrolling document: it is a game sized to fit. If one overflows,
     that is a wrong number in nav.php, and embed.css clips it so the wrong
     number is visible rather than papered over with a scrollbar. */
}

/* ===========================================================================
 * The consultation, inside the bubble
 *
 * It was a titled section at the bottom of the page with its own streak
 * counter and nav strip — a lot of chrome around one decision, placed last, so
 * the site's only daily habit was the last thing you saw.
 *
 * It then spent a while inside the avatar's speech bubble, which fixed that
 * and gave the bubble two jobs. It is the first state of the single slot now:
 * question, then teaser. See the note in index.php, and the one in hub.js's
 * handOverBubble() for the three attempts the leaving animation took.
 * ========================================================================= */
/* The consultation, as the slot's first state.
 *
 * This was .bubble-cons, styled to sit inside the avatar's speech bubble. It
 * is a panel in the slot now and takes the same treatment as .teaser -- same
 * edges, same accent rail, same padding -- because they are two states of one
 * object and should look like one object. The rail is the consultation colour
 * rather than the drill colour, which is the only difference and the only one
 * worth having: it says this is the daily thing, not the practice thing.
 *
 * base.css's [hidden] rule is !important, so display:block here can no longer
 * defeat it -- which it did, for as long as the handover existed: the
 * attribute went on and 220px of answered question stayed on screen.
 */
.slot-cons {
  display: block;
  position: relative;
  margin: 20px 0 24px;
  padding: 15px 17px 13px;
  border: 1px solid var(--line-dim);
  border-left: 2px solid var(--line);
  border-radius: 4px;
  background: var(--panel);

  overflow: hidden;
  max-height: 1200px;
  opacity: 1;
  transition: opacity .45s ease, max-height .55s ease .1s, margin .55s ease .1s;
}

@media (max-width: 560px) {
  .slot-cons { padding: 13px 13px 11px; }
}
/* No max-height here on purpose. Both ends of the height transition are set
   inline by handOverBubble(), because the start value has to be measured and
   an inline declaration would beat a stylesheet one anyway -- so putting the
   target here meant it lost to the pinned start and never animated. */
/* No max-height here on purpose. Both ends of the height transition are set
   inline by handOverBubble(), because the start has to be measured and an
   inline declaration beats a stylesheet one anyway -- so putting the target
   here meant it lost to the pinned start and never animated. */
.slot-cons.leaving {
  opacity: 0;
  margin: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  /* Still leaves, just immediately. The point of the animation is to show
     WHERE the question went; somebody who has asked for less motion has still
     asked for the question to go. */
  .slot-cons { transition: none; }
}

.bc-lab {
  display: block;
  font-size: 9px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--drill);
}
.bc-q {
  margin: 6px 0 12px;
  font-family: var(--disp); font-size: 16px; line-height: 1.5;
}
.bc-opts { display: grid; gap: 6px; }
.bc-opt {
  text-align: left;
  font-family: var(--mono); font-size: 11.5px; line-height: 1.45;
  padding: 9px 12px;
  border: 1px solid var(--line-dim); border-radius: 5px;
  background: var(--panel-2); color: var(--ink);
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.bc-opt:hover:not(:disabled) { border-color: var(--line); background: rgba(94, 200, 216, .1); }
.bc-opt:disabled { cursor: default; }
.bc-opt.chosen { border-color: var(--ok); background: rgba(111, 231, 179, .12); color: var(--ok); }
.bc-opt.dim { opacity: .45; }

.bc-note { display: block; margin-top: 9px; font-size: 9.5px; color: var(--ink-dim); }

/* --- the archive, folded ---------------------------------------------------
 *
 * This was `.cons-after`: an open strip under the bubble carrying the streak,
 * the week, the arrows and the tally. It is a <details> now. Shut, it is one
 * line; open, it is what it always was.
 *
 * The summary carries the streak, so the number you actually want daily is
 * readable without opening anything, and the fold holds the part you go
 * looking for rather than the part you glance at.
 * ------------------------------------------------------------------------- */
.cons-arch { margin-top: 13px; padding-left: 2px; }

.cons-arch > summary {
  display: flex; align-items: center; gap: 10px;
  list-style: none; cursor: pointer;
  font-size: 10.5px; color: var(--ink-dim);
  padding: 5px 0;
}
.cons-arch > summary::-webkit-details-marker { display: none; }
.cons-arch > summary::before {
  content: "▸ "; color: var(--line); font-size: 9px;
}
.cons-arch[open] > summary::before { content: "▾ "; }
.cons-arch > summary:hover .ca-sum { color: var(--line); }
.cons-arch > summary:focus-visible { outline: 1px solid var(--drill); outline-offset: 2px; }

.ca-sum { letter-spacing: .02em; }

/* Pushed to the right end of the summary: it is the reading, not the label. */
.ca-streak { margin-left: auto; }

.ca-in { padding: 4px 0 2px; }

.ca-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 10.5px; color: var(--ink-dim);
}
.ca-streak b {
  font-family: var(--disp); font-size: 15px; color: var(--ok);
  margin-right: 3px; font-variant-numeric: tabular-nums;
}
.ca-nav { display: inline-flex; gap: 4px; }
.ca-day { color: var(--line); }
.ca-more { margin-left: auto; color: var(--line); text-decoration: none; }
.ca-more:hover { text-decoration: underline; }

/* The results bars, which used to sit inside the panel. */
.ca-in .results { margin-top: 10px; }
.ca-in .results:empty { margin-top: 0; }

/* --- the nameplate ---------------------------------------------------------
 *
 * Under the avatar on the hub. Set in the display face at a real size because
 * it is a nameplate, not a caption -- the whole point of the surname
 * capitalisation is that it looks like an institutional staff list, and 10px
 * grey would throw that away.
 *
 * Rendered by rl_name(); the capitals are in the string, not in CSS, so that
 * copying the name off the page gives you the name.
 * ------------------------------------------------------------------------- */
.hero-name {
  margin: 10px 0 0;
  font-family: var(--disp); font-weight: 700;
  font-size: 14px; line-height: 1.35;
  letter-spacing: .01em;
  text-align: center;
  max-width: 15ch;
  overflow-wrap: break-word;
}
a.hero-name.dim {
  font-family: var(--mono); font-weight: 400; font-size: 10.5px;
  color: var(--ink-dim); text-decoration: none;
  letter-spacing: .04em;
}
a.hero-name.dim:hover { color: var(--line); }

/* --- the mailbox door ------------------------------------------------------
 *
 * At the bottom of the map, where somebody who has read five banners and not
 * found what they wanted is looking.
 *
 * Deliberately NOT a sixth banner. It is not a section, it is a door, and
 * giving it a banner's weight would be a lie about what is behind it -- so it
 * gets no number, no corner brackets and a dashed edge, which reads as "there
 * is one more thing" rather than as another decision.
 * ------------------------------------------------------------------------- */
.postbox {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: start;
  gap: 15px;
  margin-top: 16px;
  padding: 15px 18px;
  border: 1px dashed var(--line-dim);
  border-radius: 4px;
  background: transparent;
  text-decoration: none;
  color: inherit;
  transition: border-color .15s, background .15s;
}
.postbox:hover {
  border-color: var(--line);
  border-style: solid;
  background: var(--panel);
}
.postbox:focus-visible { outline: 2px solid var(--drill); outline-offset: 2px; }

.pb-ic {
  font-size: 17px; color: var(--line); line-height: 1.4;
}
.pb-body { display: block; min-width: 0; }
.pb-t {
  display: block;
  font-family: var(--disp); font-weight: 700; font-size: 13.5px;
  line-height: 1.4; margin-bottom: 4px;
}
.pb-d {
  display: block; font-size: 11.5px; line-height: 1.7; color: var(--ink-dim);
  max-width: 74ch;
}
.pb-d b { color: var(--ink); }
.pb-go {
  font-family: var(--disp); font-size: 15px; color: var(--line);
  transition: transform .15s;
}
.postbox:hover .pb-go { transform: translateX(3px); }

@media (max-width: 560px) {
  .postbox { grid-template-columns: auto 1fr; padding: 13px 14px; }
  .pb-go { display: none; }
}

/* ===========================================================================
 * BEFORE YOU VOTE
 * ---------------------------------------------------------------------------
 * A consultation that asks a real question and offers three buttons is a poll,
 * not a consultation: somebody who does not already know what the current rule
 * IS cannot tell whether an option is the status quo or a change to it, and
 * half these questions turn on exactly that.
 *
 * Under the question rather than in a modal. It costs one line when shut, it
 * is on the same screen as the ballot so opening it does not take the question
 * away, and a modal on a phone covers the thing it is explaining.
 *
 * Closed by default, so the front page stays a front page.
 * ========================================================================= */
.bc-brief {
  margin: 0 0 14px;
  border-top: 1px dashed var(--line-dim);
  border-bottom: 1px dashed var(--line-dim);
}
.bc-brief > summary {
  list-style: none; cursor: pointer;
  padding: 9px 0 9px 17px; position: relative;
  font-size: 11px; line-height: 1.5; color: var(--ink-dim);
  transition: color .12s;
}
.bc-brief > summary::-webkit-details-marker { display: none; }
.bc-brief > summary:hover { color: var(--line); }
.bc-brief > summary::before {
  content: "▸"; position: absolute; left: 2px; top: 9px;
  font-size: 9px; color: var(--line);
  transition: transform .18s;
}
.bc-brief[open] > summary::before { transform: rotate(90deg); }
.bc-brief > summary:focus-visible { outline: 1px solid var(--drill); outline-offset: 2px; }

/* No ::details-content animation here. I tried one and it broke every
   disclosure on the site — see the note in components.css. A panel that snaps
   open is a small annoyance; a panel that does not open is a broken page. */
@media (prefers-reduced-motion: reduce) {
  .bc-brief > summary::before { transition: none; }
}
.bc-b-lab {
  font-size: 9px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--line); margin: 6px 0 5px;
}
.bc-b-t {
  font-size: 12px; line-height: 1.75; color: var(--ink-dim);
  margin: 0 0 12px; max-width: 74ch;
}
.bc-b-t:last-child { margin-bottom: 14px; }
