/* Deliberate single visual world: a warm parchment exchange ledger for York.
     Colors are painted explicitly throughout, so this page does not adapt
     to light/dark — it commits to one paper-and-ink identity. */
  html, body { background:#E7E1D2; margin:0; }
  .ukpx-root { --paper:#E7E1D2; --paper-dark:#DCD5C2; --ink:#1B2420; --forest:#1F4B3F; --forest-dark:#163429;
    --navy:#23395D; --brick:#A23E27; --gain:#2F6B45; --loss:#B0342A; --gold:#B08C1E; --silver:#6F7A85; --line:#C6BC9F;
    /* The tactical record's own ground — a cold slate that nothing else in
       the game uses, so a list of people moving against you cannot be
       mistaken for part of the market. */
    --war-paper:#E3E4DE; --war-line:#BCBEB3;
    /* --muted WAS NEVER DECLARED, and forty-six rules asked for it. Every
       one of them — rarity marks, ability lines, the segmented buttons, the
       ghost button, card tags — resolved to nothing and inherited whatever
       colour happened to be above it, which is why secondary text has been
       reading at full strength in places it was meant to sit back.

       IT IS NOT THE COLOUR THE CLASS USED. `.muted` has always been #8b8471,
       which is 2.86:1 against this paper and 2.5:1 against the darker panel
       — below AA for small text, and it is small text everywhere it appears.
       Declaring the token at that value would have spread a contrast failure
       across forty-six more rules. #615c4f is the same warm grey walked down
       until it clears 4.5:1 on BOTH parchments (5.11 and 4.55), and the
       class now reads the token so the two cannot drift apart again. */
    --muted:#615c4f;
    --mono:'IBM Plex Mono', ui-monospace, monospace;
    font-family:'IBM Plex Sans', sans-serif; background:var(--paper); color:var(--ink); min-height:100%; width:100%; }
  .ukpx-root * { box-sizing:border-box; }
  .center-screen { display:flex; align-items:center; justify-content:center; min-height:420px; flex-direction:column; padding:24px; }
  .join-card { background:var(--paper-dark); border:1px solid var(--line); padding:32px 36px; max-width:420px; width:100%; }
  .join-card h1 { font-family:'Fraunces', serif; font-weight:700; font-size:28px; margin:0 0 6px; text-wrap:balance; }
  .join-card p { margin:0 0 14px; color:#4b463a; font-size:14px; line-height:1.5; }
  .join-card input, .join-card select { width:100%; padding:10px 12px; font-size:15px; border:1px solid var(--line); background:var(--paper); font-family:inherit; margin-bottom:10px; }
  .founding-note { font-size:11.5px; color:#6b6455; border-left:3px solid var(--gold); padding-left:10px; margin:14px 0 18px; line-height:1.5; }
  .live-note { font-size:11px; color:#5a7a6a; margin:0 0 14px; line-height:1.5; }
  .mode-toggle { display:flex; margin-bottom:14px; border:1px solid var(--line); }
  .mode-btn { flex:1; padding:8px; background:var(--paper); border:none; cursor:pointer; font-size:12.5px; color:#6b6455; font-family:inherit; }
  .mode-btn.active { background:var(--forest); color:#fff; }
  .btn { cursor:pointer; border:1px solid var(--ink); background:var(--forest); color:#fff; padding:9px 16px; font-family:inherit; font-size:13.5px; font-weight:500; }
  .btn:hover:not(:disabled) { background:var(--forest-dark); }
  .btn:disabled { opacity:0.4; cursor:not-allowed; }
  .btn.secondary { background:transparent; color:var(--ink); }
  .btn.secondary:hover:not(:disabled) { background:var(--paper); }
  .btn.small { padding:5px 10px; font-size:12px; }
  .btn:focus-visible { outline:2px solid var(--gold); outline-offset:2px; }
  .error-text { color:var(--loss); font-size:13px; margin:-4px 0 10px; }

  /* A CITY'S COLOURS.
     Every city gets its own pair — the header band and the ticker beneath
     it — so that a player with two of them open knows at a glance which
     market they are looking at. York is the green and the blue the game was
     built in, stated here explicitly rather than left as the default, so
     that adding Newcastle is one block rather than an audit of every rule
     that happens to mention --forest. */
  .ukpx-root.city-york { --forest:#1F4B3F; --forest-dark:#163429; --navy:#23395D; }

  .topbar { background:var(--forest); color:#f2efe4; padding:16px 20px; display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px 16px; }
  .topbar h1 { font-family:'Fraunces', serif; font-weight:700; font-size:22px; margin:0; letter-spacing:.005em; }
  .brand-city { font-weight:400; font-size:17px; color:#b9cdbe; }
  .brand-city::before { content:"·"; margin:0 7px; color:#7d9a86; }
  .topbar .sub { font-size:12.5px; color:#c9d6cb; }
  .topbar-right { display:flex; align-items:center; gap:16px; flex-wrap:wrap; justify-content:flex-end; }

  /* The wall clock, in the city's own time. An hour here is an hour there,
     so this is game state rather than decoration. */
  .city-clock { display:flex; align-items:baseline; gap:7px; font-family:'IBM Plex Mono', monospace;
    padding:4px 10px; border:1px solid rgba(242,239,228,.22); border-radius:2px; }
  .clock-day { font-size:11px; color:#a8c0af; }
  .clock-time { font-size:15px; font-weight:600; color:#f2efe4; font-variant-numeric:tabular-nums; }
  .clock-zone { font-size:10px; letter-spacing:.1em; color:#e9c95a; }
  @media (max-width: 620px) {
    .topbar-right { width:100%; justify-content:space-between; }
    .clock-day { display:none; }
  }
  .ticker-wrap { background:var(--navy); color:#e9c95a; overflow:hidden; white-space:nowrap; border-bottom:1px solid var(--ink); }
  .ticker-track { display:inline-block; padding-left:100%; animation:tk 48s linear infinite; font-family:'IBM Plex Mono', monospace; font-size:12.5px; padding-top:7px; padding-bottom:7px; }
  @keyframes tk { 0% { transform:translateX(0); } 100% { transform:translateX(-100%); } }
  @media (prefers-reduced-motion: reduce) { .ticker-track { animation:none; } }
  .ticker-item { margin-right:48px; }

  /* FROZEN TO THE TOP — 21 Sep 2026.

     The market is a long list, and the one thing you need while reading it
     is what you can afford. That was scrolling off the top of the page, so
     every purchase decision meant scrolling back up to check the cash and
     then back down to find the building again.

     z-index 20 puts it above the content and well under everything modal —
     overlays sit at 80, backdrops at 100, the buy confirmation at 140 —
     so a sticky bar can never cover a dialog. The background is opaque
     because the content scrolls underneath it. */
  .playerbar { position:sticky; top:0; z-index:20;
    display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:10px; padding:12px 20px;
    background:var(--paper-dark); border-bottom:1px solid var(--line); font-family:'IBM Plex Mono', monospace; font-size:13px; }
  /* ---- THE WAR HISTORY ----
     A ledger, not a feed: fixed columns so a week of nights can be scanned
     down rather than read across. Incoming rows carry a brick edge and the
     full ink; your own sit back at 62% so the eye finds what was done TO
     you first, which is the whole reason the panel exists. */
  /* THE DISPATCH LINE. Set as a footnote under the column, in the paper's
     own italic, with a rule above it — the visual grammar has to say "this
     is not another sighting", because a reader deducing from the column
     must not fold a city-wide count into somebody's night. */
  /* ---- THE LANDING PAGE ----
     One column on a phone, pitch-beside-form from 900px. The form keeps its
     own card styling untouched; everything here is the argument around it. */
  .land { max-width:74rem; margin:0 auto; padding:0 20px 56px; }
  .land-top { display:flex; align-items:baseline; flex-wrap:wrap; gap:8px 16px; padding:28px 0 22px; }
  .land-top h1 { font:700 30px 'Fraunces', serif; margin:0; }
  /* .brand-city is written for the dark topbar — #b9cdbe on parchment is
     about 1.7:1 and reads as a smudge. On paper it takes the ink. */
  .land-top .brand-city { color:var(--muted, #6b6455); }
  .land-flag { font:10.5px 'IBM Plex Mono', monospace; letter-spacing:.11em; text-transform:uppercase;
    color:#f2efe4; background:var(--forest); padding:4px 9px; }
  .land-grid { display:grid; gap:30px; align-items:start; }
  .land-pitch { max-width:36rem; }
  .land-lede { font:400 19px/1.55 'Fraunces', serif; margin:0 0 22px; text-wrap:pretty; }
  .land-points { list-style:none; margin:0 0 22px; padding:0; display:grid; gap:16px; }
  .land-points li { border-left:3px solid var(--gold); padding-left:14px; }
  .land-points b { display:block; font:600 15px 'Fraunces', serif; margin-bottom:3px; }
  .land-points li { font-size:13.5px; line-height:1.6; color:var(--ink); }
  .land-foot { font-size:13px; line-height:1.6; color:var(--muted, #6b6455); margin:0; }
  .land-join .auth-card { margin:0; }
  .auth-h { font:700 19px 'Fraunces', serif; margin:0 0 4px; }

  .land-road-wrap { margin-top:46px; padding-top:26px; border-top:2px solid var(--line); }
  /* It ran straight into the last roadmap item with nothing between them. */
  .land-bottom { margin-top:44px; padding-top:18px; border-top:1px solid var(--line);
    font:12px 'IBM Plex Mono', monospace; letter-spacing:.04em;
    color:var(--muted, #6b6455); }
  .land-road-wrap h3 { font:700 21px 'Fraunces', serif; margin:0 0 4px; }
  .land-road-lede { font-size:13px; line-height:1.6; color:var(--muted, #6b6455); margin:0 0 20px; max-width:44rem; }

  /* Three columns of state. The dot carries the status so the columns do
     not need three different type treatments to be told apart. */
  .road { display:grid; gap:24px; }
  .road-col h4 { display:flex; align-items:center; gap:8px; margin:0 0 10px;
    font:10.5px 'IBM Plex Mono', monospace; letter-spacing:.12em; text-transform:uppercase;
    color:var(--muted, #6b6455); }
  .road-dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; background:var(--line); }
  .road-live .road-dot { background:var(--gain); }
  .road-building .road-dot { background:var(--gold); }
  .road-next .road-dot { background:#b3a988; }
  .road-col ul { list-style:none; margin:0; padding:0; display:grid; gap:13px; }
  .road-col li { border-top:1px solid rgba(198,188,159,.6); padding-top:9px; }
  .road-col b { display:block; font:600 13.5px 'Fraunces', serif; margin-bottom:2px; }
  .road-col span { display:block; font-size:12px; line-height:1.55; color:var(--muted, #6b6455); }
  .road.is-compact .road-col span { font-size:11.5px; }

  @media (min-width: 900px) {
    .land-grid { grid-template-columns:1fr 24rem; gap:46px; }
    .road { grid-template-columns:repeat(3, 1fr); gap:32px; }
    .road.is-compact { grid-template-columns:1fr; gap:20px; }
  }

  .gaz-dispatch { margin:7px 0 0; padding-top:6px; border-top:1px solid rgba(90,74,45,.28);
    font-style:italic; font-size:12px; line-height:1.55; opacity:.82; }
  .gaz-quiet { font-style:italic; opacity:.6; }

/* ---- THE TACTICAL RECORD, ON ITS OWN GROUND -------------------------
   This lived inside the market stall and wore the market's colours, so a
   list of people moving against you read as part of the shopping. It now
   has a surface of its own: cold slate, the one neutral nothing else in
   the game uses, with the two directions coloured at the edge rather than
   the middle. Yours forest, theirs brick.
   -------------------------------------------------------------------- */
.war-recent, .war-archive {
  margin:22px 0 0; padding:16px 18px 18px;
  background:var(--war-paper, #E4E4DD); border:1px solid var(--war-line, #BEBFB4);
  border-top:3px solid var(--navy);
}
.war-archive { margin-top:14px; background:none; border-top-width:1px; }
.war-archive-head { margin-bottom:10px; }
.war-archive-head h3 { font:600 17px/1.2 'Fraunces', serif; margin:0 0 2px; color:var(--ink); }
.war-archive-head p { margin:0; font-size:12.5px; line-height:1.5; color:var(--muted); max-width:62ch; }
.war-line { display:flex; align-items:flex-start; gap:10px; }
.war-line > .war-row { flex:1 1 auto; }
.war-watch { flex:0 0 auto; align-self:center; }
.war-sealed { margin-bottom:8px; padding-bottom:8px; border-bottom:1px dashed var(--line); }
.war-row.is-sealed { opacity:.9; border-left-color:var(--gold); }
.war-row.is-sealed .war-what { color:var(--muted); font-style:italic; }
.war-empty { margin:6px 0 0; font-size:12.5px; color:var(--muted); }

/* Each evening is a line until you open it. Seven nights of open lists is
   more history than anyone reads. */
.war-night { border-top:1px solid var(--line); }
.war-night > summary { cursor:pointer; list-style:none; padding:9px 0; }
.war-night > summary::-webkit-details-marker { display:none; }
.war-night > summary::before { content:"▸"; display:inline-block; width:14px;
  color:var(--muted); font-size:10px; transition:transform .15s ease; }
.war-night[open] > summary::before { transform:rotate(90deg); }
.war-night > summary:hover b { text-decoration:underline; }
.war-night-body { padding:0 0 10px 14px; }

  /* superseded by the .war-night details rule above */
  .war-head { display:flex; align-items:baseline; gap:12px;
    padding:0 0 5px; border-bottom:1px solid var(--line); }
  .war-head > span:last-child { margin-left:auto; }
  /* Quiet until wanted. A share button that shouts sits on the page asking
     to be pressed by somebody who has nothing to share yet. */
  .war-share { border:none; background:none; padding:0; cursor:pointer; font:inherit;
    font-size:10.5px; letter-spacing:.06em; text-transform:uppercase;
    font-family:'IBM Plex Mono', monospace; color:var(--muted, #6b6455); opacity:.6; }
  .war-share:hover { opacity:1; color:var(--forest); text-decoration:underline; }
  .war-share:focus-visible { outline:2px solid var(--gold); outline-offset:2px; opacity:1; }
  .war-head b { font:600 13.5px 'Fraunces', serif; }
  .war-head span { font:10px 'IBM Plex Mono', monospace; letter-spacing:.09em;
    text-transform:uppercase; color:var(--muted, #6b6455); }
  .war-list { list-style:none; margin:0; padding:0; }
  .war-row { display:grid; gap:2px 12px; align-items:baseline; padding:7px 0 7px 11px;
    border-bottom:1px solid rgba(198,188,159,.45); border-left:3px solid transparent;
    grid-template-columns:8.5rem 1fr 1fr auto; font-size:12.5px; }
  .war-row.is-theirs { border-left-color:var(--brick); }
  .war-row.is-mine { opacity:.62; }
  .war-dir { font:600 9.5px 'IBM Plex Mono', monospace; letter-spacing:.1em;
    color:var(--muted, #6b6455); }
  .war-row.is-theirs .war-dir { color:var(--brick); }
  .war-card { font-weight:600; }
  .war-where { color:var(--muted, #6b6455); }
  .war-what { font-family:'IBM Plex Mono', monospace; font-size:11.5px; }
  .war-row.is-stopped .war-what { color:var(--gain); }
  .war-row:not(.is-stopped).is-theirs .war-what { color:var(--loss); }
  .war-who { grid-column:2 / -1; font-size:11px; color:var(--muted, #6b6455); }
  .war-who em { font-style:italic; }
  .war-spent { grid-column:2 / -1; font:11px 'IBM Plex Mono', monospace;
    color:var(--muted, #6b6455); }

  /* One column at phone width: four fixed tracks in 390px is four words a
     line and nothing legible. */
  @media (max-width: 640px) {
    .war-row { grid-template-columns:1fr; gap:1px; padding-left:9px; }
    .war-dir { font-size:9px; }
    .war-who, .war-spent { grid-column:1; }
  }

  .order-shelter { display:block; margin-top:6px; font-style:normal; font-size:11px; line-height:1.5;
    color:var(--muted, #6b6455); max-width:34rem; }
  .stat-label { color:#6b6455; font-size:10.5px; text-transform:uppercase; letter-spacing:0.06em; display:block; }

  /* A STICKY BAR HAS TO EARN ITS HEIGHT, AND ON A PHONE IT DID NOT.

     Measured at six widths: the bar is one 57px row down to 820px, two rows
     (98px) below that, and three rows (139px) at 390px. Freezing 139px to
     the top of a phone screen spends about a fifth of it permanently, to
     show figures most of which are not what you came for.

     So below 820px it becomes one row that scrolls sideways. The order in
     the markup is already the order of usefulness — who you are, cash,
     portfolio — so the two that matter while shopping are the two you can
     see without moving anything. */
  @media (max-width: 819px) {
    .playerbar { flex-wrap:nowrap; overflow-x:auto; justify-content:flex-start; gap:20px;
      scrollbar-width:none; -ms-overflow-style:none; }
    .playerbar::-webkit-scrollbar { display:none; }
    .playerbar > * { flex:0 0 auto; }
  }

  /* A figure you can open. It has to sit in the player bar as if it were
     one of the other tiles — same type, same spacing — and only admit to
     being a button when the cursor is on it, or the bar reads as a row of
     controls rather than a row of numbers. */
  .stat-button { padding:0; border:0; background:none; font:inherit; text-align:left; cursor:pointer;
    border-bottom:1px dotted transparent; }
  .stat-button:hover { border-bottom-color:#8e8674; }
  .stat-value { font-size:16px; font-weight:600; font-variant-numeric:tabular-nums; }
  .switch-link { background:none; border:none; color:#6b6455; text-decoration:underline; cursor:pointer; font-size:12px; font-family:'IBM Plex Sans',sans-serif; }

  .tabs { display:flex; padding:0 20px; background:var(--paper); border-bottom:1px solid var(--line); overflow-x:auto; }
  .tab-btn { padding:11px 14px; background:none; border:none; border-bottom:2px solid transparent; font-size:13.5px; cursor:pointer; color:#6b6455; font-family:inherit; white-space:nowrap; }
  .tab-btn.active { color:var(--ink); border-bottom-color:var(--brick); font-weight:600; }
  .tab-btn:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }

  .content { padding:18px 20px 40px; max-width:1040px; margin:0 auto; }
  .intro { font-size:13px; color:#5a5546; margin:0 0 14px; line-height:1.55; max-width:700px; }
  .filter-bar { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px; }
  .filter-bar input, .filter-bar select { padding:7px 9px; border:1px solid var(--line); background:var(--paper-dark); font-family:inherit; font-size:12.5px; }

  .grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); gap:14px; }
  .ptile { background:var(--paper-dark); border:1px solid var(--line); cursor:pointer; display:flex; flex-direction:column; }
  .ptile:hover { border-color:var(--forest); }
  .ptile:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }
  .art { display:block; border-bottom:1px solid var(--line); }
  .ptile-body { padding:10px 12px 12px; }
  .ptile-name { font-weight:600; font-size:13.5px; margin-bottom:4px; }
  .tag { font-size:10px; padding:2px 6px; border:1px solid var(--tag-color); color:var(--tag-color); white-space:nowrap; margin-right:4px; display:inline-block; }
  .price { font-family:'IBM Plex Mono', monospace; font-weight:600; font-variant-numeric:tabular-nums; }
  .chg-up { color:var(--gain); font-family:'IBM Plex Mono', monospace; font-size:12.5px; font-variant-numeric:tabular-nums; }
  .chg-down { color:var(--loss); font-family:'IBM Plex Mono', monospace; font-size:12.5px; font-variant-numeric:tabular-nums; }
  .rent-line { font-size:11.5px; color:#5a5546; margin-top:4px; }
  .muted { font-size:11px; color:var(--muted); }
  .sv-link { font-size:11.5px; color:var(--navy); text-decoration:underline; display:inline-block; margin-top:6px; }
  .auction-badge { font-size:10.5px; background:var(--gold); color:var(--ink); padding:2px 6px; }
  .lock-badge { font-size:10.5px; background:var(--ink); color:#f2efe4; padding:2px 6px; }

  .card { background:var(--paper-dark); border:1px solid var(--line); padding:16px 18px; margin-bottom:14px; }
  .card h3 { font-family:'Fraunces', serif; font-size:16px; margin:0 0 4px; font-weight:600; }
  .card .meta { font-size:12px; color:#6b6455; margin-bottom:10px; }
  .card-row { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-wrap:wrap; }
  .field-row { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-top:8px; }
  .field-row label { font-size:12px; color:#5a5546; }
  .field-row input, .field-row select { padding:6px 8px; border:1px solid var(--line); background:var(--paper); font-family:'IBM Plex Mono', monospace; font-size:13px; width:120px; }
  .empty { color:#8b8471; font-size:13px; padding:20px 0; text-align:center; border:1px dashed var(--line); }
  .hold-note { font-size:11.5px; padding:3px 0; }
  .hold-note.ok { color:var(--gain); }
  .hold-note.warn { color:var(--loss); }
  .cluster-head { font-family:'Fraunces', serif; font-size:15px; margin:18px 0 8px; padding-bottom:4px; border-bottom:1px solid var(--line); }

  .portfolio-total { display:flex; gap:24px; margin-bottom:16px; flex-wrap:wrap; }
  .portfolio-total .block { border-left:3px solid var(--forest); padding-left:10px; }
  .portfolio-total .label { font-size:11px; text-transform:uppercase; color:#6b6455; letter-spacing:0.05em; }
  .portfolio-total .value { font-family:'IBM Plex Mono', monospace; font-size:19px; font-weight:600; font-variant-numeric:tabular-nums; }

  .trade-cols { display:flex; gap:16px; flex-wrap:wrap; }
  .trade-col { flex:1; min-width:220px; }
  .check-list { display:flex; flex-direction:column; gap:5px; max-height:180px; overflow-y:auto; border:1px solid var(--line); padding:8px; background:var(--paper); }
  .check-row { display:flex; align-items:center; gap:7px; font-size:12.5px; }
  .offer-block { border:1px solid var(--line); padding:12px; margin-bottom:10px; background:var(--paper); }
  .search-input { padding:6px 8px; border:1px solid var(--line); background:var(--paper); font-family:inherit; font-size:12.5px; width:180px; }

  table.lb { width:100%; border-collapse:collapse; font-size:13.5px; }
  table.lb th { text-align:left; font-weight:500; color:#6b6455; font-size:11px; text-transform:uppercase; letter-spacing:0.05em; padding:6px 8px; border-bottom:1px solid var(--line); }
  table.lb td { padding:10px 8px; border-bottom:1px solid var(--line); font-variant-numeric:tabular-nums; }
  .lb-wrap { overflow-x:auto; }
  .rank { font-family:'Fraunces', serif; font-size:16px; width:36px; }
  .you-row td { background:rgba(31,75,63,0.08); }

  .gauge-row { display:flex; align-items:center; gap:10px; margin-bottom:9px; font-size:12.5px; }
  .gauge-label { width:110px; flex-shrink:0; color:#5a5546; }
  .gauge-track { flex:1; height:8px; background:var(--paper); border:1px solid var(--line); position:relative; }
  .gauge-fill { position:absolute; top:0; bottom:0; background:var(--forest); }
  .gauge-fill.neg { background:var(--loss); }
  .event-row { padding:9px 0; border-bottom:1px solid var(--line); font-size:13px; display:flex; gap:10px; }
  .event-time { font-family:'IBM Plex Mono', monospace; font-size:11px; color:#8b8471; white-space:nowrap; padding-top:1px; }

  .notice-toast { position:fixed; bottom:18px; left:50%; transform:translateX(-50%); background:var(--ink); color:#f2efe4; padding:10px 18px; font-size:13px; z-index:120; max-width:90vw; text-align:center; }
  /* ---- Territory desk (map V2 look) ----------------------------------
     The frame, the palette and the field-report panel come from the V2
     design; the map inside them is still the SVG sheet, so this costs no
     tile provider, no extra scripts and no change to the page's
     Content-Security-Policy. */
  .map-desk { --desk-forest:#183f35; --desk-forest-deep:#0f2c25; --desk-navy:#253657;
    --desk-gold:#c8a633; --desk-gold-bright:#e7cb61; --desk-brick:#9f3d29; --desk-rule:rgba(232,218,174,.18); }
  .map-desk .map-layout { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(260px,1fr); gap:0;
    border:3px solid #253a34; outline:1px solid #b69a3c; outline-offset:-7px; background:#172b26;
    box-shadow:0 18px 44px rgba(31,27,18,.26); align-items:stretch; }
  .map-desk .map-svg-wrap { max-width:none; min-width:0; border:0; border-right:3px solid #263f37;
    background:#a8aa95; padding:0; position:relative; }
  .map-desk .map-svg-wrap svg { display:block; }
  /* Gold corner marks, drawn over the sheet and never in the way of it. */
  .map-corner { position:absolute; z-index:3; width:30px; height:30px; pointer-events:none; }
  .corner-nw { top:7px; left:7px; border-top:3px solid #d6b643; border-left:3px solid #d6b643; }
  .corner-se { right:7px; bottom:7px; border-right:3px solid #d6b643; border-bottom:3px solid #d6b643; }

  .zoom-readout { display:flex; flex-direction:column; gap:2px; padding:8px 14px; text-align:right;
    color:#eee7d4; background:var(--desk-navy); border-right:4px solid var(--desk-gold); }
  .zoom-readout span { color:var(--desk-gold-bright); font-family:'IBM Plex Mono', monospace; font-size:10px;
    letter-spacing:.14em; text-transform:uppercase; }
  .zoom-readout b { font-family:'Fraunces', serif; font-size:13px; font-weight:600; }

  /* TOP-LEFT, NOT BOTTOM-LEFT.

     The key floated over the south-west of the city and sat squarely on
     Dringhouses — a district you could see but never click. Any corner
     covers something, so it moves up under the breadcrumb bar, where the
     map's own furniture already lives, and the city now opens a little
     zoomed out so there is margin rather than district underneath it. */
  .map-key { position:absolute; left:14px; top:84px; z-index:3; display:flex; flex-wrap:wrap; gap:6px 10px;
    max-width:220px; padding:9px 11px; color:#eee6d1; border:1px solid #c4a841; background:rgba(14,37,31,.94);
    box-shadow:0 5px 0 rgba(7,22,18,.5); font-size:10px; }
  .map-key b { width:100%; color:var(--desk-gold-bright); font-family:'IBM Plex Mono', monospace;
    font-size:8px; letter-spacing:.14em; }
  .map-key span { display:flex; align-items:center; gap:5px; color:#e5dfcf; }
  .key-mark { width:9px; height:9px; display:inline-block; border:1px solid rgba(255,255,255,.5); transform:rotate(45deg); }
  .zoom-hint { position:absolute; left:50%; top:14px; z-index:3; transform:translateX(-50%); padding:5px 10px;
    border:1px solid #e6c755; color:#f5e7aa; background:rgba(26,43,70,.94); box-shadow:0 4px 0 rgba(16,25,43,.5);
    font-family:'IBM Plex Mono', monospace; font-size:9px; letter-spacing:.12em; pointer-events:none; }

  /* The inspector becomes a field report rather than a stack of cards. */
  .map-desk .map-side { min-width:0; padding:24px; color:#ece5d2; background-color:#152e27;
    background-image:linear-gradient(rgba(229,214,170,.04) 1px,transparent 1px),linear-gradient(90deg,rgba(229,214,170,.04) 1px,transparent 1px);
    background-size:13px 13px; }
  .map-desk .map-side::before { content:"FIELD REPORT"; display:block; margin:-24px -24px 20px; padding:10px 24px;
    color:var(--desk-gold-bright); border-bottom:1px solid #56655c; background:#0d241e;
    font-family:'IBM Plex Mono', monospace; font-weight:700; font-size:9px; letter-spacing:.16em; }
  .map-desk .map-side .card { border:0; background:transparent; padding:0; margin:0 0 18px; box-shadow:none; }
  .map-desk .map-side h3 { color:#fff6df; }
  .map-desk .map-side .meta, .map-desk .map-side .muted { color:#c9c4b5; }
  .map-desk .map-side .empty { color:#a7ab9d; }
  .map-desk .map-side .block .label { color:#aeb2a5; }
  .map-desk .map-side .block .value { color:#f4e9ca; }
  .map-desk .map-side .cluster-row { border-bottom-color:var(--desk-rule); color:#e7e1cf; }
  .map-desk .map-side .cluster-row:hover { background:rgba(232,218,174,.06); }
  .map-desk .map-side .price { color:#f4e9ca; }
  .map-desk .legend-wrap { padding:10px 14px; margin:0; background:#132822; border-top:1px solid #26413a; }
  .map-desk .legend-row { color:#cfc9b8; }
  .map-desk .map-zoom-btn { border-color:#d4b849; color:#f4e7bd; background:#173a31; }
  .map-desk .map-zoom-btn:hover { border-color:#f0d56b; }

  /* One control for both keys. Sits with the zoom buttons rather than in the
     flow, so folding the keys away does not move the map. */
  .map-keys-toggle { position:absolute; left:14px; top:52px; z-index:4; padding:4px 10px; cursor:pointer;
    border:1px solid #d4b849; border-radius:3px; color:#f4e7bd; background:rgba(23,58,49,.9);
    font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.08em; }
  .map-keys-toggle:hover { border-color:#f0d56b; }

  @media (max-width: 900px) {
    .map-desk .map-layout { grid-template-columns:1fr; }
    .map-desk .map-svg-wrap { border-right:0; border-bottom:3px solid #263f37; }
  }

  /* Phones. The sheet gets a fixed share of the viewport so it stays a map
     rather than a stripe, the keys stop floating over it (they cover a third
     of a 360px screen), and the field report scrolls on its own instead of
     pushing the map off the top. */
  @media (max-width: 760px) {
    .map-desk .map-svg-wrap svg { max-height:58vh; }
    .map-desk .map-key, .map-desk .legend-wrap { position:static; max-width:none; }
    .map-key { position:static; margin:0; border-radius:0; top:auto; }
    .map-desk .map-side { padding:16px; max-height:52vh; overflow-y:auto; }
    .map-desk .map-side::before { margin:-16px -16px 14px; padding:9px 16px; }
    .map-desk .zoom-hint { font-size:9px; padding:4px 8px; }
    .map-switch { flex-wrap:wrap; }
    .map-switch .zoom-readout { flex:1 1 100%; }
  }

  .map-layout { display:flex; gap:20px; flex-wrap:wrap; align-items:flex-start; }
  .map-svg-wrap { flex:1.3; min-width:300px; max-width:480px; background:var(--paper-dark); border:1px solid var(--line); padding:10px; position:relative; }
  .map-pin { cursor:pointer; }
  /* Zoom controls sit over the sheet rather than in it, so they stay put
     while the map moves underneath and never end up scaled with it. */
  .map-zoom { position:absolute; right:16px; top:16px; display:flex; flex-direction:column; gap:4px; z-index:2; }
  .map-zoom-btn { width:26px; height:26px; padding:0; border:1px solid var(--line); background:var(--paper);
    color:var(--ink); font-family:'IBM Plex Mono', monospace; font-size:14px; line-height:1; cursor:pointer;
    border-radius:3px; opacity:0.9; }
  .map-zoom-btn:hover { opacity:1; border-color:var(--ink); }
  .map-zoom-btn.wide { width:26px; font-size:9px; letter-spacing:0.2px; }
  /* A trader's name is a way into their profile everywhere it appears, but
     it has to keep reading as a name inside a sentence rather than turning
     every mention into a button. */
  .trader-link { background:none; border:0; padding:0; margin:0; font:inherit; color:inherit;
    cursor:pointer; display:inline; text-align:left; border-bottom:1px dotted var(--line); }
  .trader-link:hover { border-bottom-color:var(--ink); }
  .trader-link:focus-visible { outline:2px solid var(--ink); outline-offset:2px; }

  /* Someone else's portfolio, as pictures. Fixed aspect so a wall of them
     reads as a collection rather than a ragged column. */
  .holding-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(86px, 1fr)); gap:7px; }
  /* Rarity is carried the same way the market tiles carry it — border plus
     ring — with a colour bar along the top edge as well, because at 86px a
     1px border is too quiet to read across a grid. --q is set per tile by
     the q- class and everything else resolves through it. */
  .holding-tile { --q:var(--line); position:relative; border:1px solid var(--q); border-radius:4px;
    overflow:hidden; background:var(--paper-dark); line-height:0; }
  .holding-tile.q-uncommon { --q:#8E979F; box-shadow:0 0 0 1px rgba(142,151,159,.3); }
  .holding-tile.q-rare     { --q:#B08C1E; box-shadow:0 0 0 1px rgba(176,140,30,.34); }
  .holding-tile.q-ultra    { --q:#B4342E; box-shadow:0 0 0 2px rgba(180,52,46,.26); }
  .holding-tile.q-secret   { --q:#7A5AA8; box-shadow:0 0 0 2px rgba(122,90,168,.32); }
  .holding-rarity { position:absolute; inset:0 0 auto 0; height:4px; z-index:2; background:var(--q); }
  .holding-tile.q-common .holding-rarity { background:rgba(90,82,70,.5); }
  .holding-tile.open { cursor:pointer; }
  .holding-tile.open:hover { border-color:var(--ink); }
  .holding-tile img, .holding-tile svg { width:100%; height:auto; aspect-ratio:3/2; object-fit:cover; display:block; }
  .holding-cap { padding:4px 6px 5px; line-height:1.25; display:flex; flex-direction:column; gap:1px;
    font-size:10.5px; }
  .holding-cap .muted { font-size:9.5px; }

  .legend-swatch.ring { background:transparent; border-radius:50%; box-sizing:border-box; }
  .legend-swatch.ring.you { border:2px solid #2F6B45; }
  .legend-swatch.ring.rival { border:2px solid #B0342A; }
  .legend-swatch.ring.free { border:1px solid #9AA39C; }
  .map-pin-label { font-size:8px; fill:var(--ink); pointer-events:none; }
  .map-side { flex:1; min-width:260px; }
  .legend-wrap { display:flex; flex-wrap:wrap; gap:10px; margin-top:10px; }
  .legend-row { display:flex; align-items:center; gap:5px; font-size:11px; color:#5a5546; }
  .legend-swatch { width:9px; height:9px; border-radius:50%; display:inline-block; }
  .cluster-row { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:7px 0; border-bottom:1px solid var(--line); font-size:12.5px; cursor:pointer; }

  .modal-backdrop { position:fixed; inset:0; background:rgba(20,20,15,0.55); display:flex; align-items:center; justify-content:center; z-index:100; padding:16px; }
  /* ABOVE EVERYTHING, INCLUDING THE TOAST.
     The confirmation is raised from a property tile that has usually already
     opened its own modal, and both were .modal-backdrop at z-index 100 — so
     the one rendered later in the tree simply covered the question being
     asked. It is a modal ABOUT another modal, so it gets its own layer, and
     one above the notice toast as well, which otherwise lands squarely on
     the Buy button. */
  .modal-backdrop.confirm-backdrop { z-index:140; }
  .modal-box { background:var(--paper); border:1px solid var(--ink); max-width:500px; width:100%; max-height:88vh; overflow-y:auto; position:relative; }
  .modal-inner { padding:18px 20px 22px; }
  .modal-close { position:absolute; top:8px; right:12px; background:rgba(255,255,255,0.85); border:none; font-size:20px; cursor:pointer; color:#3a352a; width:28px; height:28px; }
  .hist-row { font-size:12px; color:#5a5546; padding:4px 0; border-bottom:1px solid var(--line); }
  .improve-box { border:1px solid var(--line); background:var(--paper-dark); padding:10px 12px; margin-top:10px; font-size:12.5px; }
  .conn-dot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--gold); margin-right:5px; }
  .foreclosure-badge { font-size:10px; letter-spacing:0.08em; text-transform:uppercase; background:var(--loss); color:#F2EFE4; padding:2px 7px; vertical-align:middle; font-family:'IBM Plex Sans',sans-serif; font-weight:600; }

/* ---- server build additions ---- */
.auth-wrap { display:flex; align-items:center; justify-content:center; min-height:100vh; padding:24px; }
.auth-card { background:var(--paper-dark); border:1px solid var(--line); padding:30px 34px; max-width:430px; width:100%; }
.auth-card h1 { font-family:'Fraunces', serif; font-weight:700; font-size:27px; margin:0 0 4px; }
.auth-card .lede { font-size:13.5px; color:#4b463a; line-height:1.55; margin:0 0 16px; }
.auth-card label { display:block; font-size:11px; text-transform:uppercase; letter-spacing:0.06em; color:#6b6455; margin:10px 0 4px; }
.auth-card input { width:100%; padding:10px 12px; font-size:15px; border:1px solid var(--line); background:var(--paper); font-family:inherit; }
.auth-card input:focus-visible { outline:2px solid var(--gold); outline-offset:1px; }
.auth-switch { margin-top:14px; font-size:12.5px; color:#6b6455; }
.auth-switch button { background:none; border:none; color:var(--navy); text-decoration:underline; cursor:pointer; font-size:12.5px; font-family:inherit; padding:0; }
.hint { font-size:11.5px; color:#8b8471; margin-top:4px; line-height:1.5; }
.gate-note { border-left:3px solid var(--gold); padding:8px 0 8px 10px; font-size:12px; color:#5a5546; line-height:1.55; margin:12px 0; background:rgba(176,140,30,0.06); }
.notif-row { display:flex; gap:10px; padding:8px 0; border-bottom:1px solid var(--line); font-size:12.5px; }
.notif-dot { width:6px; height:6px; border-radius:50%; background:var(--gold); margin-top:6px; flex-shrink:0; }
.conn-bad { background:var(--loss); }
.offline-bar { background:var(--loss); color:#F2EFE4; padding:6px 20px; font-size:12.5px; text-align:center; }

/* The lock countdown. Sits above the ticker and looks like the ticker's
   serious cousin — same navy, but it does not scroll, because a deadline
   that slides off the edge of the screen is not a deadline. */
.lock-bar { display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:12px;
  padding:7px 20px; background:var(--navy); color:#F2EFE4; font-size:12.5px;
  border-bottom:1px solid var(--ink); }
.lock-bar-clock { font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:.1em;
  padding:2px 8px; border:1px solid #e9c95a; color:#e9c95a; }
.lock-bar-go { padding:3px 10px; cursor:pointer; font-size:12px; color:#14150F;
  background:#e9c95a; border:1px solid #14150F; border-radius:2px; }
.lock-bar-go:hover { background:#f5dd86; }
.lock-bar-x { margin-left:4px; padding:0 8px; cursor:pointer; font-size:18px; line-height:1.3; color:#F2EFE4;
  background:none; border:1px solid rgba(242,239,228,.35); border-radius:2px; }
.lock-bar-x:hover, .lock-bar-x:focus-visible { border-color:#F2EFE4; }
@media (max-width: 640px) { .lock-bar { font-size:11.5px; padding:6px 12px; gap:8px; } }

/* ---- purchasable themes -------------------------------------------------
   Each overrides the palette tokens only; every component reads them, so a
   theme is a dozen colour values rather than a second stylesheet. */
.ukpx-root.theme-night-desk {
  --paper:#1E1F1C; --paper-dark:#262723; --ink:#E8E3D4; --forest:#7FA08C; --forest-dark:#5E7C6A;
  --navy:#8FA8C9; --brick:#D08A6A; --gain:#7FBF95; --loss:#E08573; --gold:#D9B45A; --silver:#C3CBD3; --line:#3C3D37;
  --war-paper:#1D211D; --war-line:#3A3D37;
  --muted:#9A9484;
}
.ukpx-root.theme-night-desk .topbar { background:#14150F; }
.ukpx-root.theme-night-desk .ticker-wrap { background:#101821; }
.ukpx-root.theme-night-desk .btn { color:#14150F; background:var(--forest); border-color:#0E0F0B; }
.ukpx-root.theme-night-desk .btn.secondary { color:var(--ink); background:transparent; }
.ukpx-root.theme-night-desk .lock-badge { background:var(--ink); color:#14150F; }
.ukpx-root.theme-night-desk .modal-close { background:rgba(40,40,36,0.9); color:var(--ink); }

.ukpx-root.theme-blueprint {
  --paper:#12314F; --paper-dark:#173A5C; --ink:#E3EDF7; --forest:#7FB0D8; --forest-dark:#5D93BE;
  --navy:#AFCDE6; --brick:#F0A98A; --gain:#8FD3B0; --loss:#F0968A; --gold:#EBD9A6; --silver:#D3DCE5; --line:#2E5578;
  --war-paper:#0E1A24; --war-line:#2E5578;
  --muted:#93AEC8;
}
.ukpx-root.theme-blueprint .topbar { background:#0D2540; }
.ukpx-root.theme-blueprint .ticker-wrap { background:#0A1D33; color:#EBD9A6; }
.ukpx-root.theme-blueprint .btn { color:#0D2540; background:var(--forest); border-color:#08192C; }
.ukpx-root.theme-blueprint .btn.secondary { color:var(--ink); background:transparent; }
.ukpx-root.theme-blueprint .lock-badge { background:var(--ink); color:#0D2540; }
.ukpx-root.theme-blueprint .modal-close { background:rgba(23,58,92,0.92); color:var(--ink); }

.ukpx-root.theme-terminal {
  --paper:#080C08; --paper-dark:#0E140E; --ink:#B7F5C0; --forest:#2C8C43; --forest-dark:#1F6B31;
  --navy:#7FE0A0; --brick:#E4C86A; --gain:#5CE07C; --loss:#F07A6A; --gold:#D8E36A; --silver:#C6D0C8; --line:#1C2E1C;
  --war-paper:#0D160D; --war-line:#1C2E1C;
  --muted:#6E9E77;
  font-family:'IBM Plex Mono', monospace;
}
.ukpx-root.theme-terminal .topbar { background:#0B1A0D; }
.ukpx-root.theme-terminal .ticker-wrap { background:#04140A; color:#7FE0A0; }
.ukpx-root.theme-terminal h1, .ukpx-root.theme-terminal h3, .ukpx-root.theme-terminal .rank { font-family:'IBM Plex Mono', monospace !important; }
.ukpx-root.theme-terminal .btn { color:#04140A; background:var(--forest); border-color:#04140A; }
.ukpx-root.theme-terminal .btn.secondary { color:var(--ink); background:transparent; }
.ukpx-root.theme-terminal .lock-badge { background:var(--ink); color:#04140A; }
.ukpx-root.theme-terminal .modal-close { background:rgba(14,20,14,0.92); color:var(--ink); }

/* ---- shop ---- */
.shop-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(260px, 1fr)); gap:14px; }
.shop-item { background:var(--paper-dark); border:1px solid var(--line); padding:14px 16px; display:flex; flex-direction:column; gap:6px; }
.shop-item h4 { margin:0; font-family:'Fraunces', serif; font-size:15px; font-weight:600; }
.shop-item .blurb { font-size:12.5px; color:#6b6455; line-height:1.5; flex:1; }
.shop-price { font-family:'IBM Plex Mono', monospace; font-weight:600; font-size:15px; }
.owned-tag { font-size:10.5px; background:var(--forest); color:#fff; padding:2px 7px; align-self:flex-start; }
.swatch-row { display:flex; gap:8px; flex-wrap:wrap; margin-top:8px; }
.swatch { width:54px; height:38px; border:1px solid var(--line); cursor:pointer; padding:0; position:relative; }
.swatch.active { outline:2px solid var(--gold); outline-offset:1px; }
.swatch[disabled] { opacity:0.35; cursor:not-allowed; }
.crest-btn { width:44px; height:44px; border:1px solid var(--line); background:var(--paper); cursor:pointer; padding:3px; }
.crest-btn.active { outline:2px solid var(--gold); outline-offset:1px; }
.crest-btn[disabled] { opacity:0.3; cursor:not-allowed; }
.crest-inline { vertical-align:-2px; margin-right:4px; }
.firm-line { font-size:11px; color:#8b8471; font-style:italic; }
.founder-mark { color:var(--gold); margin-left:3px; }

/* ---- map style switcher ----
   Locked styles stay visible rather than hidden: seeing that Market Heat
   exists is what makes the Broker feed worth saving up for. */
.map-switch { display:flex; gap:0; margin-bottom:14px; border:1px solid var(--line); flex-wrap:wrap; }
.map-switch-btn {
  padding:8px 15px; background:var(--paper); border:none; border-right:1px solid var(--line);
  font-family:inherit; font-size:12.5px; color:#6b6455; cursor:pointer;
  display:flex; align-items:center; gap:7px;
}
.map-switch-btn:last-child { border-right:none; }
.map-switch-btn:hover:not(.active) { background:var(--paper-dark); }
.map-switch-btn.active { background:var(--forest); color:#fff; font-weight:600; }
.map-switch-btn.locked { color:#a29b88; cursor:help; }
.map-switch-btn:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }
.lock-pip {
  font-family:'IBM Plex Mono', monospace; font-size:9px; letter-spacing:0.08em; text-transform:uppercase;
  border:1px solid currentColor; padding:1px 4px; opacity:0.75;
}

/* ---- rarity marker ----------------------------------------------------
   The inline pill used in lists and the tactics table. The card frame
   itself is styled further down. */
.rarity-mark { display:inline-flex; align-items:center; gap:4px; vertical-align:middle;
  margin-left:5px; padding:1px 5px; border:1px solid; border-radius:2px;
  font-size:10px; letter-spacing:.05em; text-transform:uppercase; }
.rarity-dot { width:6px; height:6px; border-radius:50%; display:inline-block; }
.rarity-mark.q-common { border-color:var(--line); color:var(--muted); }
.rarity-mark.q-common .rarity-dot { background:var(--line); }

.ability-line { margin-top:6px; font-size:11.5px; line-height:1.45; color:var(--muted);
  border-left:2px solid var(--line); padding-left:7px; }
.ability-line strong { color:var(--ink); font-weight:600; }
.ability-line.off { opacity:.5; }
/* Said quietly on a property you do not own — it is a condition to know
   about, not a score you are being marked against. */
.ability-line .set-need { color:var(--muted); font-family:'IBM Plex Mono', monospace;
  font-size:10.5px; letter-spacing:.04em; }

.ability-row { display:flex; gap:8px; align-items:flex-start; padding:7px 0;
  border-top:1px solid var(--line); font-size:12.5px; }
.ability-row .dot { width:8px; height:8px; border-radius:50%; margin-top:5px; flex:0 0 auto; }
.ability-row.inactive { opacity:.45; }

/* ---- friends ---------------------------------------------------------- */
.seg { display:inline-flex; border:1px solid var(--line); border-radius:8px; overflow:hidden; }
.seg-btn { padding:5px 12px; border:0; background:transparent; color:var(--muted);
  font-size:13px; cursor:pointer; font-family:inherit; }
.seg-btn.on { background:var(--accent, #2f5d50); color:#fff; }
.inline-form { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.inline-form input { flex:1 1 180px; min-width:0; padding:7px 10px; border:1px solid var(--line);
  border-radius:6px; font:inherit; font-size:14px; background:var(--paper, #fffdf8); color:inherit; }
.friend-row { display:flex; justify-content:space-between; align-items:center; gap:10px;
  padding:6px 0; border-top:1px solid var(--line); font-size:14px; }
.friend-row .btn.small + .btn.small { margin-left:6px; }
.btn.ghost { background:transparent; border:1px solid var(--line); color:var(--muted); }

/* ---- hostile bids ------------------------------------------------------ */
.takeover-alert { display:flex; gap:14px; justify-content:space-between; align-items:center;
  flex-wrap:wrap; margin:0 0 12px; padding:12px 14px; border-radius:10px;
  border:1px solid #8c2f2f; background:rgba(140,47,47,.07); }
.takeover-alert.mine { border-color:var(--line); background:transparent; }
.btn.danger { background:#8c2f2f; border-color:#8c2f2f; color:#fff; }
.btn.danger:disabled { opacity:.45; }
/* The interception sits between a plain tactic and the takeover: it moves
   money rather than a deed, so it is marked but not painted as the nuclear
   option that the takeover is. */
.btn.danger-soft { background:transparent; color:#8c2f2f; border-color:#8c2f2f; }
.btn.danger-soft:hover:not(:disabled) { background:#8c2f2f; color:#fff; }
.set-count { font-family:'IBM Plex Mono', monospace; font-size:10.5px; padding:1px 5px;
  border-radius:4px; background:var(--line); color:var(--ink); margin-left:4px; }

/* ---- property cards ----------------------------------------------------
   A collectible card: full-bleed art, a rarity ribbon, a crest for the
   building type, and the address beneath. The rarity colour owns the frame,
   the ribbon and the crest, so all three say the same thing at a glance. */
.pcard { position:relative; border-radius:12px; overflow:hidden; background:var(--paper);
  border:3px solid var(--line); cursor:pointer; display:flex; flex-direction:column;
  transition:transform .12s ease, box-shadow .12s ease; }
.pcard:hover { transform:translateY(-2px); }
.pcard.q-common   { border-color:var(--line); }
.pcard.q-uncommon { border-color:#8E979F; box-shadow:0 0 0 1px rgba(142,151,159,.3); }
.pcard.q-rare     { border-color:#B08C1E; box-shadow:0 0 0 1px rgba(176,140,30,.34); }
.pcard.q-ultra    { border-color:#B4342E; box-shadow:0 0 0 2px rgba(180,52,46,.26); }
.pcard.q-secret   { border-color:#7A5AA8; box-shadow:0 0 0 2px rgba(122,90,168,.32); }

.pcard-art { position:relative; line-height:0; background:var(--line); }
.pcard-art img { width:100%; aspect-ratio:3/2; object-fit:cover; display:block; }
.pcard-art .art { width:100%; height:auto; display:block; }

.ribbon { position:absolute; top:0; right:0; display:flex; align-items:center;
  padding:4px 10px 5px; border-bottom-left-radius:9px; line-height:1;
  font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.11em;
  color:#fff; background:rgba(40,36,30,.82); }
.ribbon.q-common   { background:rgba(90,82,70,.88); }
.ribbon.q-uncommon { background:#7B848C; }
.ribbon.q-rare     { background:#A8871F; }
.ribbon.q-ultra    { background:#9C2C27; }
.ribbon.q-secret   { background:#6A4E93; }

.pcard-head { display:flex; gap:9px; align-items:center; padding:9px 11px 0; }
.crest { display:inline-flex; align-items:center; justify-content:center; flex:0 0 auto;
  width:28px; height:28px; border-radius:8px; color:#fff; background:#5A5246; }
.crest.q-uncommon { background:#7B848C; } .crest.q-rare { background:#A8871F; }
.crest.q-ultra { background:#9C2C27; }   .crest.q-secret { background:#6A4E93; }
.pcard-title { min-width:0; }
.pcard-name { font-weight:600; font-size:14px; color:var(--ink); line-height:1.25; }
.pcard-place { display:flex; align-items:center; gap:4px; margin-top:2px;
  font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.09em;
  text-transform:uppercase; color:#9C4A3C; }
.pcard-tag { padding:6px 11px 0; font-style:italic; font-size:12px; color:var(--muted);
  font-family:'Cormorant Garamond', Georgia, serif; font-size:13.5px; }
.pcard-body { padding:8px 11px 11px; }

  /* ---- the market draw ------------------------------------------------
     Ported from the motion study, repainted in the exchange's own palette
     and scoped under .draw-* so nothing here can leak into the rest of the
     page. The stage carries the rarity as a class and every colour below
     resolves through --reveal, so one class swap changes the whole reveal. */
  /* The one bright thing on the Market tab. It has to out-shout a grid of
     property cards without looking like an advert bolted onto a ledger, so
     it borrows the deep forest of the top bar and the gold rule, and earns
     its brightness with contrast rather than saturation. */
  .lotto-bar { display:flex; align-items:center; gap:14px; margin:0 0 18px; padding:14px 18px;
    color:#F4EFDF; background:linear-gradient(100deg, var(--forest-dark) 0%, var(--forest) 62%, #276151 100%);
    border:1px solid var(--forest-dark); border-left:5px solid var(--gold);
    box-shadow:0 6px 16px rgba(22,52,41,.24); }
  .lotto-bar.resting { background:linear-gradient(100deg,#3C4A44 0%,#4A5A52 100%); border-left-color:#8b8264; }
  .lotto-ticket { font-size:26px; line-height:1; color:var(--gold); flex:none;
    filter:drop-shadow(0 0 7px rgba(176,140,30,.5)); animation:lotto-pulse 2.6s ease-in-out infinite; }
  .lotto-bar.resting .lotto-ticket { color:#9a927c; filter:none; animation:none; }
  @keyframes lotto-pulse { 0%,100% { opacity:.75; transform:scale(1); } 50% { opacity:1; transform:scale(1.12); } }
  @media (prefers-reduced-motion: reduce) { .lotto-ticket { animation:none; } }
  .lotto-copy { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .lotto-kicker { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.14em; color:var(--gold); }
  .lotto-copy strong { font-family:'Fraunces', serif; font-size:21px; font-weight:700; line-height:1.05; }
  .lotto-sub { font-size:12.5px; color:#cfdcd2; line-height:1.4; }
  .btn.lotto-go { background:var(--gold); color:#2A2410; border-color:#7A6115; font-weight:700;
    padding:11px 20px; flex:none; }
  .btn.lotto-go:hover:not(:disabled) { background:#dcb63a; }
  /* Full opacity on the resting state rather than the global 40% fade: a
     ghosted button reads as broken, where a solid one that says when it
     opens reads as a clock. */
  .lotto-bar .btn.lotto-go:disabled { background:#7d7660; color:#e8e3d3; border-color:#5f5a49; opacity:1; }

  .lotto-box { max-width:660px; }
  .lotto-title { font-family:'Fraunces', serif; font-size:24px; margin:3px 0 8px; }
  .lotto-lede { font-size:14px; line-height:1.55; color:#4b463a; margin:0 0 12px; }
  .lotto-rules { margin:0 0 16px; padding-left:18px; font-size:13px; line-height:1.55; color:#4b463a; }
  .lotto-rules li { margin-bottom:6px; }
  .lotto-rules b { font-weight:600; }
  .lotto-choose { font-family:'IBM Plex Mono', monospace; font-size:10.5px; letter-spacing:.12em;
    color:#6b6455; text-transform:uppercase; border-top:1px solid var(--line); padding-top:12px; margin-bottom:10px; }

  .draw-bands { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:12px; }
  .draw-band { border:1px solid var(--line); background:var(--paper); padding:12px 14px; text-align:left; cursor:pointer;
    font-family:inherit; color:var(--ink); display:flex; flex-direction:column; gap:6px; transition:border-color .12s, box-shadow .12s; }
  .draw-band:hover:not(:disabled) { border-color:var(--forest); box-shadow:0 3px 0 rgba(31,75,63,.16); }
  .draw-band[aria-pressed="true"] { border-color:var(--forest); box-shadow:inset 0 0 0 1px var(--forest); }
  .draw-band:disabled { opacity:.45; cursor:not-allowed; }
  .draw-band-name { font-family:'Fraunces', serif; font-weight:700; font-size:15px; }
  .draw-band-fee { font-family:'IBM Plex Mono', monospace; font-size:22px; font-weight:600; font-variant-numeric:tabular-nums; }
  .draw-band-blurb { font-size:12px; color:#5e584a; line-height:1.45; }
  .draw-band-facts { font-family:'IBM Plex Mono', monospace; font-size:11px; color:#6b6455; letter-spacing:.02em; }
  .draw-confirm { margin-top:12px; border-top:1px solid var(--line); padding-top:12px; display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .draw-confirm .note { font-size:12px; color:#5e584a; flex:1; min-width:220px; line-height:1.45; }

  .draw-overlay { position:fixed; inset:0; z-index:80; display:grid; place-items:center; padding:16px;
    background:rgba(20,26,23,.72); backdrop-filter:blur(2px); overflow:auto; }
  .draw-stage { --reveal:#B08C1E; position:relative; width:min(860px,100%); border:1px solid #887f68;
    outline:1px solid rgba(255,255,255,.3); outline-offset:-6px; background:#F3EFE2; box-shadow:0 30px 70px rgba(10,17,15,.5);
    padding:20px 22px 16px; }
  .draw-stage.q-common { --reveal:#9aa09b; }
  .draw-stage.q-uncommon { --reveal:#8E979F; }
  .draw-stage.q-rare { --reveal:#B08C1E; }
  .draw-stage.q-ultra { --reveal:#B4342E; }
  .draw-stage.q-secret { --reveal:#7A5AA8; }
  .draw-case { display:flex; align-items:flex-start; justify-content:space-between; gap:14px; padding-bottom:10px; border-bottom:1px solid #bbb198; }
  .draw-case-no { display:block; margin-bottom:4px; color:var(--brick); font:11px 'IBM Plex Mono', monospace; letter-spacing:.12em; }
  .draw-case h2 { margin:0; font:700 24px/1.05 'Fraunces', serif; }
  .draw-stamp { min-width:96px; padding:6px 9px; border:2px double var(--brick); color:var(--brick); text-align:center;
    font:700 13px 'IBM Plex Mono', monospace; transform:rotate(2deg); }
  .draw-stamp small { display:block; font-size:9px; letter-spacing:.16em; }
  .draw-status { min-height:22px; margin:10px 0 2px; color:#5d574a; text-align:center; font:italic 15px/1.4 'Fraunces', serif; }

  .draw-space { min-height:300px; display:grid; grid-template-columns:150px 1fr 150px; align-items:center; gap:12px; }
  .draw-side { min-height:196px; padding:14px 12px; border:1px solid #c0b69e; background:rgba(233,228,212,.7); }
  .draw-side .label { display:block; margin-bottom:7px; color:#817760; font:10px 'IBM Plex Mono', monospace; letter-spacing:.11em; }
  .draw-side strong { display:block; font:600 18px 'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }
  .draw-debit { display:block; height:22px; margin-top:7px; opacity:0; color:var(--brick); font:600 13px 'IBM Plex Mono', monospace; }
  .draw-rule { height:3px; margin:14px 0 10px; overflow:hidden; background:#d0c7b1; }
  .draw-rule i { display:block; width:100%; height:100%; background:var(--brick); transform:scaleX(0); transform-origin:left; }
  .draw-side .status { color:#736b5c; font:italic 12.5px 'Fraunces', serif; }
  .draw-rarity-list { display:grid; gap:6px; margin-top:12px; color:#655e50; font-size:11px; }
  .draw-rarity-list span { display:flex; align-items:center; gap:8px; }
  .draw-gem { width:10px; height:10px; display:inline-block; border:1px solid rgba(0,0,0,.28); transform:rotate(45deg); }

  .draw-machine { position:relative; height:296px; display:grid; place-items:center; overflow:hidden; }
  .draw-orbit { position:absolute; width:286px; height:286px; border-radius:50%; opacity:.12;
    background:conic-gradient(from 0deg,#d3d0c8,#B4342E,#B08C1E,#eee,#7A5AA8,#d3d0c8); filter:blur(1px); }
  .draw-orbit::before { content:""; position:absolute; inset:16px; border-radius:inherit; background:#F3EFE2; }
  .draw-orbit span { position:absolute; inset:-7px; border-radius:inherit;
    background:repeating-conic-gradient(from 0deg,transparent 0 4deg,rgba(255,255,255,.65) 5deg 5.5deg,transparent 6deg 10deg); filter:blur(.4px); }
  .draw-halo { position:absolute; width:344px; height:344px; border-radius:50%; opacity:0;
    background:conic-gradient(from 20deg,transparent 0 8%,rgba(243,218,112,.9) 9% 10%,transparent 11% 24%,rgba(157,68,196,.85) 25% 27%,transparent 28% 45%,rgba(255,255,255,.8) 46% 47%,transparent 48% 100%);
    -webkit-mask:radial-gradient(circle,transparent 0 61%,#000 62% 65%,transparent 66%);
    mask:radial-gradient(circle,transparent 0 61%,#000 62% 65%,transparent 66%); }
  .draw-burst { position:absolute; inset:0; z-index:9; pointer-events:none; }
  .draw-spark { position:absolute; left:50%; top:50%; width:var(--size); height:var(--size); opacity:0; border-radius:50%;
    background:var(--spark); box-shadow:0 0 8px var(--spark); }
  .draw-spark.star { border-radius:0; clip-path:polygon(50% 0,61% 37%,100% 50%,61% 63%,50% 100%,39% 63%,0 50%,39% 37%); }
  .draw-flare { position:absolute; z-index:8; width:24px; height:24px; border-radius:50%; opacity:0; background:#fff;
    box-shadow:0 0 28px 12px #fff,0 0 70px 38px var(--reveal); }
  .draw-deeds { position:relative; z-index:3; width:212px; height:266px; perspective:900px; }
  .draw-deed { position:absolute; inset:0; border:1px solid #84795f; background:#e6dfca; box-shadow:0 15px 30px rgba(32,27,18,.25); }
  .draw-ghost { display:grid; place-items:center; opacity:0; color:#81755c; font:700 10px 'IBM Plex Mono', monospace; letter-spacing:.14em; }
  .draw-ghost i { position:absolute; inset:12px; border:3px double #9e9275; }
  .draw-ghost.a { transform:rotate(-9deg) translateX(-15px); }
  .draw-ghost.b { transform:rotate(7deg) translateX(13px); }
  .draw-ghost.c { transform:rotate(-3deg) translateY(-7px); }
  .draw-chosen { transform-style:preserve-3d; }
  .draw-back, .draw-face { position:absolute; inset:0; overflow:hidden; backface-visibility:hidden; }
  .draw-back { display:flex; align-items:center; flex-direction:column; padding-top:40px; color:#f1ead6; background:var(--forest); }
  .draw-back::before { content:""; position:absolute; inset:11px; border:4px double #bca866; }
  .draw-back .glyph { position:relative; font:32px 'Fraunces', serif; }
  .draw-back .rule { position:relative; width:78px; margin:13px 0; border-top:1px solid #bca866; }
  .draw-back b { position:relative; font:700 22px 'Fraunces', serif; letter-spacing:.08em; }
  .draw-back small { position:relative; margin-top:5px; font:9px 'IBM Plex Mono', monospace; letter-spacing:.14em; }
  .draw-seal { position:absolute; right:21px; bottom:20px; width:40px; height:40px; display:grid; place-items:center;
    border:3px double #e2c69c; border-radius:50%; color:#f5dfb4; background:var(--brick); font:700 15px 'Fraunces', serif; }
  .draw-face { color:var(--ink); background:#EEE8D8; transform:rotateY(180deg); }
  .draw-crown { position:absolute; left:50%; top:-40px; z-index:5; opacity:0; color:#f4dc78;
    filter:drop-shadow(0 0 8px rgba(244,220,120,.9)); font:36px/1 'Fraunces', serif; transform:translateX(-50%) scale(.5); }
  .draw-photo { height:140px; overflow:hidden; background:#cfd6d3; }
  .draw-photo img, .draw-photo svg { width:100%; height:100%; display:block; object-fit:cover; }
  .draw-tab { position:absolute; top:0; right:0; padding:6px 11px; color:#fff; background:var(--reveal);
    font:700 9px 'IBM Plex Mono', monospace; letter-spacing:.12em; }
  .draw-stage.q-common .draw-tab { color:#343837; box-shadow:inset 0 0 0 1px #aaa69b; }
  .draw-copy { padding:12px 12px 10px; }
  .draw-copy strong { display:block; font:700 15px/1.1 'Fraunces', serif; }
  .draw-copy small { display:block; margin-top:4px; color:#995442; font:8px 'IBM Plex Mono', monospace; letter-spacing:.08em; }
  .draw-copy b { display:block; margin-top:10px; font:600 17px 'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }

  .draw-progress { height:4px; overflow:hidden; background:#d2cab6; }
  .draw-progress i { display:block; width:100%; height:100%; background:var(--gold); transform:scaleX(0); transform-origin:left; }
  .draw-result { min-height:64px; padding-top:12px; text-align:center; opacity:0; transform:translateY(7px); }
  .draw-result .kicker { margin:0 0 2px; color:var(--reveal); font:700 10px 'IBM Plex Mono', monospace; letter-spacing:.14em; }
  .draw-result .title { margin:0; font:700 21px/1.1 'Fraunces', serif; }
  .draw-result .detail { margin:5px 0 0; color:#6c6454; font:13px 'Fraunces', serif; }
  .draw-result .verdict { display:inline-block; margin-top:6px; padding:2px 8px; border:1px solid currentColor;
    font:600 11px 'IBM Plex Mono', monospace; }
  .draw-result .verdict.up { color:var(--gain); }
  .draw-result .verdict.down { color:var(--loss); }
  .draw-close { display:flex; justify-content:center; gap:10px; padding-top:12px; }

  .draw-stage.playing .draw-rule i { animation:dw-rule .7s .28s ease-out forwards; }
  .draw-stage.playing .draw-debit { animation:dw-debit .36s .5s ease-out forwards; }
  .draw-stage.playing .draw-progress i { animation:dw-progress 4.7s .2s linear forwards; }
  .draw-stage.playing .draw-ghost.a { animation:dw-shuffle-a 2.35s 1s ease-in-out forwards; }
  .draw-stage.playing .draw-ghost.b { animation:dw-shuffle-b 2.35s 1.05s ease-in-out forwards; }
  .draw-stage.playing .draw-ghost.c { animation:dw-shuffle-c 2.35s 1.1s ease-in-out forwards; }
  .draw-stage.playing .draw-chosen { animation:dw-jostle 2.2s 1.05s ease-in-out; }
  .draw-stage.playing .draw-orbit { animation:dw-orbit-build 3.25s 1.25s cubic-bezier(.2,.6,.2,1) forwards; }
  .draw-stage.playing .draw-orbit span { animation:dw-orbit-spin 1.7s 1.2s linear infinite; }
  .draw-stage.revealed .draw-chosen { animation:dw-flip .72s cubic-bezier(.3,.7,.25,1) forwards; }
  .draw-stage.revealed .draw-orbit { animation:dw-orbit-resolve 1s ease-out forwards; }
  .draw-stage.revealed .draw-flare { animation:dw-flash .48s ease-out; }
  .draw-stage.revealed .draw-result { animation:dw-result .38s .5s ease-out forwards; }
  .draw-stage.revealed .draw-face { box-shadow:inset 0 0 0 4px color-mix(in srgb,var(--reveal) 72%,white); }
  .draw-stage.revealed .draw-spark { animation:dw-spark var(--life) var(--delay) cubic-bezier(.18,.68,.25,1) forwards; }
  .draw-stage.q-common.revealed .draw-orbit { animation-duration:.72s; }
  .draw-stage.q-common.revealed .draw-flare { animation-duration:.26s; }
  .draw-stage.q-common.revealed .draw-chosen { animation-duration:.58s; }
  .draw-stage.q-common.revealed .draw-result .kicker { color:#656a67; }
  .draw-stage.q-uncommon.revealed .draw-orbit { animation-duration:.82s; filter:drop-shadow(0 0 10px rgba(142,151,159,.72)); }
  .draw-stage.q-uncommon.revealed .draw-flare { animation-duration:.36s; }
  .draw-stage.q-rare.revealed .draw-orbit { filter:drop-shadow(0 0 16px rgba(176,140,30,.78)); }
  .draw-stage.q-rare.revealed .draw-face { animation:dw-rare-pulse .9s .56s ease-out; }
  .draw-stage.q-ultra.revealed .draw-orbit { animation:dw-ultra-orbit 1.08s ease-out forwards; filter:drop-shadow(0 0 18px rgba(180,52,46,.86)); }
  .draw-stage.q-ultra.revealed .draw-flare { animation:dw-ultra-flash .62s ease-out; }
  .draw-stage.q-ultra.revealed .draw-chosen { animation:dw-ultra-flip .78s cubic-bezier(.27,.72,.22,1) forwards; }
  .draw-stage.q-secret.revealed .draw-orbit { animation:dw-legend-orbit 1.25s ease-out forwards; filter:drop-shadow(0 0 19px rgba(122,90,168,.88)); }
  .draw-stage.q-secret.revealed .draw-halo { animation:dw-halo 1.3s .08s ease-out forwards; }
  .draw-stage.q-secret.revealed .draw-flare { animation:dw-legend-flash .75s ease-out; }
  .draw-stage.q-secret.revealed .draw-chosen { animation:dw-legend-flip .86s cubic-bezier(.25,.72,.2,1) forwards; }
  .draw-stage.q-secret.revealed .draw-crown { animation:dw-crown .7s .62s cubic-bezier(.2,.85,.3,1.3) forwards; }
  .draw-stage.q-secret.revealed .draw-result { animation-delay:.65s; }

  @keyframes dw-rule { to { transform:scaleX(1); } }
  @keyframes dw-debit { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:none; } }
  @keyframes dw-progress { to { transform:scaleX(1); } }
  @keyframes dw-shuffle-a { 0% { opacity:0; transform:translateX(-130px) rotate(-13deg); } 14%,70% { opacity:1; } 30% { transform:translateX(125px) rotate(10deg); } 55% { transform:translateX(-90px) rotate(-8deg); } 100% { opacity:0; transform:translateX(150px) rotate(13deg) scale(.88); } }
  @keyframes dw-shuffle-b { 0% { opacity:0; transform:translateX(140px) rotate(12deg); } 14%,70% { opacity:.9; } 34% { transform:translateX(-120px) rotate(-11deg); } 60% { transform:translateX(85px) rotate(7deg); } 100% { opacity:0; transform:translateX(-145px) rotate(-12deg) scale(.88); } }
  @keyframes dw-shuffle-c { 0% { opacity:0; transform:translateY(-85px) rotate(-4deg); } 14%,70% { opacity:.82; } 35% { transform:translateY(55px) rotate(5deg); } 65% { transform:translateY(-45px) rotate(-4deg); } 100% { opacity:0; transform:translateY(105px) scale(.86); } }
  @keyframes dw-jostle { 0%,100% { transform:translateY(0) rotate(0); } 24% { transform:translateY(5px) rotate(2deg); } 49% { transform:translateY(-3px) rotate(-2deg); } 72% { transform:translateY(3px) rotate(1deg); } }
  @keyframes dw-orbit-build { 0% { opacity:.1; transform:rotate(0) scale(.72); filter:blur(4px); } 70% { opacity:.62; } 100% { opacity:.82; transform:rotate(320deg) scale(1); filter:blur(.4px); } }
  @keyframes dw-orbit-spin { to { transform:rotate(360deg); } }
  @keyframes dw-flip { 0% { transform:rotateY(0) scale(1); } 44% { transform:rotateY(90deg) scale(1.06); } 100% { transform:rotateY(180deg) scale(1); box-shadow:0 0 0 3px var(--reveal),0 0 28px color-mix(in srgb,var(--reveal) 58%,transparent),0 18px 35px rgba(32,27,18,.34); } }
  @keyframes dw-orbit-resolve { 0% { opacity:.85; transform:rotate(320deg) scale(1); } 30% { background:var(--reveal); opacity:.95; } 100% { background:var(--reveal); opacity:.18; transform:rotate(430deg) scale(1.28); filter:blur(8px); } }
  @keyframes dw-flash { 0% { opacity:0; transform:scale(.25); } 35% { opacity:1; transform:scale(4); } 100% { opacity:0; transform:scale(12); } }
  @keyframes dw-result { to { opacity:1; transform:none; } }
  @keyframes dw-spark { 0% { opacity:0; transform:translate(-50%,-50%) scale(.2) rotate(0); } 16% { opacity:1; } 76% { opacity:.95; } 100% { opacity:0; transform:translate(calc(-50% + var(--x)),calc(-50% + var(--y))) scale(.08) rotate(var(--spin)); } }
  @keyframes dw-rare-pulse { 0%,100% { filter:none; } 42% { filter:brightness(1.16) drop-shadow(0 0 13px rgba(176,140,30,.75)); transform:rotateY(180deg) scale(1.035); } }
  @keyframes dw-ultra-orbit { 0% { opacity:.88; transform:rotate(320deg) scale(1); } 28% { background:conic-gradient(#B4342E,#fff,#7e1720,#f2b5b8,#B4342E); opacity:1; } 100% { background:conic-gradient(#B4342E,#fff,#7e1720,#f2b5b8,#B4342E); opacity:.24; transform:rotate(500deg) scale(1.38); filter:blur(9px); } }
  @keyframes dw-ultra-flash { 0% { opacity:0; transform:scale(.2); } 26% { opacity:1; transform:scale(4.5); box-shadow:0 0 32px 15px #fff,0 0 88px 48px #B4342E; } 100% { opacity:0; transform:scale(14); box-shadow:0 0 38px 20px #fff,0 0 110px 66px #7e1720; } }
  @keyframes dw-ultra-flip { 0% { transform:rotateY(0) scale(1); } 42% { transform:rotateY(90deg) scale(1.09); } 100% { transform:rotateY(180deg) scale(1); box-shadow:0 0 0 4px #d9575e,0 0 35px 8px rgba(180,52,46,.6),0 19px 36px rgba(32,27,18,.38); } }
  @keyframes dw-legend-orbit { 0% { opacity:.9; transform:rotate(320deg) scale(1); } 25% { background:conic-gradient(#7A5AA8,#f3da70,#fff,#7A5AA8); opacity:1; } 100% { background:conic-gradient(#7A5AA8,#f3da70,#fff,#7A5AA8); opacity:.28; transform:rotate(560deg) scale(1.45); filter:blur(10px); } }
  @keyframes dw-halo { 0% { opacity:0; transform:rotate(-35deg) scale(.55); } 28% { opacity:1; } 100% { opacity:0; transform:rotate(165deg) scale(1.22); } }
  @keyframes dw-legend-flash { 0% { opacity:0; transform:scale(.2); } 22% { opacity:1; transform:scale(5); box-shadow:0 0 35px 18px #fff,0 0 95px 58px #7A5AA8; } 48% { opacity:.72; } 100% { opacity:0; transform:scale(16); box-shadow:0 0 35px 18px #fff,0 0 120px 75px #f3da70; } }
  @keyframes dw-legend-flip { 0% { transform:rotateY(0) scale(1); } 38% { transform:rotateY(90deg) scale(1.12); } 72% { transform:rotateY(180deg) scale(1.065); } 100% { transform:rotateY(180deg) scale(1); box-shadow:0 0 0 4px #f0d66e,0 0 0 8px rgba(122,90,168,.72),0 0 46px 13px rgba(122,90,168,.62),0 20px 38px rgba(32,27,18,.4); } }
  @keyframes dw-crown { 0% { opacity:0; transform:translateX(-50%) translateY(14px) scale(.45); } 60% { opacity:1; transform:translateX(-50%) translateY(-5px) scale(1.18); } 100% { opacity:1; transform:translateX(-50%) translateY(0) scale(1); } }

  @media (max-width: 760px) {
    .lotto-bar { flex-wrap:wrap; padding:12px 14px; gap:10px; }
    .lotto-copy { flex:1 1 100%; order:2; }
    .lotto-ticket { order:1; }
    .btn.lotto-go { order:3; flex:1 1 100%; }
    .draw-stage { padding:16px 12px 14px; }
    .draw-space { grid-template-columns:1fr 1fr; gap:8px; }
    .draw-machine { grid-column:1 / -1; grid-row:1; height:270px; }
    .draw-side { min-height:140px; padding:11px 9px; }
    .draw-side strong { font-size:15px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .draw-stage.playing *, .draw-stage.revealed * { animation-duration:.001ms !important; animation-delay:0ms !important; }
  }

  /* ---- the interception (theft tactic) --------------------------------
     Ported from the motion study, repainted in the exchange's palette and
     cut down: no ticker, no game bar, no map paper — this plays inside the
     app, which already provides all three. The beat that matters is kept
     exactly: the outcome stays hidden through four seconds of shared
     suspense and is only revealed by the seal coming down, so a win and a
     loss are indistinguishable until the last moment. The server decided
     before any of it started. */
  .thf-overlay { position:fixed; inset:0; z-index:80; display:grid; place-items:center; padding:16px;
    background:rgba(20,26,23,.74); backdrop-filter:blur(2px); overflow:auto; }
  .thf-card { position:relative; width:min(760px,100%); padding:20px 22px 16px; background:#F3EFE2;
    border:1px solid #887f68; outline:1px solid rgba(255,255,255,.3); outline-offset:-6px;
    box-shadow:0 30px 70px rgba(10,17,15,.5); animation:thf-arrive .45s cubic-bezier(.2,.75,.25,1) both; }
  .thf-head { display:flex; align-items:flex-start; justify-content:space-between; gap:14px;
    padding-bottom:10px; border-bottom:1px solid #bbb198; }
  .thf-no { display:block; margin-bottom:4px; color:var(--brick); font:11px 'IBM Plex Mono', monospace; letter-spacing:.12em; }
  .thf-head h2 { margin:0; font:700 23px/1.05 'Fraunces', serif; }
  .thf-timer { padding:5px 9px; border:1px solid #b3a988; color:#5d574a; background:rgba(233,228,212,.7);
    font:600 13px 'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }
  .thf-status { min-height:22px; margin:10px 0 4px; color:#5d574a; text-align:center; font:italic 15px/1.4 'Fraunces', serif; }

  .thf-exchange { display:grid; grid-template-columns:1fr 1.5fr 1fr; align-items:center; gap:12px; min-height:210px; }
  .thf-acct { padding:13px 12px; border:1px solid #c0b69e; background:rgba(233,228,212,.72); text-align:center; }
  .thf-acct .who { display:block; margin-bottom:6px; color:#817760; font:10px 'IBM Plex Mono', monospace; letter-spacing:.11em; }
  .thf-acct .name { display:block; font:700 14px 'Fraunces', serif; margin-bottom:4px; }
  .thf-acct .bal { display:block; font:600 17px 'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }
  .thf-acct .delta { display:block; height:20px; margin-top:5px; opacity:0; font:600 12.5px 'IBM Plex Mono', monospace; }
  .thf-acct .delta.up { color:var(--gain); } .thf-acct .delta.down { color:var(--loss); }
  .thf-avatar { width:40px; height:40px; margin:0 auto 8px; display:grid; place-items:center; border-radius:50%;
    color:#f1ead6; background:var(--forest); font:700 14px 'Fraunces', serif; }

  .thf-route { position:relative; height:190px; display:grid; place-items:center; }
  .thf-line { position:absolute; left:6%; right:6%; top:50%; height:3px; background:#d0c7b1; overflow:hidden; }
  .thf-line i { display:block; width:100%; height:100%; background:var(--forest); transform:scaleX(0); transform-origin:left; }
  .thf-cp { position:absolute; top:50%; transform:translate(-50%,-50%); text-align:center; }
  .thf-cp span { width:22px; height:22px; display:grid; place-items:center; margin:0 auto; border-radius:50%;
    border:1px solid #b3a988; background:#F3EFE2; color:#7a715c; font:600 10px 'IBM Plex Mono', monospace; }
  .thf-cp small { display:block; margin-top:4px; color:#8a806a; font:8px 'IBM Plex Mono', monospace; letter-spacing:.1em; }
  .thf-cp.c1 { left:6%; } .thf-cp.c2 { left:50%; } .thf-cp.c3 { left:94%; }
  .thf-order { position:absolute; left:6%; top:50%; z-index:3; width:34px; height:44px; margin-top:-22px;
    border:1px solid #84795f; background:#e9e2cd; box-shadow:0 6px 12px rgba(32,27,18,.25); }
  .thf-order::before { content:""; position:absolute; inset:6px 5px auto 5px; height:2px; background:#a89b7c;
    box-shadow:0 5px 0 #a89b7c, 0 10px 0 #a89b7c, 0 15px 0 #bcb197; }
  .thf-order i { position:absolute; right:3px; bottom:3px; width:13px; height:13px; border-radius:50%;
    display:grid; place-items:center; background:var(--brick); color:#f5dfb4; font:700 7px 'Fraunces', serif; }
  .thf-beam { position:absolute; left:50%; top:50%; width:3px; height:74px; margin-top:-37px; opacity:0; z-index:2;
    background:linear-gradient(#b08c1e00, #B08C1E, #b08c1e00); box-shadow:0 0 12px 3px rgba(176,140,30,.5); }
  /* ABOVE THE LINE, NOT ON IT. The stamp sat dead centre and the middle
     checkpoint sits dead centre, so the verdict landed on top of the
     marker and neither could be read. It is the loudest thing in the
     sequence and it was the one thing obscured. */
  .thf-stamp { position:absolute; left:50%; top:16%; z-index:5; transform:translate(-50%,-50%); opacity:0;
    padding:6px 12px; border:3px double var(--brick); color:var(--brick); white-space:nowrap;
    background:rgba(243,239,226,.9);
    font:700 15px 'IBM Plex Mono', monospace; letter-spacing:.08em; }
  .thf-coins { position:absolute; inset:0; z-index:4; pointer-events:none; }
  .thf-coin { position:absolute; right:8%; top:50%; width:11px; height:11px; border-radius:50%; opacity:0;
    background:radial-gradient(circle at 34% 32%, #f4dc78, #B08C1E 62%, #7A6115);
    box-shadow:0 0 5px rgba(176,140,30,.7); }

  .thf-vault { position:relative; width:56px; height:56px; margin:0 auto 8px; perspective:340px; }
  .thf-door { position:absolute; inset:0; transform-origin:left center; border:2px solid #4a5450; border-radius:5px;
    background:linear-gradient(140deg,#8d979a,#5f6b6d 62%,#48524f); box-shadow:inset 0 0 0 3px rgba(255,255,255,.14); }
  .thf-wheel { position:absolute; left:50%; top:50%; width:22px; height:22px; margin:-11px 0 0 -11px;
    border:2px solid #cfd6d4; border-radius:50%; }
  .thf-wheel i { position:absolute; left:50%; top:50%; width:2px; height:20px; margin:-10px 0 0 -1px; background:#cfd6d4; }
  .thf-wheel i:nth-child(2) { transform:rotate(45deg); }
  .thf-wheel i:nth-child(3) { transform:rotate(90deg); }
  .thf-wheel i:nth-child(4) { transform:rotate(135deg); }
  .thf-glow { position:absolute; inset:0; border-radius:5px; opacity:0; background:radial-gradient(circle,#f4dc78,transparent 66%); }

  .thf-result { min-height:62px; padding-top:12px; text-align:center; opacity:0; transform:translateY(7px); }
  .thf-result .kicker { margin:0 0 2px; font:700 10px 'IBM Plex Mono', monospace; letter-spacing:.14em; }
  .thf-result .title { margin:0; font:700 21px/1.1 'Fraunces', serif; }
  .thf-result .detail { margin:5px 0 0; color:#6c6454; font:13px/1.45 'Fraunces', serif; }
  .thf-card.won .thf-result .kicker { color:var(--gain); }
  .thf-card.lost .thf-result .kicker { color:var(--loss); }
  .thf-close { display:flex; justify-content:center; padding-top:12px; }

  /* THREE BEATS, AND THE TIMINGS HANG OFF THE CARD ITSELF.

     The phase class changes under this element every beat — running, then
     at-vault, then settled — so anything keyed to `.running` would be torn
     off mid-flight at 950ms. The approach therefore runs on `.thf-card`
     with `both`, which starts once when the card mounts and stays put. */

  /* Beat one, the approach: the route draws and the crew walks it. */
  .thf-card .thf-line i { animation:thf-fill .88s .06s cubic-bezier(.4,0,.5,1) both; }
  .thf-card .thf-order { animation:thf-route .88s .06s cubic-bezier(.4,0,.5,1) both; }
  .thf-card .thf-cp.c1 span { animation:thf-check .26s .2s ease-out both; }
  .thf-card .thf-cp.c2 span { animation:thf-check .26s .62s ease-out both; }

  /* Beat two, the attempt. The wheel turns; against a guarded property it
     catches and has to be worked, which is the one thing the player learns
     before the answer. */
  .thf-card.at-vault .thf-wheel { animation:thf-work .72s ease-in-out both; }
  .thf-card.at-vault.lost .thf-wheel { animation:thf-resist .72s ease-in-out both; }
  .thf-card.at-vault .thf-beam { animation:thf-scan .6s .05s ease-in-out both; }

  /* Beat three, the outcome — and the three have to look nothing alike. */
  .thf-card.settled .thf-cp.c3 span { animation:thf-check .26s ease-out both; }
  .thf-card.settled .thf-stamp { animation:thf-impact .3s .1s ease-out both; }
  .thf-card.settled .thf-result { animation:thf-in .36s .12s ease-out forwards; }
  .thf-card.settled .delta { animation:thf-in .36s .12s ease-out forwards; }

  /* Cleared: the door swings and the money comes home along the route. */
  .thf-card.won.settled .thf-door { animation:thf-open .62s cubic-bezier(.3,.7,.25,1) forwards; }
  .thf-card.won.settled .thf-glow { animation:thf-glow .8s .1s ease-out forwards; }
  .thf-card.won.settled .thf-coin { animation:thf-coin var(--life) var(--delay) cubic-bezier(.3,.5,.4,1) forwards; }

  /* Stopped: the door holds. The alarm is the loudest thing in the
     sequence because being caught should be the loudest thing that can
     happen to you. */
  .thf-card.lost.settled .thf-vault { animation:thf-shake .4s ease-in-out; }
  .thf-card.lost.settled .thf-door { animation:thf-refuse .8s ease-out; }
  .thf-card.lost.settled .thf-glow { animation:thf-alarm .9s ease-out forwards;
    background:radial-gradient(circle,#e05a4a,transparent 66%); }
  .thf-card.lost.settled .thf-line i { background:var(--loss); }
  .thf-card.lost.settled .thf-stamp { border-color:var(--loss); color:var(--loss); }
  /* A GREEN TICK IS THE STRONGEST CLAIM ON THE CARD, AND IT WAS LYING.

     The seal checked on `.settled` whatever had happened, so a botched job
     finished with a red route, a STOPPED stamp — and three green ticks
     reading 1, 2, 3 all clear. Green ticks beat every other signal on a
     page; a reader who takes only the route away from this card took away
     the opposite of the truth. The seal is never reached on a failure, so
     it does not close. */
  .thf-card.lost.settled .thf-cp.c3 span { animation:thf-halt .26s ease-out both; }

  /* Empty: the door opens on nothing at all. No glow, no coins, no colour.
     It is the funniest of the three outcomes and dressing it up would be
     the surest way to spoil it — the joke is the anticlimax. */
  .thf-card.empty.settled .thf-door { animation:thf-open .62s cubic-bezier(.3,.7,.25,1) forwards; }
  .thf-card.empty.settled .thf-vault { filter:grayscale(.5) brightness(.92); }
  .thf-card.empty.settled .thf-stamp { border-color:#8b8271; color:#8b8271; }
  .thf-card.empty .thf-result .kicker { color:#8b8271; }

  @keyframes thf-arrive { from { opacity:0; transform:translateY(20px) scale(.985); } to { opacity:1; transform:none; } }
  @keyframes thf-fill { to { transform:scaleX(1); } }
  /* THE ORDER IS DELIVERED, NOT PARKED.

     It used to finish at left:94% and stay there — which is exactly where
     the third checkpoint sits, and the order is 35px of opaque paper at
     z-index 3. So from 0.94s onward the SEAL marker was underneath it, and
     when the seal finally checked at 2.60s it checked invisibly: the one
     frame that says the job is closed, hidden by the envelope that closed
     it. It now hands itself over as it arrives, which also gives beat one
     an ending instead of a stop. */
  @keyframes thf-route { 0% { left:6%; transform:translateY(0) rotate(0); opacity:1; } 48% { left:50%; transform:translateY(-7px) rotate(3deg); opacity:1; } 84% { opacity:1; } 100% { left:94%; transform:translateY(-3px) rotate(-2deg); opacity:0; } }
  @keyframes thf-scan { 0% { opacity:0; transform:translateX(-24px); } 15%,85% { opacity:1; } 100% { opacity:0; transform:translateX(26px); } }
  @keyframes thf-check { 50% { color:#fff; background:var(--gold); border-color:var(--gold); transform:scale(1.35); } 100% { color:#fff; background:var(--forest); border-color:var(--forest); transform:scale(1); } }
  /* Stands alone now. It used to begin where thf-wait ended — the stamp
     hovering at 30% opacity for two seconds waiting to learn what it said. */
  @keyframes thf-impact { 0% { opacity:0; transform:translate(-50%,-50%) translateY(-30px) rotate(-9deg) scale(1.5); } 55% { opacity:1; transform:translate(-50%,-50%) translateY(4px) rotate(-9deg) scale(.88); } 100% { opacity:1; transform:translate(-50%,-50%) rotate(-9deg) scale(1); } }
  @keyframes thf-open { to { transform:rotateY(-105deg); } }
  /* The seal refusing to close: it recoils rather than stamping. */
  @keyframes thf-halt { 50% { transform:scale(1.2); } 100% { color:#fff; background:var(--loss); border-color:var(--loss); transform:scale(1); } }
  @keyframes thf-spin { to { transform:rotate(180deg); } }
  /* The wheel being turned, and the wheel refusing to be. */
  @keyframes thf-work { 0% { transform:rotate(0); } 100% { transform:rotate(200deg); } }
  @keyframes thf-resist { 0% { transform:rotate(0); } 28% { transform:rotate(58deg); }
    38% { transform:rotate(44deg); } 62% { transform:rotate(96deg); }
    72% { transform:rotate(84deg); } 100% { transform:rotate(104deg); } }
  @keyframes thf-alarm { 0% { opacity:0; transform:scale(.6); } 18% { opacity:.95; }
    46% { opacity:.3; } 64% { opacity:.85; } 100% { opacity:0; transform:scale(2); } }
  @keyframes thf-glow { 30% { opacity:.9; transform:scale(1.4); } 100% { opacity:0; transform:scale(2.2); } }
  @keyframes thf-coin { 0% { opacity:0; transform:translate(0,0) scale(.6) rotate(0); } 16% { opacity:1; } 100% { opacity:0; transform:translate(calc(-1 * var(--travel)), var(--arc)) scale(1) rotate(-460deg); } }
  @keyframes thf-refuse { 0%,100% { filter:none; } 50% { filter:brightness(.55) sepia(.6) saturate(2); } }
  @keyframes thf-shake { 0%,100% { transform:translateX(0); } 25% { transform:translateX(-5px); } 50% { transform:translateX(4px); } 75% { transform:translateX(-2px); } }
  @keyframes thf-in { to { opacity:1; transform:translateY(0); } }

  @media (max-width: 760px) {
    .thf-card { padding:16px 12px 14px; }
    .thf-exchange { grid-template-columns:1fr 1fr; gap:9px; }
    .thf-route { grid-column:1 / -1; grid-row:1; height:150px; }
    .thf-acct { padding:10px 8px; }
    .thf-acct .bal { font-size:14px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .thf-card, .thf-card *, .thf-card.at-vault *, .thf-card.settled * {
      animation-duration:.001ms !important; animation-delay:0ms !important; }
  }

  /* ---- honours -------------------------------------------------------
     A shelf rather than a list: the crests are meant to be scanned in a
     second when you open somebody's profile, with the detail on hover for
     anyone who wants it. Tier decides how loud one is, so a landmark does
     not sit at the same volume as a first purchase. */
  .honours { margin:4px 0 16px; padding:12px 12px 10px; border:1px solid var(--line);
    border-radius:4px; background:linear-gradient(180deg, rgba(176,140,30,.07), rgba(176,140,30,0) 60%), var(--paper); }
  .honours.none { background:var(--paper); }
  .honours-head { display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 10px; margin-bottom:10px; }
  .honours-head h3 { font-family:'Fraunces', serif; font-size:16px; margin:0; }
  .honours-count { font-family:'IBM Plex Mono', monospace; font-size:10.5px; letter-spacing:0.1em; color:#6b6455; }
  .honours-tally { display:flex; gap:10px; margin-left:auto; font-size:11px; color:#6b6455; }
  .honours-tally .ht { display:inline-flex; align-items:center; gap:4px; }
  .honours-tally i { width:9px; height:9px; border-radius:50%; display:inline-block; }
  .ht1 i { background:radial-gradient(circle at 35% 30%, #F4F6F7, #7F888F); }
  .ht2 i { background:radial-gradient(circle at 35% 30%, #FBEFC4, #9C7A14); }
  .ht3 i { background:radial-gradient(circle at 35% 30%, #C8443C, #701A16); box-shadow:0 0 0 1.5px #D9B24A; }
  .honours-empty { font-size:12.5px; color:#8b8471; font-style:italic; margin:0; }
  .medal-row { display:grid; grid-template-columns:repeat(auto-fill, minmax(92px, 1fr)); gap:12px 8px; }
  .medal { position:relative; display:flex; flex-direction:column; align-items:center; text-align:center;
    gap:3px; padding:4px 2px 2px; border-radius:4px; cursor:default; min-width:0;
    transition:transform .18s ease; }
  .medal:hover { transform:translateY(-2px); }
  .medal-svg { display:block; filter:drop-shadow(0 2px 2px rgba(40,30,10,.28)); }
  .medal.t3 .medal-svg { filter:drop-shadow(0 2px 3px rgba(112,26,22,.35)) drop-shadow(0 0 6px rgba(217,178,74,.35)); }
  .medal-name { font-size:11.5px; font-weight:600; line-height:1.2; max-width:100%; overflow-wrap:anywhere; }
  .medal.t2 .medal-name { color:#6E5714; }
  .medal.t3 .medal-name { color:#8E2A24; }
  .medal-when { font-family:'IBM Plex Mono', monospace; font-size:9.5px; color:#8b8471; line-height:1.25; }
  .medal-times { position:absolute; top:22px; right:calc(50% - 30px); font-size:10px; background:#7E1F1B;
    color:#FBEBC4; border:1px solid #D9B24A; border-radius:9px; padding:0 5px; line-height:15px; }
  .medal.locked { opacity:.42; filter:grayscale(1); }
  .medal.locked:hover { opacity:.7; transform:none; }
  .medal.locked .medal-name { color:inherit; font-weight:500; }
  .medal.locked .medal-when { font-family:inherit; font-size:10px; }
  .medal-row.locked { margin-top:8px; padding-top:10px; border-top:1px dashed var(--line); }
  .honours-more { margin-top:10px; background:none; border:0; padding:2px 0; font-size:11.5px; color:#6b6455;
    text-decoration:underline; text-underline-offset:2px; cursor:pointer; }
  .honours-more:focus-visible { outline:2px solid #B08C1E; outline-offset:2px; }
  @media (prefers-reduced-motion: reduce) { .medal { transition:none; } .medal:hover { transform:none; } }
  .map-desk .honours, .map-side .honours { background:rgba(233,228,212,.06); border-color:#3a5349; }
  .map-side .medal-name, .map-side .honours-head h3 { color:#e7e1cf; }
  .map-side .medal.t2 .medal-name { color:#E6C76A; }
  .map-side .medal.t3 .medal-name { color:#E48A80; }

/* ---- the desk: grouped repeats ---------------------------------------- */
.notif-row.grouped { cursor:pointer; align-items:flex-start; }
.notif-row.grouped:hover { background:rgba(176,140,30,.05); }
.notif-row.grouped:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }
.notif-sub { font-size:11px; color:var(--muted); margin-top:3px;
  font-variant-numeric:tabular-nums; }
.notif-count { display:inline-block; padding:0 5px; border-radius:8px;
  background:rgba(176,140,30,.16); border:1px solid rgba(176,140,30,.4);
  color:var(--gold); font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:10.5px; }
.notif-caret { margin-left:6px; opacity:.65; }
.notif-row.child { padding-left:22px; border-bottom:1px dotted var(--line);
  font-size:12px; color:var(--muted); }
.desk-toggle { display:flex; align-items:center; justify-content:space-between;
  gap:10px; flex-wrap:wrap; padding:0 0 8px; margin-bottom:2px;
  border-bottom:1px solid var(--line); font-size:12px; }

/* ---- Map V3: the real city -------------------------------------------- */
.city-map { display:block; width:100%; height:auto; touch-action:none; }

/* Territory: the whole point is that it responds. A segment you can take has
   to look takeable before you click it. Emphasis multiplies the drawn
   opacity rather than replacing it, so hover and selection both respect the
   fade that thins the wash as you zoom in. */
.terr { cursor:pointer; fill-opacity:var(--op);
  transition:fill-opacity .16s ease, stroke-width .16s ease; }
.terr:focus { outline:none; }
/* The hover value is computed where the fade is, and arrives as --hop. CSS
   cannot see the zoom, so every attempt to express this as a multiple or a
   floor of --op was wrong at one end of the scale or the other. */
.terr:hover, .terr:focus-visible {
  fill-opacity:var(--hop); stroke-width:4; stroke-opacity:1; }
.terr.sel { stroke-width:3; stroke-opacity:1; }
/* The chosen district keeps its outline and drops the hover entirely: --hop
   equals --op for it, and the stroke stays where selection put it. */
.terr.sel:hover, .terr.sel:focus-visible { stroke-width:3; }
.prop { cursor:pointer; }
.prop:focus { outline:none; }
/* The casing is drawn first, so the hover reaches for the shape by name
   (29 Sep 2026), and the casing brightens to a gold rim instead. */
.prop:hover .prop-shape, .prop:focus-visible .prop-shape { filter:brightness(1.18); }
.prop:hover .prop-case, .prop:focus-visible .prop-case { stroke:#E8C75A; fill:#E8C75A; }
@media (prefers-reduced-motion:reduce) { .terr { transition:none; } }

/* The trail. York is always the first step and always clickable, which alone
   replaces what the old FIT chip was for — in a place people already look. */
.map-crumbs { position:absolute; left:14px; top:14px; right:14px; z-index:4;
  display:flex; align-items:center; gap:8px; padding:6px 10px; border-radius:4px;
  background:rgba(14,28,21,.9); border:1px solid #2C4238; border-left:3px solid var(--gold); }
.map-crumbs ol { list-style:none; display:flex; align-items:center; gap:6px;
  margin:0; padding:0; flex:1; min-width:0; overflow:hidden; }
.map-crumbs li { display:flex; align-items:center; gap:6px; min-width:0; }
.map-crumbs li + li::before { content:"\203A"; color:#BCB8A6; font-size:13px; }
.map-crumbs .crumb { background:none; border:0; padding:0; cursor:pointer; color:var(--gold);
  font-family:inherit; font-size:13px; white-space:nowrap; text-underline-offset:3px; }
.map-crumbs .crumb:hover { text-decoration:underline; color:#E8CC61; }
.map-crumbs .here { font-family:'Fraunces',Georgia,serif; font-weight:700; font-size:14px;
  color:#E9E4D4; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* Gold and labelled. A bare grey arrow is furniture; this has to look like
   the thing you press, because the control it replaces went unclicked for
   exactly that reason. */
.crumb-back { flex:none; display:inline-flex; align-items:center; gap:5px; cursor:pointer;
  min-height:32px; padding:0 11px; border-radius:4px; border:1px solid #7A6115;
  background:var(--gold); color:#2A2410; font-family:inherit; font-weight:600;
  font-size:12.5px; line-height:1; }
.crumb-back:hover:not(:disabled) { background:#E8CC61; }
.crumb-back:active:not(:disabled) { transform:translateY(1px); }
.crumb-back:disabled { background:transparent; border-color:#2C4238; color:#BCB8A6;
  opacity:.45; cursor:default; }
.crumb-back:focus-visible { outline:2px solid #F2E3B0; outline-offset:2px; }
.map-scale { flex:none; font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:10px;
  color:#BCB8A6; letter-spacing:0.06em; white-space:nowrap; font-variant-numeric:tabular-nums; }

/* Zoom sits in the corner as a joined pair, so it reads as one control
   rather than a scatter of chips. */
.map-tools { position:absolute; right:14px; bottom:14px; display:flex; flex-direction:column;
  z-index:3; border:1px solid var(--gold); border-radius:4px; overflow:hidden; }
.map-tools button { width:32px; height:32px; padding:0; cursor:pointer; border:0;
  background:rgba(14,28,21,.92); color:#F2E3B0;
  font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:17px; line-height:1; }
.map-tools button + button { border-top:1px solid rgba(176,140,30,.5); }
.map-tools button:hover { background:var(--gold); color:#0E1C15; }
.map-tools button:focus-visible { outline:2px solid #F2E3B0; outline-offset:-2px; }

/* The key toggle used to sit top-left, which is where the trail now lives. */
/* The toggle sits ON the key it hides, not across the map from it. It was
   pinned to the right while the key was bottom-left, which made "Hide key"
   read as a control for something else entirely. */
.map-desk .map-keys-toggle { left:14px; right:auto; top:52px; }

.map-loading { display:flex; flex-direction:column; gap:6px; justify-content:center;
  align-items:center; text-align:center; min-height:320px; padding:24px;
  color:#ECE5D2; font-size:13px; line-height:1.55; }
.map-loading b { font-family:'Fraunces',Georgia,serif; font-size:16px; }

.key-mark.outline { background:transparent; border-style:solid; transform:none;
  width:10px; height:10px; }

/* "Nothing happened here" has no colour on the map, so it has no colour in
   the key either — an empty diamond, which is exactly what the district
   looks like. Painting a swatch for it would put a colour in the legend
   that the map never draws. */
.key-mark.key-none { background:transparent; border-color:rgba(255,255,255,.45);
  border-style:dashed; }

/* The field report's own furniture. */
.holder-note { display:flex; align-items:center; gap:7px; font-size:13px; margin:0 0 12px;
  padding:8px 10px; border:1px solid var(--desk-rule, #26413a); border-radius:2px; }
.holder-note i { width:10px; height:10px; border-radius:2px; flex:none; }
.stat-row { display:grid; grid-template-columns:repeat(3,1fr); gap:10px; margin:0 0 14px; }
.stat { border-left:2px solid var(--desk-rule, #26413a); padding-left:9px; }
.stat .l { font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:9.5px;
  letter-spacing:0.08em; color:#aeb2a5; text-transform:uppercase; display:block; }
.stat .v { font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:15px;
  font-variant-numeric:tabular-nums; color:#f4e9ca; }

/* Phones. Each change here is a thumb problem rather than a space problem:
   the zoom pair goes where a thumb reaches, every control clears the 44px
   touch target Apple and Google both ask for, and the trail keeps the back
   button and the current place while the scale readout — the one thing
   nobody taps — drops out. */
@media (max-width:760px) {
  .map-crumbs { left:8px; right:8px; top:8px; padding:5px 7px; gap:6px; }
  .crumb-back { min-height:40px; padding:0 13px; font-size:13px; }
  .map-crumbs .here { font-size:13px; }
  .map-crumbs .crumb { font-size:12.5px; }
  .map-scale { display:none; }
  .map-tools { right:10px; bottom:10px; }
  .map-tools button { width:44px; height:44px; font-size:20px; }
  .map-desk .map-keys-toggle { top:auto; bottom:14px; left:14px; right:auto;
    min-height:40px; display:inline-flex; align-items:center; }
  .stat-row { gap:6px; }
  .stat .v { font-size:13.5px; }
  .map-desk .map-side .cluster-row { padding:11px 0; }
}

/* ---- the watchlist ----------------------------------------------------- */
.fav-star { background:none; border:0; padding:2px; cursor:pointer; line-height:0;
  color:#a8a08a; flex:none; border-radius:3px; }
.fav-star:hover { color:var(--gold); }
.fav-star.on { color:var(--gold); }
.fav-star:focus-visible { outline:2px solid var(--gold); outline-offset:1px; }
.watchlist { border:1px solid var(--line); background:var(--paper-dark); padding:14px 16px;
  margin:0 0 16px; }
.watchlist h3 { margin:0 0 2px; }
.watch-row { display:flex; align-items:center; gap:9px; padding:7px 0; font-size:12.5px;
  border-bottom:1px solid var(--line); cursor:pointer; }
.watch-row:last-child { border-bottom:0; }
.watch-row:hover { background:rgba(176,140,30,.06); }
.watch-name { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.watch-price { font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-variant-numeric:tabular-nums; min-width:86px; text-align:right; }
.map-desk .map-side .watch-row { color:#e7e1cf; }

/* ---- confirming a purchase -------------------------------------------- */
.confirm-box { max-width:380px; }
.confirm-figures { display:grid; gap:6px; margin:0 0 16px; }
.confirm-figures div { display:flex; justify-content:space-between; align-items:baseline;
  gap:12px; padding:7px 10px; background:var(--paper-dark); border:1px solid var(--line); }
.confirm-figures span { font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--muted); }
.confirm-figures b { font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:15px;
  font-variant-numeric:tabular-nums; }
.confirm-actions { display:flex; gap:8px; flex-wrap:wrap; }

/* ---- the City Council -------------------------------------------------- */
.council-strip { display:flex; flex-wrap:wrap; gap:18px; padding:12px 16px; margin:0 0 16px;
  background:var(--paper-dark); border:1px solid var(--line); }
.council-strip > div { display:flex; flex-direction:column; gap:2px; }
.council-grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:16px;
  align-items:start; }
.council-card { border:1px solid var(--line); background:var(--paper-dark); padding:14px 16px;
  margin:0 0 16px; }
.council-card h4 { margin:0 0 4px; font-family:'Fraunces',Georgia,serif; font-size:15px; }
.council-card.filed { border-left:3px solid var(--gold); }

.field { display:block; margin:0 0 10px; }
.field > span { display:block; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--muted); margin-bottom:4px; }
.field > span em { text-transform:none; letter-spacing:0; font-style:normal; }
/* A name the player has to copy EXACTLY must be shown exactly. The label is
   uppercased, so "Type Shotwright to confirm" rendered as "TYPE SHOTWRIGHT TO
   CONFIRM" — telling somebody to type a string that is not their name. */
.field > span b { text-transform:none; font-weight:600; }
/* `input` belongs in this list too. It was missing, so every text and
   password box in the account panel fell back to the browser's own narrow
   default while the selects beside them filled the width. The panel looked
   half-built rather than broken, which is exactly why no assertion caught it
   — it took looking at the thing. */
.field select, .field textarea, .field input { width:100%; padding:7px 8px; border:1px solid var(--line);
  background:var(--paper); font-family:inherit; font-size:13px; color:inherit; }
.field select:focus-visible, .field textarea:focus-visible, .field input:focus-visible {
  outline:2px solid var(--gold); outline-offset:1px; }
.field textarea { resize:vertical; line-height:1.5; }

/* THE PRIVATE REPORT. What the building actually has, for its owner alone.
   Set apart from the form around it — different ground, a rule at the top —
   because it is evidence, not an input: the two drop-downs below are where
   the player answers it. */
.register { border:1px solid var(--line); border-top:2px solid var(--gold);
  background:rgba(184,151,74,.06); padding:10px 11px; margin:2px 0 12px; }
.register-kicker { display:block; font-size:9.5px; letter-spacing:.14em; color:var(--gold);
  margin-bottom:6px; }
.register-row { display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  font-size:12.5px; padding:2px 0; }
.register-row > span { color:var(--muted); }
.register-row > b { text-align:right; }
.register-foot { font-size:10.5px; color:var(--muted); margin-top:7px; font-style:italic; }

/* What this filing will pay, given what is currently in the drop-downs. It
   changes as they change, which is how a player discovers the stakes of a
   lie without ever being asked to declare one. */
.filing-stakes { margin-top:11px; padding:7px 9px; font-size:12px; border-radius:2px;
  text-align:center; }
.filing-stakes.true { background:rgba(47,107,69,.12); color:#2F6B45; }
.filing-stakes.false { background:rgba(176,52,42,.12); color:#B0342A; }

.filed-line { font-size:13.5px; margin:6px 0; }
.filed-note { font-style:italic; font-size:13px; color:var(--muted); margin:6px 0;
  padding-left:10px; border-left:2px solid var(--line); }
.filed-flag { font-size:12.5px; padding:7px 9px; margin-top:8px; border-radius:2px; }
.filed-flag.true { background:rgba(47,107,69,.12); color:#2F6B45; }
.filed-flag.false { background:rgba(176,52,42,.12); color:#B0342A; }

.dossier { border:1px solid var(--line); background:var(--paper); padding:12px 13px;
  margin:0 0 10px; }
.dossier.called { opacity:.72; }
.dossier-head { display:flex; justify-content:space-between; align-items:baseline; gap:10px;
  flex-wrap:wrap; }
.dossier-by { font-size:11.5px; color:var(--muted); margin-top:2px; }
.dossier-value { color:var(--muted); }
/* The two claims as a small ledger rather than a sentence. An auditor reads
   a dozen of these in a sitting and wants them in the same place every time. */
.dossier-claims { display:grid; grid-template-columns:auto 1fr; gap:2px 12px; margin:8px 0 0;
  font-size:12.5px; }
.dossier-claims > div { display:contents; }
.dossier-claims span { color:var(--muted); font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; align-self:center; }
.dossier-claims b { color:var(--gold); font-weight:600; }

.filed-claims { display:flex; flex-wrap:wrap; gap:6px; margin:6px 0 0; }
.filed-claims span { font-size:11.5px; color:var(--gold); border:1px solid var(--line);
  padding:3px 7px; }
.dossier-note { font-style:italic; font-size:12.5px; margin:7px 0 0; line-height:1.55;
  padding-left:10px; border-left:2px solid var(--line); }
.filer-record { font-family:'IBM Plex Mono',ui-monospace,monospace; font-size:10.5px;
  color:var(--muted); white-space:nowrap; }
.filer-record.new { font-style:italic; }
.dossier-actions { display:flex; gap:8px; margin-top:11px; }
.btn-certify, .btn-condemn { flex:1; display:flex; flex-direction:column; gap:2px; padding:7px 8px;
  border:1px solid; cursor:pointer; font-family:inherit; font-size:12.5px; font-weight:600; }
.btn-certify { border-color:#2F6B45; color:#2F6B45; background:rgba(47,107,69,.07); }
.btn-condemn { border-color:#B0342A; color:#B0342A; background:rgba(176,52,42,.07); }
.btn-certify:hover:not(:disabled) { background:#2F6B45; color:#fff; }
.btn-condemn:hover:not(:disabled) { background:#B0342A; color:#fff; }
.btn-certify:disabled, .btn-condemn:disabled { opacity:.4; cursor:default; }
.btn-certify small, .btn-condemn small { font-weight:400; font-size:10.5px; opacity:.85; }
.dossier-called { margin-top:10px; font-size:12px; padding:6px 8px; }
.dossier-called.certify { background:rgba(47,107,69,.12); color:#2F6B45; }
.dossier-called.condemn { background:rgba(176,52,42,.12); color:#B0342A; }

.settled-row, .ledger-row { display:flex; align-items:baseline; gap:9px; padding:6px 0;
  border-bottom:1px solid var(--line); font-size:12.5px; }
.settled-row:last-child, .ledger-row:last-child { border-bottom:0; }
.settled-what { flex:1; line-height:1.5; }
.pip { width:8px; height:8px; border-radius:50%; flex:none; margin-top:4px; }
.pip.good { background:#2F6B45; } .pip.bad { background:#B0342A; } .pip.quiet { background:#9a947f; }
.ledger-row span:first-child { min-width:36px; font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-variant-numeric:tabular-nums; }
.ledger-reason { flex:1; color:var(--muted); }

.perk { border-top:1px solid var(--line); padding:11px 0 12px; }
.perk:first-of-type { border-top:0; }
.perk-head { display:flex; justify-content:space-between; align-items:baseline; gap:10px; }
.perk-cost { font-family:'IBM Plex Mono',ui-monospace,monospace; color:var(--gold);
  font-size:13px; }
.perk-cost::after { content:" skill"; font-size:10px; color:var(--muted); }
.perk-blurb { font-size:12.5px; margin:4px 0 3px; line-height:1.5; }
.perk-note { font-size:11.5px; line-height:1.45; }
.perk-target { display:block; width:100%; margin:7px 0; padding:5px 7px;
  border:1px solid var(--line); background:var(--paper); font-family:inherit; font-size:12.5px; }
.perk .btn { margin-top:7px; }

@media (max-width:820px) {
  .council-grid { grid-template-columns:1fr; }
  .council-strip { gap:12px; font-size:12px; }
  .honesty-pick { grid-template-columns:1fr; }
  .dossier-actions { flex-direction:column; }
  .btn-certify, .btn-condemn { min-height:44px; flex-direction:row; align-items:baseline; gap:6px; }
}

/* ---- the pod ----------------------------------------------------------- */
.pod-strip { display:flex; flex-wrap:wrap; align-items:center; gap:7px; padding:9px 14px;
  margin:0 0 16px; background:var(--paper-dark); border:1px solid var(--line);
  border-left:3px solid var(--gold); font-size:12.5px; }
.pod-label { font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--muted); margin-right:3px; }
.pod-name { padding:2px 8px; border:1px solid var(--line); border-radius:11px;
  background:var(--paper); }
.pod-name.you { border-color:var(--gold); color:var(--gold); font-weight:600; }
.pod-warn { color:var(--loss); font-size:11.5px; }
.pod-redraw { margin-left:auto; font-size:11px; color:var(--muted); }

/* ---- the council resolution -------------------------------------------- */
/* Built to the motion pack's contract: 0.0–4.3s of suspense both outcomes
   share exactly, then a branch. The suspense animations hang off .res-stage
   itself rather than off a phase class, because the phase class changes at
   the reveal and an animation attached to the old class would snap its
   element back to the start at the worst possible moment. */
.res-overlay { position:fixed; inset:0; z-index:85; display:grid; place-items:center;
  padding:16px; background:rgba(8,12,10,.88); animation:res-in .25s ease-out; }
@keyframes res-in { from { opacity:0; } to { opacity:1; } }

.res-stage { --seal:#8a7e64; position:relative; width:min(940px,100%); max-height:94vh;
  overflow-y:auto; }
.res-stage.out-good { --seal:#2F6B45; }
.res-stage.out-bad { --seal:#A23E27; }
.res-stage.out-void { --seal:#7C7768; }

.res-card { position:relative; z-index:2; padding:22px 26px 18px; color:#20261F;
  background:#F3EFE2; border:1px solid #887f68; outline:1px solid rgba(255,255,255,.35);
  outline-offset:-7px; box-shadow:0 30px 70px rgba(10,17,15,.45);
  animation:res-card-arrive .45s cubic-bezier(.2,.75,.25,1) both; }
.res-card::before { content:""; position:absolute; inset:0; z-index:-1; opacity:.23;
  pointer-events:none; background-image:radial-gradient(#746b55 .55px,transparent .7px);
  background-size:4px 4px; }
@keyframes res-card-arrive {
  from { opacity:0; transform:translateY(14px) scale(.985); }
  to { opacity:1; transform:none; } }

.res-head { display:flex; align-items:flex-start; justify-content:space-between; gap:14px;
  padding-bottom:10px; border-bottom:1px solid #bbb198; }
.res-head h2 { margin:0; font:700 23px/1.05 'Fraunces',Georgia,serif; }
.res-no { display:block; margin-bottom:4px; color:#A23E27;
  font:11px 'IBM Plex Mono',ui-monospace,monospace; letter-spacing:.12em; }
.res-tools { display:flex; align-items:center; gap:8px; flex:none; }
.res-timer { padding:5px 9px; border:1px solid #b3a988; color:#5d574a;
  background:rgba(233,228,212,.7); font:12px 'IBM Plex Mono',ui-monospace,monospace;
  font-variant-numeric:tabular-nums; }
.res-mute { width:28px; height:28px; padding:0; cursor:pointer; border:1px solid #b3a988;
  background:rgba(233,228,212,.7); color:#5d574a; font-size:13px; line-height:1; }
.res-mute[aria-pressed="false"] { color:#a49a84; }
.res-mute:hover { border-color:#8a7e64; }

.res-status { min-height:22px; margin:12px 0 6px; color:#5d574a; text-align:center;
  font:italic 15px/1.4 'Fraunces',Georgia,serif; }

.res-scene { display:grid; grid-template-columns:150px 1fr 170px; align-items:center;
  gap:18px; min-height:215px; }
.res-desk { display:grid; justify-items:center; text-align:center; }
.res-avatar { display:grid; place-items:center; width:58px; height:58px; margin-bottom:9px;
  border-radius:50%; background:#24483d; color:#f2e9d5;
  font:700 13px 'IBM Plex Mono',ui-monospace,monospace; }
.res-label { margin:0 0 4px; color:#8a7e64; font:10px 'IBM Plex Mono',ui-monospace,monospace;
  letter-spacing:.11em; }
.res-desk b { font:700 16px 'Fraunces',Georgia,serif; }
.res-desk small { margin-top:7px; color:#7a705c; font:10px 'IBM Plex Mono',ui-monospace,monospace; }

/* Where the file comes to rest. A custom property because the route is much
   narrower on a phone, and the desktop end position walks the dossier clean
   over the claim plate next to it. */
.res-route { position:relative; height:185px; --travel-end:calc(88% - 52px); }
.res-line { position:absolute; left:4%; right:4%; top:120px; height:3px; background:#d0c7b1;
  overflow:hidden; }
.res-line i { display:block; height:100%; width:0; background:#24483d;
  animation:res-route-fill 3.12s .64s linear forwards; }
@keyframes res-route-fill { to { width:100%; } }
/* The file travels ABOVE the route, not along it. Sat at the same height it
   simply parked on top of the third checkpoint — the one labelled SEAL,
   which is the one that matters. The pips still straddle the line; the line
   and the file just do not share a lane. */
.res-cp { position:absolute; top:110px; transform:translateX(-50%); text-align:center; }
.res-cp.c1 { left:4%; } .res-cp.c2 { left:50%; } .res-cp.c3 { left:96%; }
.res-cp span { display:grid; place-items:center; width:22px; height:22px; margin:0 auto;
  border-radius:50%; border:1px solid #b3a988; background:#efe9d9; color:#8a7e64;
  font:11px 'IBM Plex Mono',ui-monospace,monospace; transition:transform .2s ease; }
.res-cp.lit span { border-color:#24483d; background:#24483d; color:#f2e9d5;
  animation:res-checkpoint .28s ease-out; }
@keyframes res-checkpoint { 0% { transform:scale(.6); } 60% { transform:scale(1.25); } 100% { transform:scale(1); } }
.res-cp small { display:block; margin-top:4px; color:#8a806a;
  font:8px 'IBM Plex Mono',ui-monospace,monospace; letter-spacing:.1em; }

.res-dossier { position:absolute; left:2%; top:6px; z-index:4; width:104px; height:112px;
  padding:13px 10px; border:1px solid #766d58; background:#eee7d5;
  box-shadow:0 8px 16px rgba(39,36,28,.22); opacity:0;
  animation:res-dossier-route 3.2s .55s cubic-bezier(.45,.05,.3,1) forwards; }
.res-dossier::before { content:""; position:absolute; inset:7px; border:1px solid #cbc1aa;
  pointer-events:none; }
.res-dossier span, .res-dossier b, .res-dossier i { position:relative; display:block; }
.res-doc-head { color:#A23E27; font:7px 'IBM Plex Mono',ui-monospace,monospace; letter-spacing:.08em; }
.res-dossier b { margin-top:12px; font:700 12px/1.1 'Fraunces',Georgia,serif; }
.res-dossier i { margin-top:7px; color:#665e4f; font:9px/1.15 'Fraunces',Georgia,serif; }
.res-wax { position:absolute; right:9px; bottom:9px; display:grid; place-items:center;
  width:17px; height:17px; border-radius:50%; background:#8c3324; color:#f4e6cf;
  font:700 9px 'Fraunces',Georgia,serif; }
@keyframes res-dossier-route {
  0% { left:2%; opacity:0; transform:translateX(-15px) rotate(-5deg); }
  8% { opacity:1; }
  30% { left:18%; transform:rotate(2deg); } 38% { left:18%; transform:rotate(-2deg); }
  66% { left:48%; transform:rotate(2deg); } 74% { left:48%; transform:rotate(-2deg); }
  100% { left:var(--travel-end); opacity:1; transform:rotate(0); } }

.res-beam { position:absolute; left:0; top:2px; width:64px; height:150px; opacity:0;
  background:linear-gradient(90deg,rgba(176,140,30,0),rgba(176,140,30,.5),rgba(176,140,30,0));
  animation:res-scan 1.1s 1.82s ease-in-out forwards; }
@keyframes res-scan {
  0% { opacity:0; transform:translateX(0); }
  15% { opacity:1; } 85% { opacity:1; }
  100% { opacity:0; transform:translateX(320px); } }

.res-stamp { position:absolute; right:0; top:52px; z-index:8; display:grid; place-items:center;
  width:78px; height:78px; border:5px double var(--seal); border-radius:50%;
  color:var(--seal); background:rgba(245,241,229,.94); text-align:center;
  font:700 10px/1 'IBM Plex Mono',ui-monospace,monospace; opacity:0;
  transform:translateY(-65px) rotate(-12deg) scale(1.7); }
.res-stage.settled .res-stamp { opacity:1;
  animation:res-stamp .3s cubic-bezier(.2,.8,.35,1.3) forwards; }
@keyframes res-stamp {
  0% { transform:translateY(-65px) rotate(-12deg) scale(1.7); }
  58% { transform:translateY(5px) rotate(-8deg) scale(.88); }
  100% { transform:translateY(0) rotate(-8deg) scale(1); } }

.res-claim { text-align:center; }
.res-plate { margin-bottom:12px; padding:14px 8px; border:1px solid #b7ad95; background:#e8e1cf;
  box-shadow:inset 0 0 0 4px rgba(255,255,255,.28); }
.res-house { display:grid; place-items:center; width:46px; height:46px; margin:0 auto;
  border:1px solid #847b68; background:#24483d; color:#f7f0df;
  font:26px 'Fraunces',Georgia,serif; transform:rotate(45deg); }
.res-plate b { display:block; margin-top:9px; font:700 14px 'Fraunces',Georgia,serif; }
.res-plate small { display:block; margin-top:4px; color:#756b58;
  font:9px 'IBM Plex Mono',ui-monospace,monospace; }
.res-claim strong { display:block; color:#69402f; font:italic 13px/1.3 'Fraunces',Georgia,serif; }

.res-verify { display:flex; align-items:center; gap:10px; margin:16px 0 4px; }
.res-verify-label { color:#8a7e64; font:9.5px 'IBM Plex Mono',ui-monospace,monospace;
  letter-spacing:.11em; }
.res-verify-track { flex:1; height:3px; background:#d0c7b1; overflow:hidden; }
.res-verify-track i { display:block; height:100%; width:0; background:var(--seal);
  animation:res-verify-fill 3.58s .55s linear forwards; }
@keyframes res-verify-fill { to { width:100%; } }
.res-verify-count { color:#8a7e64; font:10px 'IBM Plex Mono',ui-monospace,monospace;
  font-variant-numeric:tabular-nums; }

.res-result { min-height:86px; margin-top:12px; text-align:center; opacity:0; }
.res-stage.settled .res-result { animation:res-result-in .42s .18s ease-out forwards; }
@keyframes res-result-in { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
.res-kicker { margin:0 0 4px; color:var(--seal);
  font:10.5px 'IBM Plex Mono',ui-monospace,monospace; letter-spacing:.13em; }
.res-title { margin:0 0 5px; font:700 21px/1.1 'Fraunces',Georgia,serif; }
.res-detail { margin:0; color:#5d574a; font-size:13px; line-height:1.5; max-width:56ch;
  margin-inline:auto; }
.res-calls { display:flex; flex-wrap:wrap; gap:6px; justify-content:center; margin-top:12px; }
.res-call { padding:3px 9px; border:1px solid #cbc1aa; background:rgba(255,255,255,.5);
  font-size:11.5px; }
.res-call.good { border-color:#2F6B45; color:#2F6B45; }
.res-call.bad { border-color:#A23E27; color:#A23E27; }
.res-call.void { color:#7C7768; }

.res-flash { position:absolute; inset:0; z-index:6; pointer-events:none; opacity:0;
  background:radial-gradient(circle at center,rgba(244,216,105,.8),rgba(244,216,105,0) 62%); }
.res-stage.settled.out-good .res-flash { animation:res-good-flash .75s ease-out; }
.res-stage.settled.out-bad .res-flash {
  background:radial-gradient(circle at center,rgba(169,55,38,.52),rgba(169,55,38,0) 62%);
  animation:res-bad-flash .62s ease-out; }
@keyframes res-good-flash { 0% { opacity:0; } 18% { opacity:.95; } 100% { opacity:0; } }
@keyframes res-bad-flash { 0% { opacity:0; } 20% { opacity:.85; } 100% { opacity:0; } }
.res-stage.settled.out-good .res-dossier {
  box-shadow:0 0 0 3px rgba(47,104,79,.25),0 12px 24px rgba(39,36,28,.25); }
.res-stage.settled.out-bad .res-dossier { animation:res-dossier-reject .45s ease-in-out forwards; }
@keyframes res-dossier-reject {
  0%,100% { transform:rotate(0); }
  25% { transform:translateX(-8px) rotate(-3deg); }
  55% { transform:translateX(7px) rotate(3deg); }
  80% { transform:translateX(-3px); } }

.res-foot { margin-top:14px; display:flex; justify-content:flex-end; }

@media (max-width:780px) {
  .res-card { padding:17px 14px 14px; }
  .res-head h2 { font-size:19px; }
  .res-scene { grid-template-columns:92px 1fr 105px; gap:6px; }
  .res-avatar { width:46px; height:46px; font-size:11px; }
  .res-desk b { font-size:13px; }
  .res-desk small, .res-claim strong { font-size:9px; }
  .res-plate { padding:10px 4px; } .res-plate b { font-size:12px; }
  .res-house { width:36px; height:36px; font-size:20px; }
  .res-route { --travel-end:calc(96% - 78px); }
  .res-dossier { width:78px; height:104px; padding:10px 7px; }
  .res-dossier b { font-size:10px; } .res-dossier i { font-size:8px; }
  .res-cp small { display:none; }
  .res-stamp { width:64px; height:64px; font-size:8px; border-width:4px; }
  .res-title { font-size:18px; }
}

/* The pack's own rule: resolve near-instantly rather than animating. */
@media (prefers-reduced-motion:reduce) {
  .res-stage *, .res-card { animation-duration:.01ms !important; animation-delay:0ms !important; }
  .res-dossier, .res-result { opacity:1; }
  .res-line i, .res-verify-track i { width:100%; }
}

/* ======================= THE GAMING COUNCIL ============================= */
/* TWO GAMES, TWO BLOCKS.

   The first version ran both games down one parchment column with the perk
   shop underneath, and it read as one long confusing thing rather than three
   short clear ones — a player could not tell where Surveyor's Bluff stopped.
   Each game now sits in a band of its own colour: the Bluff in the city's
   green, the Committee in the ticker's blue, the shop left on plain paper
   because it is not a game and should not pretend to be one. */
.game-section { border:1px solid var(--line); margin:0 0 18px; background:var(--paper); }
/* ---- A COLOUR PER GAME ------------------------------------------------

   Five games have sat on this tab and until now three of them shared the
   same paper-coloured header, so scrolling the Gaming Council looked like
   one long document rather than a shelf of separate things. Each game now
   owns a hue, and a returning player can find the Tontine by colour before
   they have read a word of it.

   Chosen by measurement, not taste. Every pair is at least 32 ΔE apart
   (CIE76) so no two read as the same colour at a glance, and every one of
   them carries #F2EFE4 header text at 7:1 or better. Navy and forest were
   already spoken for by the committee and the bluff, so the search held
   those fixed and placed the other three around them.

   If a sixth game ever arrives, re-run the search rather than eyeballing a
   gap — the first attempt at this put the assessors on a slate blue that
   measured 14.6 ΔE from the committee's navy, which looked fine in
   isolation and identical on the page. */
/* THE COMMITTEE TOOK THE HOUSE GREEN, AND THE BLUFF TOOK THE NAVY.

   The committee is the oldest surviving game on this tab and the one most
   players meet first, so it wears the colour the rest of the site is built
   in. The bluff, stood down, takes the navy it vacated. Straight swap, and
   the separation still holds: green sits 39 and 49 deltaE from the tontine
   and the gazette, navy 61 and 49. Nothing had to move but the two labels.

   tone-forest and tone-navy are kept as aliases because they are the older
   names and something outside this file may still say them. */
.game-section.tone-committee,
.game-section.tone-forest  { border-color:var(--forest); }   /* Planning Committee */
.game-section.tone-bluff,
.game-section.tone-navy    { border-color:var(--navy); }     /* Surveyor's Bluff */
.game-section.tone-gazette { border-color:#63251F; }         /* The Gazette — press ink */
.game-section.tone-tontine { border-color:#5E4A0F; }         /* The Tontine — tallow */
.game-section.tone-assess  { border-color:#58246B; }         /* Assessors' Round */

.game-head { display:flex; align-items:center; justify-content:space-between; gap:12px;
  flex-wrap:wrap; padding:11px 14px; color:#f2efe4; }
.tone-committee .game-head,
.tone-forest    .game-head { background:var(--forest); }
.tone-bluff     .game-head,
.tone-navy      .game-head { background:var(--navy); }
.tone-gazette .game-head { background:#63251F; }
.tone-tontine .game-head { background:#5E4A0F; }
.tone-assess  .game-head { background:#58246B; }
.tone-plain .game-head { background:var(--paper-dark); color:var(--ink); border-bottom:1px solid var(--line); }

.game-title { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; background:none;
  border:none; padding:0; margin:0; cursor:pointer; color:inherit; font-family:inherit; text-align:left; }
.game-title.static { cursor:default; }
.game-title:focus-visible { outline:2px solid var(--gold); outline-offset:3px; }
.game-kicker { font-size:9.5px; letter-spacing:.16em; opacity:.72; }
.game-title b { font-family:'Fraunces', serif; font-size:19px; font-weight:700; }
.game-how { font-size:11.5px; opacity:.8; text-decoration:underline; text-underline-offset:2px; }
.game-title:hover .game-how { opacity:1; }
.game-tagline { font-size:12px; opacity:.85; font-style:italic; }
.tone-plain .game-tagline { font-style:normal; color:#6b6455; }

/* The rules, in the player's language and with none of the arithmetic. A
   player who has to ask somebody how a game works usually stops playing it
   instead. */
.game-synopsis { padding:13px 16px; background:var(--paper-dark); border-bottom:1px solid var(--line); }
.game-synopsis p { margin:0 0 9px; font-size:13px; line-height:1.6; max-width:62ch; }
.game-synopsis p:last-child { margin-bottom:0; }

.game-body { padding:14px; }
/* The faintest wash of the same hue through the body, so the colour is a
   property of the whole section rather than a stripe along the top. Five
   per cent — any more and the Gazette's parchment stops being parchment. */
.tone-committee .game-body,
.tone-forest    .game-body { background:rgba(31,75,63,.05); }
.tone-bluff     .game-body,
.tone-navy      .game-body { background:rgba(35,57,93,.05); }
.tone-gazette .game-body { background:rgba(99,37,31,.05); }
.tone-tontine .game-body { background:rgba(94,74,15,.05); }
.tone-assess  .game-body { background:rgba(88,36,107,.05); }
.game-section .council-strip { margin:0; border-radius:0; border-left:none; border-right:none; }

/* --- the pod ----------------------------------------------------------- */
/* Names are buttons now: the pod is the only place a reputation can be built,
   so it has to be the place one can be read. */
.pod-name { background:var(--paper); border:1px solid var(--line); color:inherit;
  font-family:inherit; font-size:12px; padding:3px 9px; cursor:pointer; }
.pod-name:hover { border-color:var(--gold); background:var(--paper-dark); }
.pod-name.you { border-color:var(--forest); color:var(--forest); font-weight:600; }
.pod-name:focus-visible { outline:2px solid var(--gold); outline-offset:1px; }

.player-backdrop { z-index:110; }
.player-box { max-width:420px; width:100%; }
.player-name { font-family:'Fraunces', serif; font-size:21px; margin:0 0 12px;
  display:flex; align-items:baseline; gap:9px; }
.player-you { font-size:10px; letter-spacing:.12em; color:var(--forest);
  border:1px solid var(--forest); padding:1px 6px; }
.player-game { margin:0 0 14px; }
.player-game-name { display:block; font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--gold); border-bottom:1px solid var(--line); padding-bottom:4px; margin-bottom:6px; }
.player-rows > div { display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  font-size:12.5px; padding:2px 0; }
.player-rows span { color:var(--muted, #6b6455); }
.player-rows b { font-variant-numeric:tabular-nums; }
.player-rows em { font-style:normal; color:#6b6455; font-weight:400; font-size:11px; }

/* --- the permit board -------------------------------------------------- */
.token-purse { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:0 0 12px; }
.purse-chip { display:flex; align-items:baseline; gap:5px; padding:4px 9px; border:1px solid var(--line);
  background:var(--paper); font-family:'IBM Plex Mono', monospace; font-size:15px; font-weight:600; }
.purse-chip em { font-style:normal; font-size:10px; letter-spacing:.09em; text-transform:uppercase;
  font-weight:400; color:#6b6455; }
.purse-chip.support { border-color:var(--forest); color:var(--forest); }
.purse-chip.smear { border-color:var(--brick); color:var(--brick); }
.purse-chip.veto { border-color:var(--ink); color:var(--ink); }
.purse-chip.spent { opacity:.35; }
.purse-note { font-size:11px; color:#6b6455; font-style:italic; }

.permit-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(190px, 1fr)); gap:9px; }
.permit { border:1px solid var(--line); background:var(--paper); padding:9px 10px;
  display:flex; flex-direction:column; gap:3px; }
.permit.yours { border-color:var(--gold); box-shadow:inset 0 0 0 1px var(--gold); }
.permit-tier { font-size:9px; letter-spacing:.14em; color:#6b6455; }
.permit.t-gold .permit-tier { color:#9a7b12; font-weight:600; }
.permit.t-silver .permit-tier { color:#5c6670; }
.permit-name { font-family:'Fraunces', serif; font-size:14px; line-height:1.25; text-wrap:balance; }
.permit-volume { font-family:'IBM Plex Mono', monospace; font-size:11px; color:#6b6455;
  font-variant-numeric:tabular-nums; }
.permit-mine { font-size:10.5px; color:var(--gold); letter-spacing:.04em; }
.permit-place { display:flex; gap:4px; margin-top:5px; }
.tok { flex:1; display:flex; align-items:center; justify-content:center; gap:3px; padding:4px 0;
  border:1px solid; background:var(--paper); cursor:pointer; font-family:'IBM Plex Mono', monospace;
  font-size:11px; font-weight:600; }
.tok span { font-variant-numeric:tabular-nums; }
.tok.support { border-color:var(--forest); color:var(--forest); }
.tok.smear { border-color:var(--brick); color:var(--brick); }
.tok.veto { border-color:var(--ink); color:var(--ink); }
.tok.clear { flex:0 0 26px; border-color:var(--line); color:#6b6455; }
.tok:hover:not(:disabled) { background:var(--paper-dark); }
.tok:disabled { opacity:.3; cursor:default; }
.tok:focus-visible { outline:2px solid var(--gold); outline-offset:1px; }
.permit-grid.sent .permit { opacity:.9; }

/* --- the minutes ------------------------------------------------------- */
.minutes-total { font-family:'IBM Plex Mono', monospace; font-size:13px; padding:7px 10px;
  margin:0 0 11px; }
.minutes-total.up { background:rgba(47,107,69,.12); color:#2F6B45; }
.minutes-total.down { background:rgba(176,52,42,.12); color:#B0342A; }
.minute { border-left:3px solid var(--line); padding:6px 0 7px 10px; margin:0 0 9px; }
.minute.o-awarded { border-left-color:#2F6B45; }
.minute.o-poisoned { border-left-color:#B0342A; }
.minute.o-vetoed { border-left-color:var(--ink); }
.minute.o-tied, .minute.o-unbid { opacity:.6; }
.minute-head { display:flex; align-items:baseline; justify-content:space-between; gap:9px; }
.minute-head b { font-family:'Fraunces', serif; font-size:14px; }
.minute-tier { font-size:9px; letter-spacing:.13em; color:#6b6455; }
.minute-tier.t-gold { color:#9a7b12; }
.minute-what { font-size:12.5px; line-height:1.5; margin-top:2px; }
.minute-placements { display:flex; flex-wrap:wrap; gap:4px 6px; margin-top:5px; }
.placement { font-family:'IBM Plex Mono', monospace; font-size:10px; padding:1px 6px;
  border:1px solid var(--line); color:#6b6455; }
.placement.k-support { border-color:rgba(47,107,69,.5); color:#2F6B45; }
.placement.k-smear { border-color:rgba(176,52,42,.5); color:#B0342A; }
.placement.k-veto { border-color:var(--ink); color:var(--ink); font-weight:600; }

@media (max-width: 720px) {
  .game-head { align-items:flex-start; }
  .permit-grid { grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); }
}

/* --- a disguised figure ------------------------------------------------ */
/* The mark says a number is a claim. It deliberately does NOT say which way,
   or by how much — a board nobody knows can lie is a board that lies for
   ever, but a board that shows the whole trick is no lie at all. */
.disguised-mark { margin-left:5px; color:var(--gold); font-size:11px; vertical-align:super; }
.board-caveat { font-size:11.5px; color:#6b6455; border-left:3px solid var(--gold);
  padding:5px 0 5px 10px; margin:0 0 12px; line-height:1.5; }

.perk-options { display:grid; grid-template-columns:1fr 1fr; gap:6px; margin:8px 0 2px; }
.perk-option { display:flex; flex-direction:column; gap:2px; padding:7px 9px; cursor:pointer;
  border:1px solid var(--line); background:var(--paper); text-align:left;
  font-family:inherit; color:inherit; }
.perk-option b { font-size:12px; }
.perk-option span { font-size:10.5px; color:#6b6455; line-height:1.4; }
.perk-option:hover { border-color:var(--gold); }
.perk-option.on { border-color:var(--forest); box-shadow:inset 0 0 0 1px var(--forest); }
.perk-option:focus-visible { outline:2px solid var(--gold); outline-offset:1px; }

.disguise-live { border:1px solid var(--gold); background:rgba(176,140,30,.09);
  padding:9px 11px; margin:0 0 12px; display:flex; flex-direction:column; gap:3px; }
.disguise-live b { font-size:12.5px; }
.disguise-live span { font-size:11.5px; color:#5a5344; line-height:1.5; }

@media (max-width: 620px) { .perk-options { grid-template-columns:1fr; } }

/* --- who holds a property ---------------------------------------------- */
/* Arriving from the map, the first thing a player needs is whether this
   building belongs to somebody, because it decides whether the rest of the
   card is about buying or about dealing with a person. It was a grey
   footnote sharing a line with the security level. */
.deed-owner { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap;
  font-size:16px; margin:0 0 6px; padding:8px 11px;
  background:var(--paper-dark); border-left:3px solid var(--gold); }
.deed-owner-label { font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:#6b6455; }
.deed-owner b { font-size:16px; font-weight:600; }
.deed-owner .firm-line { flex-basis:100%; font-size:11.5px; color:#6b6455; margin:0; }

/* ===================== THE ACCOUNT PANEL AND GUIDE ===================== */
.account-backdrop, .guide-backdrop { z-index:115; }
.account-box { max-width:560px; width:100%; max-height:88vh; overflow-y:auto; }
.account-title { font-family:'Fraunces', serif; font-size:22px; margin:0 0 12px; }
.account-tabs { display:flex; flex-wrap:wrap; gap:4px; border-bottom:1px solid var(--line);
  margin:0 0 14px; }
.account-tab { background:none; border:none; border-bottom:2px solid transparent; cursor:pointer;
  font-family:inherit; font-size:12.5px; color:#6b6455; padding:7px 10px; margin-bottom:-1px; }
.account-tab:hover { color:var(--ink); }
.account-tab.on { color:var(--ink); border-bottom-color:var(--gold); font-weight:600; }
.account-tab:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }

.account-facts { display:grid; gap:2px; margin:0 0 16px; }
.account-facts > div { display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  font-size:13px; }
.account-facts span { color:#6b6455; }
.account-h { font-family:'Fraunces', serif; font-size:15px; margin:18px 0 8px;
  padding-bottom:5px; border-bottom:1px solid var(--line); }
.account-h:first-of-type { margin-top:0; }
.account-note { font-size:11.5px; color:#6b6455; line-height:1.55; margin:0 0 10px; }
.account-warn { font-size:11.5px; line-height:1.55; margin:0 0 10px; padding:7px 9px;
  background:rgba(176,140,30,.12); border-left:3px solid var(--gold); }
.account-done { font-size:13px; padding:9px 11px; margin:0 0 10px;
  background:rgba(47,107,69,.12); color:#2F6B45; }
.account-list { margin:0 0 14px; padding-left:18px; }
.account-list li { font-size:12.5px; line-height:1.6; margin-bottom:6px; }

/* Leaving is the one irreversible thing in here, so it is the one control
   that does not look like the others. */
.btn.danger { background:var(--loss); border-color:#7d2419; }
.btn.danger:hover:not(:disabled) { background:#8d2a1f; }

.receipt { border:1px solid var(--line); background:var(--paper); padding:8px 10px; margin:0 0 7px; }
.receipt-head { display:flex; justify-content:space-between; align-items:baseline; gap:10px; }
.receipt-amount { font-family:'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }
.receipt-meta { font-size:11px; color:#6b6455; margin-top:2px; }
.receipt-ref { font-family:'IBM Plex Mono', monospace; font-size:10px; }

.guide-box { max-width:480px; width:100%; }
.guide-head { display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  margin:0 0 12px; }
.guide-kicker { font-size:9.5px; letter-spacing:.16em; color:var(--gold); }
.guide-title { font-family:'Fraunces', serif; font-size:24px; margin:0 0 12px;
  text-wrap:balance; line-height:1.2; }
.guide-line { font-size:14px; line-height:1.65; margin:0 0 12px; max-width:56ch; }

/* The four opening moves. Numbered because they ARE a sequence — the free
   pull pays for the purchase — which is the only thing that earns a
   numbered list. */
.guide-steps { margin:0 0 14px; padding:0 0 0 20px; max-width:56ch; }
.guide-steps li { margin:0 0 10px; font-size:13.5px; line-height:1.55; }
.guide-steps li b { display:block; font-family:'Fraunces',Georgia,serif; font-size:15px;
  font-weight:600; margin-bottom:2px; }
.guide-steps li span { color:#6b6455; }

/* A link inside the guide or the account panel is part of the prose, not a
   browser default — the untouched blue was the one thing on the card that
   did not belong to the game. */
.guide-line a, .account-note a { color:var(--forest-dark); text-underline-offset:2px; }
.guide-line a:hover, .account-note a:hover { color:var(--forest); }

/* The appeals board. Deliberately plain — a panel that looked like a
   charity drive would make asking feel worse than the position that
   caused it. */
.appeals .appeal-mine { padding:10px 12px; margin:10px 0; border-left:3px solid var(--gold);
  background:var(--paper-dark); font-size:13px; }
.appeal-row { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap;
  gap:10px; padding:9px 0; border-top:1px solid var(--line); font-size:13px; }
.appeal-give { display:flex; gap:6px; align-items:center; }
.appeal-give input { width:120px; padding:6px 8px; font-size:13px; border:1px solid var(--line);
  background:var(--paper); font-family:inherit; }
@media (max-width: 560px) { .appeal-row { flex-direction:column; align-items:flex-start; } }

/* The rival's map ink, beside their name. Round, so it is never mistaken
   for the diamond swatches in the map key. */
.rival-ink { display:inline-block; width:10px; height:10px; border-radius:50%;
  margin-right:7px; vertical-align:baseline; border:1px solid rgba(0,0,0,.35); }

/* A property's name, wherever it is written, opens its deed. Underlined on
   hover rather than always, so a list of six names does not read as a row
   of links shouting for attention. */
.prop-link { padding:0; border:0; background:none; cursor:pointer; font:inherit; color:inherit;
  border-bottom:1px dotted currentColor; }
.prop-link:hover { color:var(--forest-dark); border-bottom-style:solid; }

/* The cash-flow breakdown. A ledger, so it should look like one: labels
   left, figures right on a single decimal column, and the net ruled off. */
.cf-table { width:100%; border-collapse:collapse; margin:12px 0 4px; font-size:13.5px; }
.cf-table th { text-align:left; font-weight:600; padding:8px 0; vertical-align:top; }
.cf-table th em { display:block; font-style:normal; font-weight:400; font-size:12px; color:#6b6455;
  margin-top:1px; }
.cf-table td { text-align:right; padding:8px 0; white-space:nowrap;
  font-family:'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }
.cf-table tr + tr th, .cf-table tr + tr td { border-top:1px solid var(--line); }
.cf-net th, .cf-net td { border-top:2px solid var(--ink) !important; font-weight:700; padding-top:10px; }

/* THE ASSESSORS' ROUND.

   Five cards in a row that have to read as one object: same edges, same
   baselines, the chosen two lifted rather than the other three dimmed —
   dimming the unchosen would make a board of five look like a board of
   two the moment anybody picked. */
.assess-slate { display:grid; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr)); gap:10px;
  margin:12px 0; }
.assess-card { display:flex; flex-direction:column; gap:2px; align-items:flex-start; text-align:left;
  padding:10px 11px; cursor:pointer; font:inherit; background:var(--paper);
  border:1px solid var(--line); border-radius:2px; }
.assess-card:hover { border-color:var(--forest); }
.assess-card b { font-family:'Fraunces',Georgia,serif; font-size:14.5px; line-height:1.25; }
.assess-card .assess-where { font-size:11.5px; color:#6b6455; }
.assess-card .assess-open { font-size:11.5px; color:#8e8674; margin-top:4px; }
.assess-card .assess-now { font-family:'IBM Plex Mono', monospace; font-size:12.5px;
  font-variant-numeric:tabular-nums; }
.assess-role { font-family:'IBM Plex Mono', monospace; font-size:8.5px; letter-spacing:.14em;
  color:var(--gold); min-height:12px; }
.assess-card.is-rise { border-color:var(--gain); box-shadow:inset 0 0 0 1px var(--gain); }
.assess-card.is-fall { border-color:var(--loss); box-shadow:inset 0 0 0 1px var(--loss); }
.assess-card.is-rise .assess-role { color:var(--gain); }
.assess-card.is-fall .assess-role { color:var(--loss); }

.assess-actions { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.assess-actions .hint { margin:0; }
.assess-last { padding:9px 11px; margin-bottom:4px; font-size:13px;
  border-left:3px solid var(--line); background:var(--paper-dark); }
.assess-last.won { border-left-color:var(--gain); }
.assess-last b { margin-right:8px; font-family:'Fraunces',Georgia,serif; }
.assess-last em { display:block; font-style:normal; color:#6b6455; font-size:12.5px; margin-top:3px; }
.assess-week { margin-top:16px; }

/* ---- THE TONTINE ------------------------------------------------------

   Parchment, and candles that never stop burning. The panel has to feel
   like a room somebody is sitting in rather than a form, because the whole
   game is the nerve to leave it alone for another night. */
.tont-roll { position:relative; isolation:isolate; display:flex; flex-wrap:wrap; gap:18px;
  justify-content:center; padding:35px 20px 42px; margin:10px 0 14px; overflow:hidden;
  background:
    radial-gradient(ellipse at 50% 12%, rgba(244,205,103,.15), transparent 38%),
    repeating-linear-gradient(90deg, rgba(255,255,255,.018) 0 1px, transparent 1px 37px),
    linear-gradient(145deg,#244b40,#122f28 52%,#0e251f);
  border:5px double #8f7331; box-shadow:inset 0 0 0 4px #17382f,
  inset 0 -25px 50px rgba(3,13,10,.42),0 12px 28px rgba(34,29,19,.24);
  animation:tont-room-breathe 9s ease-in-out infinite; }
.tont-roll::before { content:"THE TONTINE · YOUR FIELD'S TABLE"; position:absolute; left:18px; right:18px;
  top:9px; padding-bottom:6px; border-bottom:1px solid rgba(211,179,91,.35);
  color:#c8ac61; font-family:'IBM Plex Mono',monospace; font-size:8px; letter-spacing:.18em;
  text-align:center; }
.tont-candle { --sweep:0s; position:relative; z-index:2; width:86px; padding:7px 4px 6px;
  text-align:center; border-bottom:1px solid rgba(206,178,103,.2); }
.tont-candle::before { content:""; position:absolute; z-index:-1; left:8px; right:8px; top:18px;
  height:70px; border-radius:50%; opacity:.5; background:radial-gradient(ellipse,
  rgba(235,168,53,.27),rgba(221,142,31,.08) 45%,transparent 72%);
  animation:tont-light-pool 3.8s ease-in-out infinite; }
.tont-candle:nth-child(2n)::before { animation-delay:-1.4s; }
.tont-candle:nth-child(3n)::before { animation-delay:-2.3s; }
.tont-candle svg { width:54px; height:78px; display:block; margin:0 auto; overflow:visible;
  filter:drop-shadow(0 6px 4px rgba(0,0,0,.34)); }
.tont-candle b { display:block; font-family:'Fraunces',Georgia,serif; font-size:12.5px;
  margin-top:2px; color:#F1E8D0; text-shadow:0 1px #07130f; }
.tont-candle span { display:block; font-family:'IBM Plex Mono',monospace; font-size:9.5px;
  letter-spacing:.06em; color:#BDAF8B; }

.tont-wax { fill:#F3EAD2; stroke:#C9BC98; stroke-width:.6; }
.tont-candle:not(.is-gone) .tont-wax { transform-box:fill-box;
  transform-origin:center bottom; transform:scaleY(var(--wax-level,1));
  transition:transform 1.15s cubic-bezier(.2,.72,.24,1); }
.tont-candle:not(.is-stub):not(.is-gone):not(.is-striking)::after { content:"";
  position:absolute; z-index:1; left:50%; top:35px; width:1px; height:var(--wick-grow,1px);
  background:#2A2118; box-shadow:0 0 1px rgba(239,174,66,.45); transform:translateX(-50%);
  transition:height 1.15s cubic-bezier(.2,.72,.24,1); }
.tont-holder { fill:#B08A32; filter:drop-shadow(0 1px 1px rgba(0,0,0,.6)); }
.tont-candle.is-council .tont-wax { y:9.5; height:19; fill:#EFE0B4; stroke:#B59A55; }
.tont-candle.is-council .tont-holder { fill:#6E5A22; }
.tont-candle.is-me .tont-holder { fill:#1F8A4C; }
.tont-candle.is-me { border-color:rgba(84,190,120,.62); background:linear-gradient(180deg,
  transparent,rgba(39,116,71,.12)); }
.tont-candle.is-me b { color:#F5EACF; font-weight:700; }
.tont-candle.is-council { border-inline:1px solid rgba(176,140,30,.2); }

/* The flame. Two paths: a soft halo that swells, and the fire itself,
   which leans. Staggered so a row never beats in unison. The duration is
   set inline by the game — 3.1s on Monday down to about 1.4s on Saturday. */
.tont-flame { transform-origin:12px 12px; transform-box:view-box;
  animation:tont-burn 3s ease-in-out infinite; filter:drop-shadow(0 0 1.4px #fff1a7)
  drop-shadow(0 0 4px #e69728) drop-shadow(0 0 9px rgba(226,128,31,.52)); }
.tont-candle:nth-child(2n) .tont-flame { animation-delay:-.7s; }
.tont-candle:nth-child(3n) .tont-flame { animation-delay:-1.4s; }
.tont-fire { fill:#F0A52B; animation:tont-colour 4.1s ease-in-out infinite; }
.tont-halo { fill:#F7D570; opacity:.48; animation:tont-halo 2.7s ease-in-out infinite; }
@keyframes tont-burn {
  0%,100% { transform:translate(0,0) scaleY(1) scaleX(1) rotate(0deg); opacity:1; }
  17% { transform:translate(.35px,.15px) scaleY(1.08) scaleX(.94) rotate(-2.4deg); opacity:.94; }
  39% { transform:translate(-.25px,.35px) scaleY(.95) scaleX(1.06) rotate(1.8deg); opacity:1; }
  61% { transform:translate(.25px,-.25px) scaleY(1.13) scaleX(.92) rotate(3.2deg); opacity:.91; }
  82% { transform:translate(-.2px,.2px) scaleY(1.03) scaleX(.98) rotate(-1.3deg); opacity:.97; }
}
@keyframes tont-colour { 0%,100%{fill:#E89B26} 48%{fill:#FFD76A} 72%{fill:#ED8521} }
@keyframes tont-halo { 0%,100%{opacity:.34;transform:scale(.96)} 50%{opacity:.62;transform:scale(1.18)} }
@keyframes tont-light-pool { 0%,100%{opacity:.34;transform:scale(.96)} 50%{opacity:.58;transform:scale(1.04)} }
@keyframes tont-room-breathe { 0%,100%{background-color:#17382f} 50%{background-color:#1b4035} }

/* Gone, but intact — carried off, the outline says a candle stood here. */
.tont-ghost { fill:none; stroke:#9E9277; stroke-width:.8; stroke-dasharray:2.5 2.5;
  opacity:.72; animation:tont-empty-chair 6s linear infinite; }
.tont-candle.is-gone::before,.tont-candle.is-stub::before { opacity:.08; animation:none; }
.tont-candle.is-gone svg { opacity:.62; }
.tont-candle.is-gone b { color:#9E9785; }
.tont-candle.is-gone span { color:#71B087; }

/* Struck: a cold stub, name ruled through, a thread of smoke. */
.tont-candle.is-stub .tont-wax { fill:#D8CDB0; stroke:#A99C78; }
.tont-candle.is-stub b { color:#918A79; text-decoration:line-through; }
.tont-candle.is-stub span { color:#D57969; }
.tont-smoke { fill:none; stroke:#8B8371; stroke-width:1.1; stroke-linecap:round; opacity:.5;
  stroke-dasharray:3 4; animation:tont-drift 5.8s ease-in-out infinite; }
@keyframes tont-drift { 0%{stroke-dashoffset:0;opacity:.16;transform:translateY(2px)}
  45%{opacity:.48} 100%{stroke-dashoffset:-14;opacity:.05;transform:translate(-1.5px,-5px)} }
@keyframes tont-empty-chair { to{stroke-dashoffset:-14} }

/* A stub read out again tonight: it gutters where a flame would be. */
.tont-candle.is-spent svg { animation:tont-gutter .22s ease-in-out 5,tont-dry-settle .7s 1.1s ease-out both; }
.tont-candle.is-spent::after { content:"VOID"; position:absolute; left:50%; top:16px;
  padding:2px 5px; border:1px solid #887C65; opacity:0; color:#B7AC96; background:#173129;
  font:600 7px 'IBM Plex Mono',monospace; letter-spacing:.11em;
  animation:tont-void-stamp .35s .85s ease-out forwards; }
@keyframes tont-gutter { 0%,100%{transform:none} 50%{transform:translateX(1.5px) rotate(1.5deg)} }
@keyframes tont-dry-settle { 0%{filter:brightness(1.35)} 100%{filter:brightness(.72)} }
@keyframes tont-void-stamp { 0%{opacity:0;transform:translate(-50%,8px) scale(1.2)}
  70%{opacity:1;transform:translate(-50%,-1px) scale(.96)} 100%{opacity:1;transform:translate(-50%,0)} }

/* ---- THE DRAW ------------------------------------------------------
   Not built yet. This is the sequence the game wants, once a night:
     1. the draught  — every flame leans and gutters together
     2. the sweep    — tension passes down the row while every living flame remains alight
     3. the ending   — one of three:
          .is-striking  the flame flares white and snuffs, smoke rises
          .is-reprieve  the Council's candle flares and holds; no candle is lost
          .is-spent     the cold stub gutters, nothing happens
   The game adds and removes these classes on .tont-roll and on the
   individual .tont-candle. Nothing below exists yet — build it here. */
.tont-candle:nth-child(1){--sweep:.08s}.tont-candle:nth-child(2){--sweep:.20s}
.tont-candle:nth-child(3){--sweep:.32s}.tont-candle:nth-child(4){--sweep:.44s}
.tont-candle:nth-child(5){--sweep:.56s}.tont-candle:nth-child(6){--sweep:.68s}
.tont-candle:nth-child(7){--sweep:.80s}
.tont-roll.is-drawing { animation:tont-draw-room 3.6s ease-in-out both; }
.tont-roll.is-drawing::before { content:"THE DAILY NAME IS BEING DRAWN";
  animation:tont-inscription-pulse .46s ease-in-out 6; }
.tont-roll.is-drawing .tont-candle:not(.is-stub):not(.is-gone) .tont-flame {
  animation:tont-draught .5s 0s ease-in-out both,tont-search-sweep .42s calc(.58s + var(--sweep)) ease-in-out both!important;
  animation-duration:.5s,.42s!important; }
.tont-roll.is-drawing .tont-candle { animation:tont-candle-tension .45s calc(.25s + var(--sweep)) ease-in-out 2; }

/* Strike: the chamber stills, a silent draught takes one flame, and the wax goes cold. */
.tont-roll .tont-candle.is-striking .tont-flame { animation:tont-strike-flame 1.22s ease-out forwards!important;
  animation-duration:1.22s!important; }
.tont-roll:has(.is-striking) { animation:tont-life-leaves 2.4s ease-out both; }
.tont-roll:has(.is-striking) .tont-candle:not(.is-striking)::before {
  animation:tont-wind-shadow .85s ease-out both; }
.tont-candle.is-striking::before { opacity:.62; background:radial-gradient(ellipse,
  rgba(235,168,53,.3),rgba(221,142,31,.08) 42%,transparent 70%);
  animation:tont-last-light 1.8s ease-out forwards; }
.tont-candle.is-striking .tont-fire { animation:tont-cooling-fire 1.08s ease-out forwards; }
.tont-candle.is-striking::after { content:""; position:absolute; left:50%; top:13px; width:5px;
  height:42px; opacity:0; border-radius:50%; background:linear-gradient(180deg,
  rgba(210,211,202,.62),rgba(129,134,128,.3),transparent); filter:blur(2px);
  animation:tont-new-smoke 2.6s .92s ease-out forwards; }
.tont-candle.is-striking b { animation:tont-name-struck .7s 1s ease-out forwards; }
.tont-candle.is-striking span { font-size:0; }
.tont-candle.is-striking span::after { content:"struck"; color:#E07C6B; font-size:9.5px; }
.tont-candle.is-council.is-striking span::after { content:"drawn out"; }

/* Reprieve: the Council burns brightest, then returns everybody's light. */
.tont-roll.is-drawing .tont-candle.is-reprieve .tont-flame,
.tont-roll .tont-candle.is-reprieve .tont-flame { animation:tont-council-flare 1.5s ease-out forwards!important;
  animation-duration:1.5s!important; }
.tont-roll:has(.is-reprieve) .tont-candle:not(.is-stub):not(.is-gone):not(.is-reprieve) .tont-flame {
  animation:tont-flames-hold .82s .38s ease-out forwards!important;
  animation-duration:.82s!important; }
.tont-roll:has(.is-reprieve)::after { content:"THE COUNCIL GRANTS REPRIEVE · EVERY LIVING FLAME HOLDS";
  border-color:#B08C1E; color:#F4D97E; }

.tont-roll:has(.is-striking)::after { content:"A NAME IS STRUCK · THEY LEAVE WITH NOTHING";
  border-color:#9E4638; color:#F0B0A1; }
/* The Council drawn at a table (29 Sep 2026): its candle goes out like any
   other, and the ruling says what that means. */
.tont-roll:has(.is-council.is-striking)::after { content:"THE COUNCIL IS DRAWN · ITS MONEY STAYS IN THE POT";
  border-color:#B08C1E; color:#F4D97E; }
.tont-roll:has(.is-spent)::after { content:"A SPENT NAME · THE DRAW PASSES EMPTY";
  border-color:#807966; color:#C9C0A8; }
.tont-roll:has(.is-striking)::after,.tont-roll:has(.is-reprieve)::after,
.tont-roll:has(.is-spent)::after { position:absolute; z-index:8; left:50%; bottom:8px;
  min-width:310px; padding:5px 12px; border-top:1px solid; border-bottom:1px solid;
  opacity:1; background:rgba(9,25,20,.9); font:600 8px 'IBM Plex Mono',monospace;
  letter-spacing:.13em; text-align:center; animation:tont-ruling .4s .35s ease-out forwards; }

@keyframes tont-draw-room { 0%,100%{filter:none} 18%{filter:brightness(.72)}
  42%{filter:brightness(.54) saturate(.72)} 70%{filter:brightness(.66)} }
@keyframes tont-inscription-pulse { 50%{color:#F4D778;text-shadow:0 0 9px rgba(234,181,53,.55)} }
@keyframes tont-draught { 0%{transform:none;opacity:1} 45%{transform:translateX(2px) scaleX(.7) scaleY(1.25) rotate(12deg);opacity:.62}
  75%{transform:translateX(-1px) scaleX(.86) scaleY(.72) rotate(-8deg);opacity:.88} 100%{transform:scale(.96);opacity:1} }
@keyframes tont-search-sweep { 0%{opacity:1;transform:scale(.96);filter:brightness(1)}
  45%{opacity:.72;transform:scale(.82,.92);filter:brightness(.68)}
  72%{opacity:1;transform:scale(1.22,1.35);filter:brightness(1.75)}
  100%{opacity:1;transform:scale(1);filter:brightness(1)} }
@keyframes tont-candle-tension { 50%{transform:translateY(1px);filter:brightness(.82)} }
@keyframes tont-life-leaves { 0%{filter:brightness(.82) saturate(.82)}
  18%{filter:brightness(.68) saturate(.66)} 48%{filter:brightness(.5) saturate(.48)}
  100%{filter:brightness(.72) saturate(.68)} }
@keyframes tont-wind-shadow { 0%{opacity:.28;transform:translateX(-8px) scaleX(1.25)}
  45%{opacity:.06;transform:translateX(10px) scaleX(.7)} 100%{opacity:.2;transform:none} }
@keyframes tont-last-light { 0%,22%{opacity:.72;transform:scale(1)}
  48%{opacity:.42;transform:translateX(9px) scaleX(1.5)} 72%{opacity:.08;transform:translateX(15px) scale(.45)}
  100%{opacity:0;transform:translateX(17px) scale(.15)} }
@keyframes tont-strike-flame { 0%,18%{opacity:1;transform:scale(1.02)}
  38%{opacity:.96;transform:translate(3px,1px) scaleX(1.45) scaleY(.72) rotate(17deg)}
  58%{opacity:.78;transform:translate(7px,3px) scaleX(1.7) scaleY(.42) rotate(31deg)}
  72%{opacity:.32;transform:translate(10px,5px) scaleX(1.25) scaleY(.22) rotate(39deg)}
  100%{opacity:0;transform:translate(14px,7px) scale(.03) rotate(45deg);filter:brightness(.45)} }
@keyframes tont-cooling-fire { 0%,30%{fill:#F0A52B} 58%{fill:#C66A26} 100%{fill:#6E4730} }
@keyframes tont-new-smoke { 0%{opacity:0;transform:translate(-50%,4px) scale(.45)}
  18%{opacity:.62} 48%{opacity:.38;transform:translate(-35%,-12px) scale(.9,1.35)}
  100%{opacity:0;transform:translate(-82%,-36px) scale(1.5,2.1)} }
@keyframes tont-name-struck { to{color:#918A79;text-decoration:line-through;transform:translateY(1px)} }
@keyframes tont-council-flare { 0%{opacity:.04;transform:scale(.2) translateY(5px)}
  26%{opacity:1;transform:scale(1.9,2.3) translateY(-3px);filter:brightness(2.5) saturate(.35)}
  54%{opacity:1;transform:scale(1.28,1.6);filter:brightness(1.65)}
  100%{opacity:1;transform:scale(1.04);filter:brightness(1.15)} }
@keyframes tont-flames-hold { 0%{opacity:1;transform:scale(1)}
  42%{opacity:.84;transform:translateX(1px) scale(.92,1.08);filter:brightness(.9)}
  100%{opacity:1;transform:scale(1.02);filter:brightness(1.12)} }
@keyframes tont-ruling { 0%{opacity:0;transform:translate(-50%,9px) scale(1.06)}
  70%{opacity:1;transform:translate(-50%,-1px) scale(.98)} 100%{opacity:1;transform:translate(-50%,0)} }

@media (prefers-reduced-motion: reduce) {
  .tont-roll,.tont-flame,.tont-fire,.tont-halo,.tont-smoke,.tont-candle::before,
  .tont-candle.is-spent svg { animation:none!important; }
}

.tont-draw { padding:9px 12px; margin-bottom:10px; font-size:13px;
  border-left:3px solid var(--loss); background:var(--paper-dark); }
.tont-draw.safe { border-left-color:var(--gain); }

/* The reckoner: a slider and five figures, because the sums are awkward
   and nobody should have to do them in their head. */
.tont-reckon { padding:12px 14px; margin:0 0 12px; border:1px solid var(--line);
  background:var(--paper-dark); }
.tont-reckon label { display:block; font-size:12.5px; }
.tont-reckon label span { display:block; margin-bottom:6px; color:#6b6455; }
.tont-reckon input[type=range] { width:100%; max-width:320px; accent-color:var(--gold); }
.tont-figures { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr));
  gap:8px 14px; margin-top:10px; }
.tont-figures div { display:flex; justify-content:space-between; align-items:baseline;
  gap:8px; font-size:12.5px; border-bottom:1px dotted var(--line); padding-bottom:3px; }
.tont-figures div.lit { border-bottom-color:var(--gold); }
.tont-figures span { color:#6b6455; }
.tont-figures b { font-family:'IBM Plex Mono',monospace; font-variant-numeric:tabular-nums;
  font-size:14px; }
.tont-figures div.lit b { color:var(--forest-dark); font-size:15.5px; }

.tont-act { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.tont-act .hint { margin:0; }

/* The target map inside the tactics tab. Narrow on purpose — it answers
   "whereabouts" and hands precision back to the dropdown beside it. */
/* Small, and hung from the same baseline as the dropdowns beside it. The
   first cut was 230px wide, which made a 270px-tall picture sitting in a
   row of 40px controls — the map became the subject of a panel whose
   subject is the order. */
.target-map { width:150px; flex:none; align-self:flex-end; margin:0; }
.target-map svg { width:100%; height:auto; display:block; border:1px solid var(--line);
  background:#F1EBD9; }
.target-map .hint { margin-top:4px; }
.target-map.is-loading { font-size:12px; color:#6b6455; padding:10px 0; }
.target-dot { cursor:pointer; }
.target-dot:hover circle { stroke:#14150F; stroke-width:1.2; }
@media (max-width: 640px) { .target-map { max-width:100%; } }
.guide-dots { display:flex; gap:5px; margin:18px 0 12px; }
.guide-dot { width:7px; height:7px; border-radius:50%; background:var(--line); }
.guide-dot.past { background:#9aa38f; }
.guide-dot.on { background:var(--gold); transform:scale(1.25); }
.guide-actions { display:flex; gap:8px; }
.guide-actions .btn { flex:1; }

@media (max-width: 620px) {
  .account-box, .guide-box { max-height:92vh; }
  .account-tab { padding:7px 7px; font-size:12px; }
}

/* ---- nicknames, the estate note, the matrix, dossier thumbnails ------- */
/* A name the pod gave you. It sits under the trader's own name rather than
   replacing it, because both are useful: one identifies, one warns. */
.pod-name { display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  line-height:1.25; }
.pod-who { font-size:12px; }
.pod-nick { font-family:'IBM Plex Mono',monospace; font-size:9px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--gold); }
.pod-name.you .pod-nick { color:var(--forest); }

.player-nick { display:flex; flex-direction:column; gap:2px; margin:-6px 0 14px;
  padding:8px 11px; border-left:3px solid var(--gold); background:rgba(176,140,30,.09); }
.player-nick b { font-family:'Fraunces',serif; font-size:16px; }
.player-nick span { font-size:11.5px; color:var(--muted, #6b6455); }
.player-nick.new { border-left-color:var(--line); background:var(--paper-dark); }
.player-nick.new b { font-weight:400; color:#6b6455; }

.estate-note { font-size:11.5px; line-height:1.55; color:#5a5344; margin:0 0 12px;
  padding:7px 9px; background:rgba(176,140,30,.1); border-left:3px solid var(--gold); }

/* THE PAYOFFS AS A TABLE, BECAUSE THEY ARE A TABLE.
   Described in a sentence, a player could read the rules and still not know
   whether calling was worth it. */
.matrix { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin:0 0 12px; }
@media (max-width:640px) { .matrix { grid-template-columns:1fr; } }
.matrix-half { border:1px solid var(--line); background:var(--paper); padding:9px 11px; }
.matrix-head { display:block; font-family:'IBM Plex Mono',monospace; font-size:9px;
  letter-spacing:.14em; color:var(--gold); border-bottom:1px solid var(--line);
  padding-bottom:5px; margin-bottom:6px; }
.matrix-row { display:flex; justify-content:space-between; align-items:baseline; gap:10px;
  font-size:12px; padding:3px 0; line-height:1.4; }
.matrix-row b { font-family:'IBM Plex Mono',monospace; font-variant-numeric:tabular-nums;
  white-space:nowrap; }
.matrix-row em { display:block; font-style:normal; font-size:10.5px; color:#6b6455; }
.matrix-row.honest b { color:var(--gain); }
.matrix-row.fraud b { color:var(--brick); }
.matrix-row.call b { color:var(--ink); }
.matrix-note { grid-column:1/-1; font-size:12px; color:#5a5344; margin:0;
  border-left:3px solid var(--gold); padding-left:11px; line-height:1.55; }

/* The building itself on the audit card. Eighteen text rows is a
   spreadsheet; eighteen houses is a board you recognise. */
.dossier { position:relative; }
.dossier-thumb { width:100%; height:92px; overflow:hidden; margin:-12px -13px 9px;
  width:calc(100% + 26px); border-bottom:1px solid var(--line); background:var(--paper-dark); }
.dossier-thumb img, .dossier-thumb svg { width:100%; height:100%; object-fit:cover; display:block; }

/* Touched or quiet — never a number. */
.permit-volume.touched { color:var(--gold); font-weight:600; }

/* ======================= THE COMMITTEE BOARD ===========================
   The permits used to be a bare grid of cards on parchment, which made the
   one mechanic where six people act against each other at once look like a
   settings page. It is now a physical object: a felt board in a brass frame
   sitting on the committee table, used both for placing tokens and for
   watching the replay, so the thing a player writes on and the thing they
   watch afterwards are recognisably the same board. */
.ornate-board { --walnut:#3a2419; --brass:#C3A24B; --brass-pale:#EADB9C; --felt:#173D34;
  position:relative; margin:4px 2px 2px; padding:24px 26px 20px; border:8px ridge #9F7A37;
  outline:3px solid #251710; outline-offset:3px; background-color:var(--felt);
  background-image:radial-gradient(circle at 12px 12px,rgba(224,204,143,.075) 0 1px,transparent 1.5px),
    linear-gradient(45deg,transparent 46%,rgba(220,199,137,.035) 47% 49%,transparent 50%),
    linear-gradient(-45deg,transparent 46%,rgba(220,199,137,.035) 47% 49%,transparent 50%);
  background-size:24px 24px,38px 38px,38px 38px;
  box-shadow:0 24px 52px rgba(0,0,0,.5), inset 0 0 0 2px #DFC678,
    inset 0 0 0 7px rgba(7,39,31,.68), inset 0 0 0 9px rgba(218,190,111,.24),
    inset 0 0 58px rgba(0,0,0,.42); }
.ornate-board::before { content:""; position:absolute; inset:13px; z-index:1;
  border:1px solid rgba(227,204,137,.58); outline:1px solid rgba(9,34,28,.8); outline-offset:4px;
  box-shadow:inset 0 0 0 3px rgba(207,174,92,.1); pointer-events:none; }
.ornate-board::after { content:"✦  ❦  ✦"; position:absolute; left:50%; bottom:5px; z-index:1;
  color:rgba(228,203,134,.55); font-family:'Fraunces',Georgia,serif; font-size:12px;
  letter-spacing:.7em; transform:translateX(-50%); pointer-events:none; }
.ornate-board > *:not(.corner) { position:relative; z-index:2; }
/* SMALL. They were 38px across with a 7px double border and a star inside,
   which at the scale the board actually renders read as four brass coins
   pinned over the corners rather than as corner furniture. Down to 15px —
   about a fifth of the area — with a solid rule instead of a double one,
   because a 7px double border inside 15px is just a filled square, and the
   star dropped for the same reason. */
.corner { position:absolute; z-index:4; width:15px; height:15px; border:2px solid var(--brass);
  background:var(--walnut); transform:rotate(45deg); box-shadow:0 0 0 1px #20130c; }
.corner-tl { left:-8px; top:-8px; } .corner-tr { right:-8px; top:-8px; }
.corner-bl { left:-8px; bottom:-8px; } .corner-br { right:-8px; bottom:-8px; }

/* THE EIGHT CITIES. York is the only market open; the row along the head of
   the board is the standing promise that it is the first of eight, which is
   cheaper to draw once here than to keep saying in copy. */
.landmark-motifs { height:50px; margin:-6px 44px 6px; display:grid;
  grid-template-columns:repeat(8,1fr); align-items:end;
  border-top:1px solid rgba(226,202,135,.28); border-bottom:1px solid rgba(226,202,135,.5);
  background:linear-gradient(90deg,transparent,rgba(221,196,125,.045) 18% 82%,transparent);
  pointer-events:none; }
.landmark { position:relative; width:46px; height:46px; display:block; justify-self:center;
  opacity:.6; filter:drop-shadow(0 1px rgba(0,0,0,.75)); }
.landmark svg { width:100%; height:100%; fill:none; stroke:#E8D397; stroke-width:1.45;
  stroke-linecap:round; stroke-linejoin:round; }
.landmark::after { content:""; position:absolute; left:8%; right:8%; bottom:3px; height:1px;
  background:linear-gradient(90deg,transparent,#D9C07A,transparent); }

.board-masthead { min-height:78px; display:grid; grid-template-columns:52px 1fr 52px;
  align-items:center; gap:10px; color:#F4EAD1; text-align:center; }
.masthead-spacer { width:48px; height:1px; }
.board-masthead span { color:var(--brass-pale); font-family:'IBM Plex Mono',monospace;
  font-size:9.5px; letter-spacing:.21em; }
.board-masthead h2 { margin:3px 0 2px; color:#FFF8E7; font-family:'Fraunces',Georgia,serif;
  font-weight:700; font-size:clamp(21px,3vw,32px); line-height:1; letter-spacing:-.025em; }
.board-masthead p { margin:0; color:#C8B988; font-family:'Fraunces',Georgia,serif;
  font-style:italic; font-size:12.5px; }

/* SMALLER AND DARKER.

   At 78px in a bright walnut-and-brass palette the gavel was the loudest
   thing on a board whose subject is the eight permits. It is furniture: it
   should say "a chair rules here" and then get out of the way. Down to
   46px, and the wood and brass both taken several stops down so it reads as
   an object resting in the shadow at the edge of the board rather than as
   an illustration of a gavel. */
.gavel-box { position:relative; width:46px; height:46px; justify-self:end;
  transform-origin:70% 72%; opacity:.82;
  filter:drop-shadow(0 3px 2px rgba(0,0,0,.5)) saturate(.65) brightness(.62); }
.ceremonial-gavel { width:46px; height:46px; overflow:visible; }
.gavel-handle-svg, .gavel-head-svg, .gavel-end-svg { fill:url(#gavel-wood); stroke:#2C170E;
  stroke-width:2; stroke-linejoin:round; }
.gavel-band-svg, .sound-block-band-svg { fill:url(#gavel-brass); stroke:#5F4312; stroke-width:1.4; }
.gavel-engraving-svg { fill:none; stroke:#E7CB83; stroke-width:1.15; stroke-linecap:round; opacity:.8; }
.gavel-gem-svg { fill:#A4432C; stroke:#F3D990; stroke-width:1.2; }
.sound-block-svg { fill:url(#gavel-wood); stroke:#2C170E; stroke-width:2; }

.board-rule { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:12px;
  margin:4px 0 16px; color:var(--brass-pale); font-family:'IBM Plex Mono',monospace;
  font-size:9px; letter-spacing:.12em; text-transform:uppercase; text-align:center; }
.board-rule span { height:1px; background:linear-gradient(90deg,transparent,var(--brass)); }
.board-rule span:last-child { background:linear-gradient(90deg,var(--brass),transparent); }
.board-footer { display:flex; flex-wrap:wrap; justify-content:center; gap:10px; margin-top:16px;
  color:#D9C98F; font-family:'IBM Plex Mono',monospace; font-size:8px; letter-spacing:.1em; }
.board-footer i { color:var(--brass); font-style:normal; }

/* The scheme's drawing. A presentation illustration when the pipeline has
   made one; a drawn elevation when it has not, so a fresh install still
   has a board rather than eight empty rectangles. */
.permit-art { position:relative; height:62px; margin:-1px -1px 6px; overflow:hidden;
  border-bottom:1px solid var(--line); background:#CCD5D3; }
.permit-art img { width:100%; height:100%; object-fit:cover; display:block; }
.permit-art.drawn { background:linear-gradient(#CBD4D2 0 58%,#A9A386 58%); }
.permit-art.drawn::before { content:""; position:absolute; left:12%; bottom:16%; width:74%; height:46%;
  background:#665C4B; box-shadow:0 6px 0 #413D34;
  clip-path:polygon(0 22%,18% 22%,18% 0,34% 0,34% 18%,68% 18%,68% 7%,84% 7%,84% 26%,100% 26%,100% 100%,0 100%); }

/* The parchment cards keep their own look, but on felt they need to read as
   paper laid on the board rather than as holes cut in it. */
.ornate-board .permit { position:relative; overflow:hidden; border-color:#8F805B;
  box-shadow:0 5px 11px rgba(0,0,0,.3), inset 0 0 0 2px #F3EDDC; }
.ornate-board .permit.t-gold { border-color:#C6A83F; }
.ornate-board .permit.t-silver { border-color:#9FA4A4; }
.ornate-board .permit.yours { box-shadow:0 5px 11px rgba(0,0,0,.3), inset 0 0 0 2px var(--gold); }

/* ---- the replay ------------------------------------------------------ */
.pc-theatre { position:relative; width:min(1180px,100%); max-height:94vh; overflow:auto;
  isolation:isolate; padding:22px 30px 26px; background:#3A2419;
  box-shadow:0 30px 70px rgba(25,16,10,.55); }
.pc-theatre::before { content:""; position:absolute; inset:12px; pointer-events:none;
  border:1px solid rgba(226,199,128,.42);
  box-shadow:inset 0 0 0 3px #2A1810, inset 0 0 0 8px rgba(197,157,75,.28),
    inset 0 0 0 11px #21130D, inset 0 0 42px rgba(0,0,0,.52); }
.wood-grain { position:absolute; inset:0; z-index:0; opacity:.9; pointer-events:none;
  background:radial-gradient(ellipse at 50% -10%,rgba(196,132,72,.25),transparent 48%),
    repeating-linear-gradient(92deg,rgba(255,255,255,.014) 0 3px,rgba(0,0,0,.038) 3px 7px,transparent 7px 16px),
    repeating-radial-gradient(ellipse at 25% 110%,transparent 0 32px,rgba(225,170,102,.1) 33px 35px,transparent 36px 55px); }
.table-light { position:absolute; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(ellipse at 50% 42%,rgba(217,181,103,.18),transparent 58%),
    linear-gradient(90deg,rgba(0,0,0,.27),transparent 10% 90%,rgba(0,0,0,.27)); }
.union-inlay { position:absolute; inset:30px; z-index:0; opacity:.16; pointer-events:none;
  background:linear-gradient(32deg,transparent 47.8%,#E4CA82 48% 48.7%,#6F261E 48.9% 50.2%,#E4CA82 50.4% 51.1%,transparent 51.3%),
    linear-gradient(-32deg,transparent 47.8%,#E4CA82 48% 48.7%,#6F261E 48.9% 50.2%,#E4CA82 50.4% 51.1%,transparent 51.3%); }
/* Only the things that sit IN the flow are lifted above the table. A
   blanket rule here clobbered position:absolute on the callout, the flying
   layer and the minutes card — the card then pushed the board down the
   page instead of landing on top of it, which is exactly the kind of fault
   no assertion catches and one screenshot does. */
.pc-theatre > .pc-head, .pc-theatre > .ornate-board, .pc-theatre > .pc-trays {
  position:relative; z-index:2; }
/* The table's own engraving. It used to float over the stage on absolute
   coordinates and struck a line straight through the status text at some
   widths; in the header row it cannot collide with anything. */
.table-inscription { display:grid; justify-items:center; gap:2px; padding:0 10px;
  color:#D9BC70; text-align:center; text-shadow:0 1px #1B0D08; pointer-events:none; }
.pc-head .table-inscription b { display:block; margin:0; font-family:'IBM Plex Mono',monospace;
  font-weight:700; font-size:9px; letter-spacing:.2em; }
.pc-head .table-inscription i { color:#9E7E45; font-style:normal;
  font-family:'IBM Plex Mono',monospace; font-size:7px; letter-spacing:.15em; }

.pc-head { display:flex; align-items:center; justify-content:space-between; gap:14px;
  flex-wrap:wrap; margin-bottom:12px; color:#EFE4C4; }
.pc-kicker { display:block; color:#C8B77E; font-family:'IBM Plex Mono',monospace;
  font-size:8.5px; letter-spacing:.18em; }
.pc-head b { display:block; margin-top:3px; font-family:'Fraunces',Georgia,serif;
  font-weight:500; font-size:15px; }
.pc-theatre .res-timer, .pc-theatre .res-mute { border-color:#8E7B4C; color:#E5D8A8;
  background:rgba(0,0,0,.25); }
.pc-close { width:28px; height:28px; padding:0; cursor:pointer; border:1px solid #8E7B4C;
  color:#E5D8A8; background:rgba(0,0,0,.25); font-family:inherit; font-size:13px; }
.pc-close:hover { background:rgba(0,0,0,.45); }

.player-callout { position:absolute; z-index:9; top:66px; left:50%; min-width:300px;
  padding:9px 20px 8px; border:1px solid var(--gold); color:#EFE4C4;
  background:rgba(18,28,25,.95); box-shadow:0 8px 24px rgba(0,0,0,.45);
  text-align:center; transform:translate(-50%,-10px); opacity:0;
  animation:callout-in .25s ease-out forwards; pointer-events:none; }
.player-callout span { display:block; color:#C8B77E; font-family:'IBM Plex Mono',monospace;
  font-size:7.5px; letter-spacing:.18em; }
.player-callout b { font-family:'Fraunces',Georgia,serif; font-size:16px; }
@keyframes callout-in { to { opacity:1; transform:translate(-50%,0); } }

.permit-grid.replay { grid-template-columns:repeat(auto-fill,minmax(168px,1fr)); }
.permit-tile { position:relative; min-width:0; padding:7px; overflow:hidden;
  border:2px solid #8F805B; color:#22251F; background:#E7DFCA;
  box-shadow:0 6px 12px rgba(0,0,0,.26), inset 0 0 0 2px #F5EFDF;
  transition:filter .25s ease, transform .25s ease, box-shadow .25s ease; }
.permit-tile::after { content:""; position:absolute; inset:0; opacity:.22; pointer-events:none;
  background-image:radial-gradient(#75694E .6px,transparent .8px); background-size:5px 5px; }
.permit-tile.t-gold { border-color:#C6A83F; box-shadow:0 6px 12px rgba(0,0,0,.26), inset 0 0 0 2px #F3DF86; }
.permit-tile.t-silver { border-color:#9FA4A4; box-shadow:0 6px 12px rgba(0,0,0,.26), inset 0 0 0 2px #D8DDDD; }
.permit-tile.t-bronze { border-color:#9A6944; box-shadow:0 6px 12px rgba(0,0,0,.26), inset 0 0 0 2px #D1A57E; }
.permit-tile .permit-art { margin:-1px -1px 5px; }
.permit-meta { display:flex; justify-content:space-between; margin:0 1px 3px; color:#80735D;
  font-family:'IBM Plex Mono',monospace; font-size:7.5px; letter-spacing:.11em; }
.permit-tile h3 { min-height:30px; margin:0; font-family:'Fraunces',Georgia,serif;
  font-weight:700; font-size:12.5px; line-height:1.15; text-wrap:balance; }
.token-well { position:relative; z-index:1; min-height:32px; display:flex; flex-wrap:wrap;
  align-items:center; gap:3px; margin-top:5px; padding:3px; border:1px inset #B5AA90;
  background:rgba(250,246,235,.62); }
.empty-well { width:100%; color:#958B76; text-align:center;
  font-family:'IBM Plex Mono',monospace; font-size:7.5px; letter-spacing:.06em; }
.board-token, .flying-token { display:grid; place-items:center; border:2px double #F4EBD5;
  border-radius:50%; color:#fff; box-shadow:0 2px 4px rgba(0,0,0,.32);
  font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:8px; }
.board-token { width:23px; height:23px; animation:token-land .22s cubic-bezier(.2,.8,.35,1.35); }
.board-token.support, .flying-token.support { background:#2F684F; }
.board-token.smear,   .flying-token.smear   { background:#A4432C; }
.board-token.veto,    .flying-token.veto    { background:#2C3E64; }
@keyframes token-land { 0% { opacity:.25; transform:scale(1.7); } 70% { transform:scale(.88); } 100% { opacity:1; transform:scale(1); } }

.tile-verdict { position:relative; z-index:1; min-height:26px; margin-top:5px; display:flex;
  align-items:center; justify-content:space-between; gap:4px; opacity:0; transform:translateY(4px); }
.tile-verdict b { font-family:'IBM Plex Mono',monospace; font-size:8px; letter-spacing:.08em; }
.tile-verdict strong { color:#2F684F; font-family:'IBM Plex Mono',monospace; font-size:12px; }
.permit-tile.resolved .tile-verdict { animation:verdict-in .25s ease-out forwards; }
.permit-tile.resolved { transform:translateY(-3px);
  box-shadow:0 9px 18px rgba(0,0,0,.36), inset 0 0 0 2px rgba(255,255,255,.45), 0 0 0 2px var(--gold); }
.permit-tile.o-vetoed { filter:saturate(.72) brightness(.74); }
.permit-tile.o-unbid, .permit-tile.o-tied { filter:grayscale(.7) brightness(.84); }
.permit-tile.o-poisoned .tile-verdict b, .permit-tile.o-poisoned .tile-verdict strong,
.permit-tile.o-vetoed .tile-verdict b { color:#A4432C; }
.permit-tile.o-unbid .tile-verdict strong, .permit-tile.o-tied .tile-verdict strong { color:#6F685B; }
@keyframes verdict-in { to { opacity:1; transform:translateY(0); } }

.resolution-stamp { position:absolute; z-index:5; right:6px; top:10px; width:54px; height:54px;
  display:grid; place-items:center; border:4px double #2F684F; border-radius:50%; opacity:0;
  color:#2F684F; background:rgba(246,239,220,.92); text-align:center;
  font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:7px; line-height:1;
  transform:rotate(-11deg) scale(1.8); pointer-events:none; }
.permit-tile.resolved .resolution-stamp { animation:stamp-tile .3s cubic-bezier(.2,.8,.35,1.35) forwards; }
.permit-tile.o-vetoed .resolution-stamp, .permit-tile.o-poisoned .resolution-stamp {
  border-color:#A4432C; color:#A4432C; }
.permit-tile.o-unbid .resolution-stamp, .permit-tile.o-tied .resolution-stamp {
  border-color:#777064; color:#777064; }
@keyframes stamp-tile { 0% { opacity:0; transform:translateY(-22px) rotate(-15deg) scale(1.8); }
  65% { opacity:1; transform:translateY(3px) rotate(-9deg) scale(.9); }
  100% { opacity:1; transform:rotate(-9deg) scale(1); } }

/* The seats. A rail rather than the four edges of a table, because a pod is
   up to six and three of them would have ended up upside down. */
.pc-trays { display:flex; flex-wrap:wrap; gap:8px; margin-top:14px; }
.player-tray { flex:1 1 170px; display:flex; align-items:center; gap:8px; padding:8px 10px;
  border:2px ridge #B18C48; color:#EEE4CA; background:#243B34; opacity:.66;
  box-shadow:0 6px 14px rgba(0,0,0,.36);
  transition:opacity .2s ease, transform .2s ease, box-shadow .2s ease; }
.player-tray small { display:block; color:#DCCB94; font-family:'IBM Plex Mono',monospace;
  font-size:7px; letter-spacing:.09em; }
.player-tray b { display:block; margin-top:2px; font-family:'Fraunces',Georgia,serif;
  font-size:12.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.player-tray > div { min-width:0; flex:1; }
.player-score { margin-left:auto; color:#F1D66E; font-family:'IBM Plex Mono',monospace;
  font-weight:700; font-size:11px; font-variant-numeric:tabular-nums; white-space:nowrap; }
.player-score.down { color:#E8927E; }
.tray-medallion { width:28px; height:28px; display:grid; place-items:center; flex:0 0 auto;
  border:3px double #E4D6AA; border-radius:50%; color:#fff; background:#77392B;
  font-family:'Fraunces',Georgia,serif; font-weight:700; font-size:12px; }
.player-tray.active { opacity:1; transform:translateY(-2px);
  box-shadow:0 6px 14px rgba(0,0,0,.36), 0 0 20px rgba(228,203,126,.6); }
.player-tray.score-hit { animation:score-hit .5s ease-out; }
@keyframes score-hit { 45% { filter:brightness(1.5);
  box-shadow:0 6px 14px rgba(0,0,0,.36), 0 0 30px rgba(241,214,110,.9); } }

.flying-layer { position:absolute; inset:0; z-index:12; pointer-events:none; }
.flying-token { position:absolute; width:34px; height:34px; will-change:transform,opacity; }
.score-orb { position:absolute; z-index:13; min-width:52px; height:30px; display:grid;
  place-items:center; padding:0 8px; border:3px double #FFF0BD; border-radius:16px;
  color:#382B12; background:linear-gradient(#FFE98B,#C99F2C);
  box-shadow:0 0 16px rgba(245,211,99,.75),0 4px 7px rgba(0,0,0,.4);
  font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:11px;
  will-change:transform,opacity; }
.score-orb.penalty { color:#FFF1DF; background:linear-gradient(#C45A3F,#7D2B20); }
.resolution-flash { position:absolute; inset:0; z-index:11; pointer-events:none; opacity:0;
  background:radial-gradient(circle,rgba(244,220,140,.75),rgba(244,220,140,0) 58%); }
.pc-theatre.ph-rulings .resolution-flash { animation:grand-flash .8s ease-out; }
.pc-theatre.ph-rulings .gavel-box { animation:gavel-strike .43s ease-in-out; }
@keyframes grand-flash { 0% { opacity:0; } 18% { opacity:1; } 100% { opacity:0; } }
@keyframes gavel-strike { 0% { transform:rotate(0); } 55% { transform:rotate(14deg) translateY(8px); } 100% { transform:rotate(0); } }

/* ---- the minutes card ------------------------------------------------ */
.final-minutes { position:absolute; z-index:20; left:50%; top:50%; width:min(660px,calc(100% - 36px));
  padding:26px 32px 28px; border:6px double var(--gold); outline:2px solid #342016; outline-offset:5px;
  color:#29271F; background:#F1E9D5; text-align:center;
  box-shadow:0 30px 80px rgba(0,0,0,.66), inset 0 0 0 1px #FFF9E9;
  transform:translate(-50%,-44%) scale(.96); opacity:0;
  animation:minutes-in .55s cubic-bezier(.2,.75,.3,1.15) forwards; }
.final-minutes::before { content:""; position:absolute; inset:8px; border:1px solid #C2AD70; pointer-events:none; }
@keyframes minutes-in { to { opacity:1; transform:translate(-50%,-50%) scale(1); } }
.minutes-kicker { color:var(--brick); font-family:'IBM Plex Mono',monospace; font-weight:700;
  font-size:8.5px; letter-spacing:.18em; }
.final-minutes h2 { margin:6px 0 5px; font-family:'Fraunces',Georgia,serif; font-weight:700; font-size:28px; }
.final-minutes p { margin:0 0 14px; color:#6D6250; font-family:'Fraunces',Georgia,serif;
  font-style:italic; font-size:13.5px; }
.score-cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px;
  padding-top:32px; max-height:44vh; overflow:auto; }
.score-card { position:relative; min-height:124px; display:grid; place-items:center;
  align-content:center; padding:17px 10px 13px; border:4px double #AA9561;
  outline:1px solid #C8B98E; outline-offset:-7px;
  background:linear-gradient(145deg,#EEE6D1,#D8CFB8 52%,#E7DECA);
  box-shadow:inset 0 0 18px rgba(91,75,42,.12),0 7px 12px rgba(52,39,21,.13); }
.score-card::before, .score-card::after { content:"◆"; position:absolute; color:#A88D51;
  font-family:'Fraunces',Georgia,serif; font-size:8px; }
.score-card::before { left:8px; top:6px; } .score-card::after { right:8px; bottom:6px; }
.score-card.yours { outline-color:var(--gold); }
.rank-medal { width:28px; height:28px; display:grid; place-items:center; border:3px double #B39B62;
  border-radius:50%; color:#766441; background:#EEE6D1; box-shadow:0 0 0 2px rgba(255,255,255,.45);
  font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:8px; }
.score-card b { margin:7px 0 1px; font-family:'Fraunces',Georgia,serif; font-weight:700; font-size:13.5px; }
.score-card small { color:#84775F; font-family:'Fraunces',Georgia,serif; font-style:italic; font-size:9.5px; }
.score-card strong { margin-top:7px; color:#2F684F; font-family:'IBM Plex Mono',monospace;
  font-size:16px; font-variant-numeric:tabular-nums; }
.score-card strong.down { color:#A4432C; }
.score-card.winner { border-color:#C59D2E; outline-color:#DFC56A;
  background:linear-gradient(145deg,#FFF1B4,#E5CB6E 48%,#F5E29B);
  box-shadow:inset 0 0 0 2px rgba(255,250,205,.65), inset 0 0 24px rgba(143,96,13,.18),
    0 8px 19px rgba(142,105,22,.28); transform:translateY(-5px);
  animation:winner-glow 1.8s .65s ease-in-out infinite; }
.score-card.winner::before, .score-card.winner::after { color:#8B6614; }
.score-card.winner .rank-medal { border-color:#896916; color:#6D500F; background:#F8E69E; }
.score-card.winner strong { color:#70510F; }
.score-card.winner small { color:#776021; letter-spacing:.04em; text-transform:uppercase; }
.winner-crown { position:absolute; left:50%; top:-44px; z-index:3; width:74px; height:56px;
  display:grid; place-items:center; transform:translateX(-50%);
  filter:drop-shadow(0 4px 3px rgba(87,57,5,.42));
  animation:crown-float 1.8s .65s ease-in-out infinite; }
.winner-crown::before { content:""; position:absolute; inset:-22px; z-index:-1; border-radius:50%;
  opacity:0; background:repeating-conic-gradient(from 0deg,rgba(255,221,89,.9) 0 3deg,transparent 4deg 16deg);
  filter:blur(.3px); animation:crown-rays 2.4s .75s linear infinite; }
.winner-crown::after { content:""; position:absolute; left:9px; right:9px; bottom:2px; height:8px;
  z-index:-1; border-radius:50%; background:rgba(158,111,13,.34); filter:blur(5px); }
.winner-crown svg { width:72px; overflow:visible; stroke:#684906; stroke-width:1.7; stroke-linejoin:round; }
.crown-body { fill:#E8B92A; } .crown-shadow { fill:#F9DC62; stroke:#9B710E; stroke-width:1.1; }
.crown-band { fill:#D8A91E; stroke:#684906; stroke-width:1.8; }
.crown-filigree { fill:none; stroke:#FFF0A1; stroke-width:1.5; }
.crown-tip { fill:#F4D04C; stroke:#6F5008; } .crown-orb { fill:#F7DC6E; stroke:#6F5008; }
.crown-jewel { stroke:#FFF3BD; stroke-width:1.2; }
.jewel-ruby { fill:#A4432C; } .jewel-sapphire { fill:#304F84; } .jewel-emerald { fill:#2F684F; }
@keyframes crown-float { 0%,100% { transform:translate(-50%,0) rotate(-2deg);
    filter:drop-shadow(0 3px 2px rgba(87,57,5,.35)) brightness(1); }
  50% { transform:translate(-50%,-4px) rotate(2deg);
    filter:drop-shadow(0 5px 8px rgba(232,186,37,.75)) brightness(1.18); } }
@keyframes crown-rays { 0% { opacity:.15; transform:rotate(0) scale(.82); } 45% { opacity:.72; }
  100% { opacity:.15; transform:rotate(360deg) scale(1.08); } }
@keyframes winner-glow { 0%,100% { box-shadow:inset 0 0 0 2px rgba(255,250,205,.65),
    inset 0 0 24px rgba(143,96,13,.18),0 8px 19px rgba(142,105,22,.28); }
  50% { box-shadow:inset 0 0 0 2px rgba(255,253,220,.9), inset 0 0 30px rgba(255,229,117,.48),
    0 8px 27px rgba(215,169,43,.58); } }

.reveal-outcome { display:inline-flex; align-items:center; gap:8px; width:100%;
  justify-content:center; margin:0 0 12px; }
.reveal-outcome span { font-size:10px; }

@media (max-width:760px) {
  .ornate-board { padding:18px 13px 16px; border-width:6px; }
  .landmark-motifs { height:36px; margin:-2px 6px 6px; }
  .landmark { width:30px; height:30px; opacity:.55; }
  .board-masthead { min-height:58px; grid-template-columns:38px 1fr 38px; }
  .masthead-spacer { width:36px; }
  .gavel-box { transform:scale(.78); transform-origin:right center; }
  .pc-theatre { padding:16px 12px 18px; }
  .table-inscription { display:none; }
  .permit-grid.replay { grid-template-columns:repeat(auto-fill,minmax(132px,1fr)); }
  .final-minutes { padding:18px 14px 20px; }
  .final-minutes h2 { font-size:22px; }
  .score-cards { grid-template-columns:1fr; padding-top:30px; }
}
@media (prefers-reduced-motion:reduce) {
  .board-token, .permit-tile.resolved .tile-verdict, .permit-tile.resolved .resolution-stamp,
  .player-callout, .final-minutes, .pc-theatre.ph-rulings .resolution-flash,
  .pc-theatre.ph-rulings .gavel-box, .player-tray.score-hit, .score-card.winner,
  .winner-crown, .winner-crown::before {
    animation-duration:.01ms !important; animation-delay:0ms !important;
    animation-iteration-count:1 !important; }
  .tile-verdict, .resolution-stamp, .player-callout, .final-minutes { opacity:1; }
  .final-minutes { transform:translate(-50%,-50%); }
}

/* ======================= THE TRADING FLOOR =============================
   Auctions and private treaty under one tab, switched here rather than in
   the main nav, so the errand is one place and the choice of instrument is
   a detail inside it. */
.floor-switch { display:flex; gap:0; margin:0 0 14px; border:1px solid var(--line);
  background:var(--paper-dark); }
.floor-tab { flex:1; display:flex; align-items:center; justify-content:center; gap:7px;
  min-height:38px; padding:0 14px; border:0; cursor:pointer; background:transparent;
  color:#6b6455; font-family:inherit; font-size:13.5px; letter-spacing:.01em; }
.floor-tab + .floor-tab { border-left:1px solid var(--line); }
.floor-tab:hover:not(.on) { background:var(--paper); }
.floor-tab.on { background:var(--forest); color:#f2efe4; font-weight:600; }
.floor-tab em { display:inline-grid; place-items:center; min-width:19px; height:19px;
  padding:0 5px; border-radius:10px; background:rgba(0,0,0,.14); color:inherit;
  font-style:normal; font-family:'IBM Plex Mono',monospace; font-size:10.5px;
  font-variant-numeric:tabular-nums; }
.floor-tab.on em { background:rgba(255,255,255,.2); }
.floor-tab em.due { background:var(--gold); color:var(--ink); font-weight:700; }
.floor-tab:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }

/* ======================= THE MAP SPOTLIGHT =============================
   The map over whatever you were reading, opening on the whole city and
   flying down to the one building. Below .modal-backdrop (100) on purpose:
   clicking the building in here still opens its deed, on top. */
.spotlight-backdrop { position:fixed; inset:0; z-index:90; display:grid; place-items:center;
  padding:16px; background:rgba(20,20,15,.62); animation:res-in .2s ease-out; }
.spotlight-box { display:flex; flex-direction:column; width:min(1180px,100%); max-height:92vh;
  border:1px solid var(--line); background:var(--paper);
  box-shadow:0 24px 60px rgba(20,16,8,.42); }
.spotlight-head { display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding:11px 16px; border-bottom:1px solid var(--line); background:var(--paper-dark); }
.spotlight-kicker { display:block; color:#9C4A3C; font-family:'IBM Plex Mono',monospace;
  font-size:9px; letter-spacing:.16em; }
.spotlight-head b { display:block; margin-top:2px; font-family:'Fraunces',Georgia,serif;
  font-size:17px; }
.spotlight-head small { display:block; margin-top:1px; color:#6b6455;
  font-family:'IBM Plex Mono',monospace; font-size:10px; letter-spacing:.08em;
  text-transform:uppercase; }
.spotlight-map { flex:1; min-height:0; overflow:auto; }
/* The map desk carries its own intro paragraph and skin picker; in here the
   city is the whole point and the rest is furniture from another room. */
.spotlight-map .map-desk > .intro, .spotlight-map .map-switch { display:none; }

/* Both links on one line under the numbers, so a card gains a verb without
   gaining a row. */
.pcard-links { display:flex; flex-wrap:wrap; align-items:center; gap:4px 14px; margin-top:6px; }
.pcard-links .sv-link { margin-top:0; }
.map-link { padding:0; border:0; background:none; cursor:pointer; font-family:inherit;
  font-size:11.5px; color:var(--navy); text-decoration:underline; }
.map-link:hover { color:var(--forest); }
.map-link:focus-visible { outline:2px solid var(--gold); outline-offset:2px; }

/* The district, named on the card. The place line above it is the
   neighbourhood; this is the quadrant it sits in. */
.pcard-district { margin-top:1px; font-family:'IBM Plex Mono',monospace; font-size:9px;
  letter-spacing:.09em; text-transform:uppercase; color:#8a8172; }

@media (max-width:640px) {
  .spotlight-backdrop { padding:0; }
  .spotlight-box { max-height:100vh; height:100%; width:100%; border:0; }
  .floor-tab { font-size:12.5px; padding:0 8px; }
}

/* The beacon over a spotlit property. It breathes rather than blinks: a
   blink competes with the map for attention, and by the time the flight
   lands the ring only has to say "this one". */
.spot-pulse { animation:spot-breathe 1.9s ease-in-out infinite; transform-box:fill-box;
  transform-origin:center; }
@keyframes spot-breathe { 0%,100% { opacity:1; transform:scale(1); }
  50% { opacity:.55; transform:scale(1.35); } }
@media (prefers-reduced-motion:reduce) { .spot-pulse { animation:none; } }

/* ======================= THE WEEKLY HONOURS ============================
   Funding grants to the three fastest-growing traders, social support to
   the three poorest, read every Sunday at 23:59. The board has to say three
   things: when, who is currently in line, and who holds one already. */
.award-clock { display:flex; flex-wrap:wrap; align-items:center; gap:14px 22px;
  margin:0 0 16px; padding:13px 16px; border:1px solid var(--line);
  border-left:3px solid var(--gold); background:var(--paper-dark); }
.award-clock-face { flex:0 0 auto; }
.award-clock-label { display:block; font-family:'IBM Plex Mono',monospace; font-size:9.5px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
.award-clock-face b { display:block; margin-top:2px; font-family:'IBM Plex Mono',monospace;
  font-size:13px; color:#6b6455; letter-spacing:.02em; }
.award-clock-face b em { font-style:normal; font-weight:700; font-size:19px; color:var(--ink);
  font-variant-numeric:tabular-nums; }
.award-clock-when { display:block; margin-top:2px; font-size:11.5px; color:var(--muted); }
.award-clock-note { flex:1 1 320px; margin:0; font-size:12.5px; line-height:1.55;
  color:#4b463a; }

/* The two marks. A diamond for money won, a lifebuoy for help given
   different shapes rather than different colours alone, because a third of
   the board is one row of a table away from being unreadable otherwise. */
.award-mark { display:inline-block; margin-left:5px; font-size:11px; line-height:1;
  vertical-align:baseline; }
.am-grant { color:var(--gold); }
.am-fastgrower { color:var(--gold); }
.am-support { color:var(--navy); }

/* Soft, not shouted. These rows are a forecast, not a result, and a loud
   highlight on "you are currently third poorest" would be a taunt. */
.lb tr.in-grant { background:rgba(176,140,30,.09); }
.lb tr.in-support { background:rgba(35,57,93,.07); }
.lb tr.in-grant.in-support { background:linear-gradient(90deg,rgba(35,57,93,.07),rgba(176,140,30,.1)); }
.lb tr.in-grant td:first-child { box-shadow:inset 3px 0 0 var(--gold); }
.lb tr.in-support td:first-child { box-shadow:inset 3px 0 0 var(--navy); }
.lb tr.in-grant.in-support td:first-child {
  box-shadow:inset 3px 0 0 var(--navy), inset 6px 0 0 -3px var(--gold); }
.lb td.lit-grant { color:#8a6e12; font-weight:600; }
.lb td.lit-support { color:var(--navy); }
.in-line-pip { margin-left:5px; font-size:10px; opacity:.85; }
.in-line-pip.is-grant { color:var(--gold); }
.in-line-pip.is-support { color:var(--navy); }

/* Who actually won it last week, read back out of the settled rows. */
.last-honours { display:flex; flex-wrap:wrap; align-items:center; gap:6px 14px;
  margin:0 0 14px; padding:9px 14px; border:1px solid var(--line); background:var(--paper);
  font-size:12.5px; }
.lh-label { font-family:'IBM Plex Mono',monospace; font-size:9.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); }
.lh-row { display:inline-flex; align-items:baseline; gap:5px; }
.lh-row b { font-weight:600; }
.lh-row em { font-style:normal; font-family:'IBM Plex Mono',monospace; font-size:11px;
  color:var(--muted); }
.lh-row.k-grant em { color:#8a6e12; }

@media (max-width:640px) {
  .award-clock { flex-direction:column; align-items:flex-start; gap:10px; }
  .award-clock-note { flex-basis:auto; }
}

/* ================= THE BLUFF'S TWO BOARDS =============================
   The same furniture as the Planning Committee, in two tones. The audit
   board is felt, because it is a board the room plays on together; File a
   Survey is ivory, because it is a document one person fills in and signs.
   Sharing the frame is the point: both are the Gaming Council, and before
   this they were two plain cards that looked like settings panels. */
.council-card.bare { padding:0; border:0; background:none; }
.council-card.bare .ornate-board { margin:0 0 2px; }

.ornate-board.tone-ivory { --felt:#EFE8D6; --brass:#A08A4E; --brass-pale:#7A6838;
  border-color:#B9A874; outline-color:#6E6141; color:#26251F;
  background-image:radial-gradient(circle at 12px 12px,rgba(120,101,58,.07) 0 1px,transparent 1.5px),
    linear-gradient(45deg,transparent 46%,rgba(120,101,58,.045) 47% 49%,transparent 50%),
    linear-gradient(-45deg,transparent 46%,rgba(120,101,58,.045) 47% 49%,transparent 50%);
  box-shadow:0 16px 34px rgba(60,48,20,.22), inset 0 0 0 2px #C9B98A,
    inset 0 0 0 7px rgba(255,253,245,.75), inset 0 0 0 9px rgba(160,138,78,.3),
    inset 0 0 44px rgba(150,130,80,.16); }
.ornate-board.tone-ivory::before { border-color:rgba(122,104,56,.45);
  outline-color:rgba(255,253,245,.8); box-shadow:inset 0 0 0 3px rgba(160,138,78,.08); }
.ornate-board.tone-ivory::after { color:rgba(140,119,63,.55); }
.ornate-board.tone-ivory .corner { background:#8A7A4C; border-color:#A08A4E; }

/* The board's own masthead — a rule, a name, a line. Deliberately quieter
   than the committee's: these are two panels on a tab, not the object the
   whole evening is about. */
.frame-head { text-align:center; padding:2px 0 0; }
.frame-head span { display:block; font-family:'IBM Plex Mono',monospace; font-size:8.5px;
  letter-spacing:.2em; color:var(--brass-pale); }
.frame-head h3 { margin:3px 0 1px; font-family:'Fraunces',Georgia,serif; font-weight:700;
  font-size:22px; letter-spacing:-.015em; color:#FFF8E7; }
.frame-head p { margin:0; font-family:'Fraunces',Georgia,serif; font-style:italic;
  font-size:12px; color:#C8B988; }
.tone-ivory .frame-head span { color:#8A7647; }
.tone-ivory .frame-head h3 { color:#2A2820; }
.tone-ivory .frame-head p { color:#6E6449; }
.tone-ivory .board-rule { color:#8A7647; }
.tone-ivory .board-rule span { background:linear-gradient(90deg,transparent,#A08A4E); }
.tone-ivory .board-rule span:last-child { background:linear-gradient(90deg,#A08A4E,transparent); }
.tone-ivory .board-footer { color:#8A7647; }
.tone-ivory .board-footer i { color:#A08A4E; }

.board-note { margin:0 0 12px; font-size:12.5px; line-height:1.55; color:#CBD8CD;
  text-align:center; }
.tone-ivory .board-note { color:#5C543F; }
.empty.on-felt { border-color:rgba(226,202,135,.28); color:#B7C6B6;
  background:rgba(0,0,0,.14); }

/* The dossiers are paper laid on the felt, the same way the permits are. */
.audit-board .dossier { border-color:#8F805B; background:var(--paper);
  box-shadow:0 5px 11px rgba(0,0,0,.3), inset 0 0 0 2px #F3EDDC; }
.audit-board .dossier.called { box-shadow:0 5px 11px rgba(0,0,0,.3), inset 0 0 0 2px var(--gold); }

/* The form on ivory keeps the game's own controls; only the ground moved. */
.survey-board .field > span { color:#5C543F; }
.survey-board .field input, .survey-board .field select, .survey-board .field textarea {
  background:#FBF7EC; border-color:#B9A874; }
.survey-board .estate-note, .survey-board .register-foot { color:#6E6449; }
.survey-board .muted { color:#6E6449; }

/* THE TAGS IN THE FIELD REPORT.

   A .tag draws its word and its rule in the category's own colour, which is
   picked to sit on parchment. On the map desk's dark green ground every one
   of the eleven fails a contrast check — measured against #152e27 they run
   from 1.47:1 (Residential) to 2.24:1 (Retail), where 4.5:1 is the floor.
   "Residential" was effectively invisible.

   Everything else in the panel is fine: body text 11.5:1, muted 8.3:1, the
   block labels 6.7:1. So the ground stays — it is the map desk's identity —
   and the tags get a pale chip to sit on instead, which keeps the colour
   coding doing its job and puts all eleven between 5.3:1 and 9.5:1. */
.map-desk .map-side .tag {
  color:#20261F; background:#EFE9D8; border-color:rgba(32,38,31,.22);
  padding:2px 7px; font-weight:600;
  box-shadow:inset 3px 0 0 var(--tag-color);
  padding-left:10px;
}

/* A labelled switch row in the account panel: the control, then a name and
   a line saying what it does. The explanation is part of the control, not a
   footnote under it. */
.account-block { margin:18px 0 0; padding-top:14px; border-top:1px solid var(--line); }
.account-block h4 { margin:0 0 8px; font-family:'Fraunces',Georgia,serif; font-size:14px; }
.switch-row { display:flex; align-items:flex-start; gap:10px; cursor:pointer; }
.switch-row input { width:17px; height:17px; margin:2px 0 0; flex:0 0 auto; cursor:pointer;
  accent-color:var(--forest); }
.switch-row b { display:block; font-weight:600; font-size:13.5px; }
.switch-row em { display:block; margin-top:2px; font-style:normal; font-size:11.5px;
  line-height:1.5; color:var(--muted); }
.switch-row input:disabled { cursor:not-allowed; opacity:.45; }
.switch-row input:disabled ~ span { opacity:.5; }

/* THE SOUNDTRACK'S CONTROLS. Indented to sit under the switch's TEXT rather
   than its box — 27px is the 17px checkbox plus the row's 10px gap — so the
   volume plainly belongs to the music line above it and not to the mute
   switch above that.

   The fallback in var(--muted, #6b6455) is not belt and braces: --muted is
   currently used 25 times in this file and defined nowhere, so a bare
   var(--muted) inherits the parent's colour instead of the grey it is asking
   for. Four other rules already carry this fallback. */
.music-now { margin:10px 0 0 27px; padding:10px 12px; border:1px solid var(--line);
  background:var(--paper); display:flex; flex-wrap:wrap; align-items:center; gap:10px 18px; }
.music-piece b { display:block; font:600 13px 'Fraunces', serif; }
.music-piece span { display:block; margin-top:1px; font:9.5px 'IBM Plex Mono', monospace;
  letter-spacing:.11em; color:var(--muted, #6b6455); }
.music-vol { display:flex; align-items:center; gap:8px; margin-left:auto; }
.music-vol > span { font:10px 'IBM Plex Mono', monospace; letter-spacing:.1em;
  color:var(--muted, #6b6455); text-transform:uppercase; }
.music-vol input[type=range] { width:116px; accent-color:var(--forest); cursor:pointer; }
.music-vol b { font:600 12px 'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums;
  min-width:34px; text-align:right; }

/* ---- THE TACTICS DECK -------------------------------------------------
   One card, three sizes, one set of rules. Everything inside scales from
   --cw (the card's width) via em, so a card in hand, a card in the Combat
   Library and a card being inspected are the same object at three sizes
   rather than three hand-tuned components that drift apart.

   The rarity owns the outline, exactly as it owns .pcard's frame above.
   The colour and the ring's thickness are set inline from the server
   catalogue, which reads lib/cards.js — one list, three views. */
.tcard { --cw: 284px; position:relative; display:block; flex:none; text-align:left;
  width:var(--cw); height:calc(var(--cw) / 0.7136); font-size:calc(var(--cw) * 0.0437);
  background:#161f55; border:8px solid var(--ring, var(--line)); overflow:hidden; padding:0;
  font-family:'IBM Plex Sans', sans-serif; box-shadow:0 10px 22px rgba(20,24,20,.28); }
.tcard.size-mid  { --cw: 200px; }
.tcard.size-hand { --cw: 168px; }
.tcard.is-clickable { cursor:pointer; transition:transform .12s ease, box-shadow .12s ease; }
.tcard.is-clickable:hover { transform:translateY(-3px); box-shadow:0 16px 30px rgba(20,24,20,.36); }
/* SELECTED IS A LIFT AND A CHALK GLOW, NEVER GOLD. Aaron, 27 Sep 2026: the
   gold ring a selected card kept read as "this card is rare", because gold
   IS the rare ring. A selection must not borrow any rarity colour (grey,
   gold, claret, violet), so it is the paper's own cream, lifted clear. */
.tcard.is-selected { transform:translateY(-8px);
  box-shadow:0 0 0 2px rgba(243,238,225,.92), 0 0 22px 4px rgba(243,238,225,.32), 0 18px 32px rgba(20,24,20,.4); }
.tcard.is-clickable.is-selected:hover { transform:translateY(-10px); }
.tcard.is-dimmed { opacity:.45; }
.tcard:focus-visible { outline:2px dashed rgba(243,238,225,.95); outline-offset:4px; }

/* Bled a pixel past the box on every side. Asked for a chromolithograph,
   the generator draws one faithfully — including the pale paper margin a
   real lithographic plate leaves round its image. That margin is in the
   file, so it has to be cropped rather than positioned away. */
.tcard-art { position:absolute; top:-3%; left:-3%; width:106%; height:106%;
  object-fit:cover; display:block; border:0; background:transparent; }
.tcard-art-blank { background:linear-gradient(160deg,#22307e,#0c1233 70%); top:0; left:0; width:100%; height:100%; }
.tcard-keyline { position:absolute; inset:.5em; border:1px solid var(--brass, #C9B98A); opacity:.55; pointer-events:none; }
.tcard-corner { position:absolute; width:.75em; height:.75em; border:1.5px solid var(--brass, #C9B98A);
  transform:rotate(45deg); opacity:.8; }
.tcard-corner.bl { bottom:.72em; left:.72em; } .tcard-corner.br { bottom:.72em; right:.72em; }
.tcard-ribbon { position:absolute; top:0; right:0; background:var(--ribbon); color:var(--rink, #fff);
  font-family:'IBM Plex Mono', monospace; font-size:.77em; letter-spacing:.11em; text-transform:uppercase;
  padding:.32em .8em .4em; border-bottom-left-radius:.72em; }
.tcard-badge { position:absolute; top:1.3em; left:1.45em; font-family:'IBM Plex Mono', monospace;
  font-size:.97em; font-weight:600; color:#fff3da; background:rgba(12,16,48,.75);
  border:1px solid var(--rtint, var(--ring)); padding:.24em .56em; font-variant-numeric:tabular-nums; }
/* A pill, not a pillar. `bottom: calc(100% - 100%)` resolved to bottom:0,
   which together with a top offset stretched this down the whole card. */
.tcard-armed { position:absolute; top:4.2em; left:1.45em; z-index:5;
  font-family:'IBM Plex Mono', monospace; font-size:.77em; letter-spacing:.16em;
  background:var(--gain); color:#fff; padding:.24em .6em; line-height:1.5; }
.tcard-plate { position:absolute; left:0; right:0; bottom:0; display:flex; flex-direction:column; gap:.5em;
  padding:4.5em 1.6em 1.8em;
  background:linear-gradient(to bottom, rgba(14,18,54,0) 0%, rgba(14,18,54,.88) 42%, rgba(14,18,54,.98) 100%); }
.tcard-kind { font-family:'IBM Plex Mono', monospace; font-size:.77em; letter-spacing:.15em;
  text-transform:uppercase; color:var(--rtint, var(--ring)); }
.tcard-name { font-family:'Fraunces', serif; font-weight:700; font-size:1.7em; line-height:1.1; color:#fff3da; }
.tcard-text { font-size:1em; line-height:1.5; color:#bcc4ec; }

/* ---- the Combat Library ---- */
.library { background:var(--paper); border:1px solid var(--ink); max-width:1180px; width:min(1180px, 96vw);
  max-height:92vh; overflow:auto; box-shadow:0 30px 70px rgba(20,24,20,.42); }
.library-head { display:flex; gap:20px; align-items:flex-start; justify-content:space-between;
  padding:22px 24px 16px; border-bottom:2px solid var(--ink); background:var(--paper); }
/* Not frozen any more (Aaron, 28 Sep 2026): pinned to the top, the cards'
   magnifiers scrolled up over the words. It scrolls away with the page. */
.library-head h2 { font-family:'Fraunces', serif; font-weight:700; font-size:26px; margin:2px 0 8px; }
.library-head .kicker { font-family:'IBM Plex Mono', monospace; font-size:10.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--muted, #6b6455); margin:0; }
.library-sub { margin:0; max-width:64ch; font-size:13.5px; line-height:1.6; color:#3c3a30; }
.library-filters { display:flex; gap:7px; align-items:center; flex-wrap:wrap; padding:14px 24px;
  border-bottom:1px solid var(--line); }
.library-filters .chip { font-family:'IBM Plex Mono', monospace; font-size:11px; letter-spacing:.08em;
  text-transform:uppercase; padding:5px 11px; border:1px solid var(--line); background:var(--paper);
  color:#6b6455; cursor:pointer; }
.library-filters .chip.on { background:var(--forest); color:#f2efe4; border-color:var(--forest); }
.library-filter-gap { width:12px; }
.library-count { margin-left:auto; font-family:'IBM Plex Mono', monospace; font-size:11px; color:#948a72; }
.library-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(200px, 1fr)); gap:22px; padding:22px 24px 34px; }
.library-item { margin:0; display:flex; flex-direction:column; gap:9px; align-items:center; }
.library-item figcaption { font-size:12.5px; line-height:1.5; color:#3c3a30; text-align:center; }
.library-item figcaption b { display:block; font-weight:600; color:var(--ink); }
.library-item figcaption i { display:block; color:var(--muted, #6b6455); font-size:11.5px; margin-top:3px; }
.library-starter { display:block; margin-top:5px; font-style:normal; font-family:'IBM Plex Mono', monospace;
  font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--forest); }
@media (max-width: 560px) {
  .library-head { flex-direction:column; }
  .library-grid { grid-template-columns:repeat(auto-fill, minmax(160px, 1fr)); gap:16px; padding:16px; }
}

/* ---- THE EVENING RECKONING --------------------------------------------
   Aaron's war-table study, reduced to the parts that carry information. The
   ceremony in the original — searchlights, alert lamps, a grid reference —
   was right for a standalone study and wrong here: this plays after every
   order a player seals, so anything that is decoration rather than evidence
   becomes something to sit through. What is left says who, through what,
   and to what effect. */
.reckoning { --oak:#3f2418; --felt:#28594c; --brass:#cba94e; --ivory:#f4eddc;
  background:linear-gradient(180deg, #4a2c1d, var(--oak)); border:1px solid #21140d;
  width:min(920px, 96vw); max-height:92vh; overflow:auto; padding:26px 26px 22px;
  display:flex; flex-direction:column; gap:18px; color:var(--ivory);
  box-shadow:0 34px 75px rgba(24,14,8,.55); }
.reck-head { text-align:center; display:flex; flex-direction:column; gap:6px; }
.reck-head span { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.2em; color:var(--brass); }
.reck-head h3 { font-family:'Fraunces', serif; font-weight:700; font-size:25px; margin:0; text-wrap:balance; }

.reck-line { display:grid; grid-template-columns:minmax(150px,1fr) minmax(220px,1.5fr) minmax(170px,1fr);
  gap:16px; align-items:stretch; background:rgba(20,46,38,.55); border:1px solid rgba(203,169,78,.3); padding:16px; }
@media (max-width: 760px) { .reck-line { grid-template-columns:1fr; } }

.reck-packet { display:flex; flex-direction:column; gap:6px; justify-content:center;
  background:rgba(12,24,20,.6); border-left:3px solid var(--brass); padding:12px 14px; }
.reck-packet small, .reck-target span, .reck-value span { font-family:'IBM Plex Mono', monospace;
  font-size:9.5px; letter-spacing:.16em; color:#9fb4a8; }
.reck-packet-name { font-family:'Fraunces', serif; font-size:18px; line-height:1.15; }
.reck-packet em { font-style:normal; font-size:11.5px; color:#c3d2c9; }

.reck-route { position:relative; display:flex; flex-direction:column; gap:8px; justify-content:center; padding:6px 0; }
.reck-rail { position:relative; height:3px; background:rgba(203,169,78,.18); overflow:hidden; }
.reck-fill { position:absolute; inset:0 auto 0 0; background:var(--brass); transition:width .5s ease; }
.reck-stage { display:grid; grid-template-columns:auto 1fr auto; gap:9px; align-items:center;
  border:1px solid rgba(203,169,78,.28); padding:7px 10px; background:rgba(10,20,17,.5);
  transition:border-color .3s ease, background .3s ease; }
.reck-stage span { font-family:'IBM Plex Mono', monospace; font-size:10px; color:var(--brass); }
.reck-stage b { font-family:'IBM Plex Mono', monospace; font-size:10.5px; letter-spacing:.12em; }
.reck-stage small { font-family:'IBM Plex Mono', monospace; font-size:9px; letter-spacing:.14em; color:#8fa89c; }
.reck-stage.breached { border-color:rgba(203,169,78,.75); background:rgba(72,127,110,.4); }
.reck-stage.breached small { color:var(--brass); }
.reck-stage.open { grid-template-columns:1fr; text-align:center; border-style:dashed; }
.reck-counter { display:grid; grid-template-columns:auto 1fr; gap:9px; align-items:center;
  border:1px solid #cba94e; background:rgba(158,59,42,.5); padding:8px 11px; }
.reck-counter span { display:grid; place-items:center; width:20px; height:20px; border-radius:50%;
  background:var(--brass); color:#20241f; font-weight:700; font-size:12px; }
.reck-counter b { font-family:'Fraunces', serif; font-size:14px; }
.reck-counter small { grid-column:1 / -1; font-family:'IBM Plex Mono', monospace; font-size:9px;
  letter-spacing:.16em; color:#f0d9a6; }

.reck-target { margin:0; display:flex; flex-direction:column; gap:10px; justify-content:center;
  background:rgba(12,24,20,.6); border-right:3px solid var(--brass); padding:12px 14px; }
.reck-target figcaption { display:flex; flex-direction:column; gap:3px; }
.reck-target strong { font-family:'Fraunces', serif; font-size:16px; line-height:1.2; }
.reck-value { display:flex; align-items:baseline; gap:7px; flex-wrap:wrap;
  font-family:'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; }
.reck-value b { font-size:15px; }
.reck-value i { color:var(--brass); font-style:normal; }
.reck-after { color:#ef9a8d; }

.reck-banner { text-align:center; display:flex; flex-direction:column; gap:6px;
  border-top:1px solid rgba(203,169,78,.3); padding-top:16px; }
.reck-banner small { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.2em; color:var(--brass); }
.reck-banner strong { font-family:'Fraunces', serif; font-size:19px; }
.reck-banner p { margin:0; font-size:13.5px; line-height:1.55; color:#cfdcd4; max-width:56ch; margin-inline:auto; }
.reck-position { font-style:normal; font-family:'IBM Plex Mono', monospace; font-size:10.5px;
  letter-spacing:.12em; color:#9fb4a8; }
.reckoning.mode-success.is-resolved .reck-banner strong { color:#ffd98a; }
.reckoning.mode-shield.is-resolved .reck-banner strong { color:#8fe0c4; }
.reckoning.mode-denied.is-resolved .reck-banner strong { color:#f2b3a6; }
.reckoning .btn { align-self:center; }
@media (prefers-reduced-motion: reduce) { .reck-fill, .reck-stage { transition:none; } }

/* ---- sealed and settled orders ---- */
.order-list { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:6px; }
.order-line { display:grid; grid-template-columns:minmax(120px,1.1fr) minmax(100px,1fr) auto auto;
  gap:12px; align-items:center; padding:9px 12px; border:1px solid var(--line); background:var(--paper-dark); }
.order-line b { font-weight:600; font-size:13.5px; }
.order-line span { font-size:12.5px; color:#5a5346; }
.order-line em { font-style:normal; font-family:'IBM Plex Mono', monospace; font-size:10.5px;
  letter-spacing:.1em; text-transform:uppercase; }
.order-line.sealed { border-left:3px solid var(--gold); }
.order-line.sealed em { color:#8a7a52; }
.order-line.landed { border-left:3px solid var(--loss); }
.order-line.landed em { color:var(--loss); }
.order-line.stopped { border-left:3px solid var(--gain); }
.order-line.stopped em { color:var(--gain); }
@media (max-width: 620px) { .order-line { grid-template-columns:1fr auto; } .order-line span { grid-column:1 / -1; } }

/* ---- the tactics tab --------------------------------------------------
   The shape of the screen follows the shape of the decision: what you are
   holding, what it would cost, who it happens to — in that order. */
.tactics-deck { display:flex; flex-direction:column; gap:26px; }
/* The masthead, in the Portfolio's shape (one band, hairline divisions, a
   serif figure) and the navy of the card backs. The Portfolio's tan is held
   back for the clock, the one figure here that runs out; the hand is shown
   card by card in the colour of what each kind does. */
.deck-strip { --ds-navy:#1E2A5E; --ds-tan:#E4BA8E; --ds-label:#A9B6E0; --ds-cream:#F2EDE0;
  display:grid; grid-template-columns:repeat(4, minmax(92px,1fr)) minmax(170px,1.5fr) auto;
  background:linear-gradient(180deg, #23316B, var(--ds-navy)); border:1px solid #141C42;
  box-shadow:0 10px 26px rgba(20,28,66,.22); }
.deck-strip .ds-tile { display:grid; align-content:start; gap:7px; padding:16px 18px 18px;
  border-left:1px solid rgba(169,182,224,.18); min-width:0; }
.deck-strip .ds-tile:first-child { border-left:0; }
.deck-strip .ds-label { font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ds-label); }
.deck-strip .ds-value { font-family:'Fraunces', serif; font-weight:700; font-size:22px; line-height:1.1;
  color:var(--ds-cream); letter-spacing:-.01em; font-variant-numeric:tabular-nums; }
.deck-strip .ds-value em { font-style:normal; font-weight:500; font-size:14px; color:var(--ds-label); }
.deck-strip .ds-value span { font:inherit; letter-spacing:inherit; color:inherit; }
.deck-strip .ds-foot { font-size:11.5px; line-height:1.35; color:rgba(242,237,224,.62); }
.deck-strip .ds-pips { display:flex; gap:5px; }
.deck-strip .ds-pips b { width:13px; height:18px; border-radius:2px; border:1.5px solid rgba(169,182,224,.45); }
.deck-strip .ds-pips b.on { background:var(--ds-cream); border-color:var(--ds-cream); box-shadow:inset 0 0 0 2px #23316B; }
/* The hand by kind of card: the colours of what each one does. */
.deck-strip .ds-pips b.k-attack { background:#F08F6E; border-color:#F08F6E; }
.deck-strip .ds-pips b.k-shield { background:#8FD9C4; border-color:#8FD9C4; }
.deck-strip .ds-pips b.k-info { background:#9CC3F0; border-color:#9CC3F0; }
.deck-strip .ds-pips b.k-self { background:#C9B3EE; border-color:#C9B3EE; }
.deck-strip .ds-stack { display:block; position:relative; height:18px; }
.deck-strip .ds-stack b { position:absolute; top:0; width:13px; height:18px; border-radius:2px;
  background:#2E3E82; border:1.5px solid rgba(242,237,224,.7); }
.deck-strip .ds-stack b:nth-child(1) { left:0; } .deck-strip .ds-stack b:nth-child(2) { left:6px; }
.deck-strip .ds-stack b:nth-child(3) { left:12px; } .deck-strip .ds-stack b:nth-child(4) { left:18px; }
.deck-strip .ds-stack b:nth-child(5) { left:24px; }
.deck-strip .ds-feature { box-shadow:inset 0 3px 0 var(--ds-tan); background:rgba(228,186,142,.06); }
.deck-strip .ds-feature .ds-value { color:var(--ds-tan); }
.deck-strip .ds-lib { align-content:center; }
.deck-strip .ds-lib-btn { background:transparent; color:var(--ds-cream); border:1px solid rgba(242,237,224,.5); white-space:nowrap; }
.deck-strip .ds-lib-btn:hover:not(:disabled) { background:rgba(242,237,224,.1); }
@media (max-width: 760px) {
  .deck-strip { grid-template-columns:repeat(2,1fr); }
  .deck-strip .ds-tile { border-left:0; border-top:1px solid rgba(169,182,224,.18); padding:13px 16px 15px; }
  .deck-strip .ds-tile:nth-child(even) { border-left:1px solid rgba(169,182,224,.18); }
  .deck-strip .ds-tile:nth-child(-n+2) { border-top:0; }
  .deck-strip .ds-feature, .deck-strip .ds-lib { grid-column:1 / -1; border-left:0 !important; }
  .deck-strip .ds-value { font-size:20px; }
}

.deck-section { display:flex; flex-direction:column; gap:12px; }
.deck-head { display:flex; flex-direction:column; gap:5px; }
.deck-head-row { flex-direction:row; align-items:center; justify-content:space-between; gap:12px; }
.deck-head h3 { font-family:'Fraunces', serif; font-weight:700; font-size:20px; margin:0; }
.deck-head p, .deck-sub { margin:0; font-size:13.5px; line-height:1.6; color:#5a5346; max-width:70ch; }
.deck-empty { margin:0; font-size:13px; color:#786e5a; font-style:italic; }
.deck-error { margin:0; }

.hand-row { display:flex; gap:16px; align-items:flex-start; overflow-x:auto; padding-bottom:6px; }
.hand-row.wrap { flex-wrap:wrap; overflow:visible; }
/* ARMED, OUTSIDE THE CARD (28 Sep 2026). A solid bar the width of the card,
   above it, so it reads as a state of the card and not part of its art. The
   spacer keeps every card in the row on one top line when any is armed. */
.hand-slot { flex:0 0 auto; display:flex; flex-direction:column; gap:6px; }
.hand-armed, .hand-armed-space { display:none; }
.hand-row.has-armed .hand-armed, .hand-row.has-armed .hand-armed-space { display:flex; height:30px; }
.hand-armed { align-items:center; justify-content:center; gap:7px; border-radius:6px;
  background:var(--gain); color:#fff; font:700 13px 'IBM Plex Mono', monospace; letter-spacing:.16em;
  text-transform:uppercase; box-shadow:0 2px 0 rgba(0,0,0,.18); }
.hand-armed svg { width:15px; height:15px; flex:0 0 auto; }
.market-item { margin:0; display:flex; flex-direction:column; gap:9px; align-items:stretch; flex:none; }
.market-item .btn { width:100%; }

/* The order desk: only ever on screen when a card is in the player's hand
   and picked up, so it can be loud without being in the way. */
.deck-order { border:1px solid var(--ink); background:var(--paper-dark); padding:18px 20px;
  display:flex; flex-direction:column; gap:14px; }
.order-row { display:flex; flex-wrap:wrap; gap:14px; align-items:flex-end; }
.order-field { display:flex; flex-direction:column; gap:5px; min-width:190px; }
.order-field span { font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.13em;
  text-transform:uppercase; color:#786e5a; }
.order-field select { padding:9px 11px; font-size:14px; border:1px solid var(--line);
  background:var(--paper); font-family:inherit; }
.order-quote { display:flex; flex-direction:column; gap:3px; border-left:3px solid var(--gold);
  padding:2px 0 2px 12px; min-width:220px; }
.order-quote span { font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.13em; color:#786e5a; }
.order-quote strong { font-size:14px; }
.order-quote em { font-style:normal; font-size:12px; line-height:1.5; color:#5a5346; }
.order-note { flex-basis:100%; margin:0; font-size:12.5px; line-height:1.6; color:#6b6455; max-width:74ch; }
/* A full width box around the last note, so the note keeps its reading
   measure without being seated beside the seal button. */
.order-foot { flex:0 0 100%; }

/* ---- the auction clock ---- */
.auction-clock { display:grid; grid-template-columns:auto 1fr; align-items:baseline; gap:2px 12px;
  margin:10px 0; padding:8px 12px; border-left:3px solid #2f6f5e; background:rgba(47,111,94,.08); }
.auction-clock-label { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.13em;
  text-transform:uppercase; color:#5d6b63; }
.auction-clock-figure { font-family:'IBM Plex Mono', monospace; font-size:22px; font-weight:600;
  font-variant-numeric:tabular-nums; color:#1f2a24; justify-self:end; }
.auction-clock-bar { grid-column:1 / -1; height:3px; background:rgba(0,0,0,.08); overflow:hidden; }
.auction-clock-bar i { display:block; height:100%; background:#2f6f5e; }
.auction-clock-note { grid-column:1 / -1; font-style:normal; font-size:12px; color:#7a2d1f; }
.auction-clock.is-closing { border-left-color:#b7791f; background:rgba(183,121,31,.10); }
.auction-clock.is-closing .auction-clock-bar i { background:#b7791f; }
.auction-clock.is-final, .auction-clock.is-closed { border-left-color:#a33a24; background:rgba(163,58,36,.10); }
.auction-clock.is-final .auction-clock-figure { color:#a33a24; }
.auction-clock.is-final .auction-clock-bar i { background:#a33a24; }
@media (prefers-reduced-motion: no-preference) {
  .auction-clock.is-final .auction-clock-figure { animation:auctionPulse 1s ease-in-out infinite; }
}
@keyframes auctionPulse { 50% { opacity:.55; } }
@media (max-width: 620px) { .order-field { min-width:100%; } }

/* ---- TWO ROOMS THAT MEET ----------------------------------------------
   The tab was one column of identical sections, which made buying a card and
   playing one feel like the same act. They are not: one is your own table,
   the other is somebody else's stall — so they get different ground, and they
   share an edge rather than floating as two panels. You look up from your
   hand and the market is simply there, in the dark, on the other side.

   THE TEXTURE IS DRAWN, NOT DOWNLOADED. A flat gradient reads as a coloured
   box; felt and canvas need grain. That grain is an inline SVG turbulence
   filter as a data URI — no file to fetch, nothing to 404, nothing added to
   the page weight worth measuring, and it keeps the promise that this game
   ships no assets it does not draw itself. */
.deck-rooms {
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  border:1px solid var(--ink); overflow:hidden; isolation:isolate;
  box-shadow:0 18px 44px rgba(18,28,22,.34);
}
.deck-table, .deck-bazaar { position:relative; isolation:isolate;
  padding:26px 24px 30px; display:flex; flex-direction:column; gap:22px; }

/* THE TABLE. Green baize under a low lamp: a pool of light where the hand
   is, the nap of the cloth in two directions, and the rail of the table
   catching the light along the top edge. */
.deck-table { color:#E9E5D7;
  background:
    radial-gradient(130% 78% at 42% -14%, rgba(255,238,196,.20), transparent 60%),
    radial-gradient(90% 60% at 85% 118%, rgba(0,0,0,.34), transparent 60%),
    linear-gradient(174deg, #2A6153 0%, #1E4B3F 46%, #143028 100%);
}
.deck-table::before, .deck-bazaar::before {           /* the grain */
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background-image:var(--grain); background-size:180px 180px;
  mix-blend-mode:overlay; opacity:.32;
}
.deck-table::after {                                   /* the nap of the baize */
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.5;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,.035) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(0deg,  rgba(0,0,0,.05)       0 1px, transparent 1px 4px);
}
.deck-table > * { position:relative; z-index:1; }

/* THE SEAM. The table's edge, then a drop into the dark. A brass rule for
   the rail, a warm highlight on the lip of it, and an inner shadow beneath
   so the stall reads as being lower and further away rather than simply
   being a second box in a different colour. */
.deck-bazaar { color:#F2EAD7;
  border-top:1px solid rgba(203,169,78,.5);
  box-shadow:inset 0 1px 0 rgba(255,222,150,.22), inset 0 22px 34px rgba(0,0,0,.5);
  background:
    radial-gradient(76% 52% at 50% -6%, rgba(247,178,74,.30), transparent 62%),
    radial-gradient(120% 90% at 50% 116%, rgba(0,0,0,.55), transparent 64%),
    linear-gradient(178deg, #532F1D 0%, #3A2013 52%, #1F1109 100%);
}
.deck-bazaar::after {                                  /* awning canvas */
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.4;
  background:
    repeating-linear-gradient(104deg, rgba(0,0,0,.14) 0 2px, transparent 2px 11px),
    repeating-linear-gradient(0deg, rgba(255,214,150,.05) 0 1px, transparent 1px 6px);
}
.deck-bazaar > * { position:relative; z-index:1; }

/* Type inside both rooms, which is otherwise ink on a dark ground. */
.deck-table .deck-head h3, .deck-bazaar .deck-head h3 { color:#FFF4DC;
  text-shadow:0 1px 0 rgba(0,0,0,.35); }
.deck-table .deck-head p, .deck-table .deck-sub, .deck-table .order-note { color:#C9D6CC; }
.deck-bazaar .deck-head p, .deck-bazaar .deck-sub, .deck-bazaar .order-note { color:#DCCBAE; }
.deck-table .deck-empty { color:#9FB4A8; }
.deck-bazaar .deck-empty { color:#B8A78B; }
.deck-table .order-field span, .deck-bazaar .order-field span { color:#AEC0B5; }
.deck-table .order-quote span { color:#AEC0B5; }
.deck-table .order-quote strong, .deck-table .order-quote em { color:#E9E5D7; }

/* The order desk is a docket laid on the cloth, not a page. */
.deck-table .deck-order { background:rgba(8,22,17,.55); border:1px solid rgba(203,169,78,.42);
  box-shadow:0 8px 20px rgba(0,0,0,.3); }
.deck-table .deck-order .btn { background:var(--gold); color:#20261F; border-color:#755C0F; }
.deck-table .deck-order .btn:hover:not(:disabled) { background:#DDB73A; }

/* On the stall, a purchase button has to look like money changing hands. */
/* Verdigris, not gold (Aaron, 27 Sep 2026): gold is the rare card's ring,
   and a gold button beside the cards made it look like one more of them.
   A copper roof gone green reads well on the stall's brown canvas. */
.deck-bazaar .btn { background:#2F7D6B; color:#F4EFE2; border-color:#1C5246; font-weight:600;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18); }
.deck-bazaar .btn:hover:not(:disabled) { background:#389A84; }
.deck-bazaar .btn:disabled { background:transparent; color:#B8A78B; border-color:#7A6244; opacity:1; }
.deck-table .btn.secondary, .deck-bazaar .btn.secondary { color:#EFE7D5; border-color:rgba(203,169,78,.5); }
.deck-table .btn.secondary:hover:not(:disabled), .deck-bazaar .btn.secondary:hover:not(:disabled) {
  background:rgba(255,255,255,.08); }

/* ---- the magnifier ----------------------------------------------------
   The rules text IS the card, and at hand size it is legible only to somebody
   who already knows what it says — which is nobody in their first week. */
/* Under the rarity ribbon rather than over the rules text, which is the one
   thing on the card this button exists to let you read. */
.tcard-zoom { position:absolute; right:.6em; top:2.9em; z-index:6; display:grid; place-items:center;
  width:1.9em; height:1.9em; padding:0; cursor:pointer; color:#20261F;
  background:var(--brass, #C9B98A); border:1px solid rgba(0,0,0,.45); border-radius:50%;
  opacity:.82; transition:opacity .12s ease, transform .12s ease; }
.tcard-zoom:hover { opacity:1; transform:scale(1.08); }
.tcard-zoom:focus-visible { outline:2px solid #fff; outline-offset:2px; opacity:1; }

.card-zoom { display:flex; gap:26px; align-items:flex-start; background:var(--paper);
  border:1px solid var(--ink); padding:26px; max-width:min(760px, 96vw); max-height:92vh; overflow:auto;
  box-shadow:0 30px 70px rgba(20,24,20,.45); }
.card-zoom-side { display:flex; flex-direction:column; gap:10px; min-width:0; }
.card-zoom-side .kicker { font-family:'IBM Plex Mono', monospace; font-size:10.5px; letter-spacing:.15em;
  text-transform:uppercase; margin:0; }
.card-zoom-side h3 { font-family:'Fraunces', serif; font-weight:700; font-size:24px; margin:0; }
.card-zoom-text { margin:0; font-size:15px; line-height:1.6; color:var(--ink); }
.card-zoom-flavour { margin:0; font-family:'Fraunces', serif; font-style:italic; font-size:13.5px;
  line-height:1.5; color:#6b6455; border-left:2px solid var(--line); padding-left:11px; }
.card-zoom-facts { margin:6px 0 0; display:flex; flex-direction:column; gap:7px; }
.card-zoom-facts div { display:flex; gap:10px; align-items:baseline; justify-content:space-between;
  border-bottom:1px dotted var(--line); padding-bottom:5px; }
.card-zoom-facts dt { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:#786e5a; }
.card-zoom-facts dd { margin:0; font-size:13px; text-align:right; }
.card-zoom .btn { align-self:flex-start; margin-top:6px; }
@media (max-width: 680px) {
  .card-zoom { flex-direction:column; align-items:center; padding:18px; }
  .deck-table, .deck-bazaar { padding:16px 14px 20px; }
}

/* ---- THE PORTFOLIO, AS PARTICULARS ------------------------------------
   Aaron's palette: #364F45 deep green, #CBC1A9 and #D3C6B3 warm stone,
   #E4BA8E tan, #513725 walnut.

   The brief was "a premium property listing page", which is a discipline
   rather than a decoration: an agent's particulars are expensive-looking
   because of what they leave out. So this is deliberately the opposite of
   the tactics table next door — no grain, no lamplight, no theatre. The
   money is spent on space, on one serif at a size nothing else on the page
   uses, and on a single accent held back for the figure that matters. */
.portfolio { --pf-green:#364F45; --pf-stone:#CBC1A9; --pf-linen:#D3C6B3;
  --pf-tan:#E4BA8E; --pf-walnut:#513725;
  display:flex; flex-direction:column; gap:20px; }

/* The masthead. One band of green across the top, the way particulars put
   the agent's mark above the property. */
.portfolio .portfolio-total { display:grid; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
  gap:0; margin:0; background:var(--pf-green); border:1px solid #223028;
  box-shadow:0 10px 26px rgba(28,40,34,.18); }
.portfolio .portfolio-total .block { border-left:1px solid rgba(203,193,169,.2);
  border-top:0; padding:18px 20px 20px; display:grid; align-content:start; gap:7px; }
.portfolio .portfolio-total .block:first-child { border-left:0; }
.portfolio .portfolio-total .label { font-family:'IBM Plex Mono', monospace; font-size:9.5px;
  letter-spacing:.18em; text-transform:uppercase; color:#A8BCAF; }
.portfolio .portfolio-total .value { font-family:'Fraunces', serif; font-weight:700; font-size:22px;
  color:#F2EDE0; letter-spacing:-.01em; font-variant-numeric:tabular-nums; }
/* The one figure worth putting a colour on. */
.portfolio .portfolio-total .feature .value { color:var(--pf-tan); }
.portfolio .portfolio-total .feature { box-shadow:inset 0 3px 0 var(--pf-tan); }

/* A holding. White particulars on linen, a hairline rule, and a walnut
   serif for the address — the only place this size of type appears. */
.portfolio .card { background:#FCFAF4; border:1px solid var(--pf-stone); border-left:3px solid var(--pf-walnut);
  padding:20px 22px; margin:0; box-shadow:0 2px 0 rgba(203,193,169,.5); transition:box-shadow .14s ease; }
.portfolio .card:hover { box-shadow:0 8px 22px rgba(81,55,37,.14); }
.portfolio .card h3 { font-family:'Fraunces', serif; font-weight:700; font-size:21px; line-height:1.2;
  color:var(--pf-walnut); margin:0 0 7px; letter-spacing:-.01em; }
.portfolio .card h3:hover { color:#7A5637; }
.portfolio .card .meta { display:flex; align-items:center; gap:8px; flex-wrap:wrap; font-size:13px;
  color:#6B6455; margin-bottom:6px; }
.portfolio .card .rent-line { font-size:13.5px; color:#3F4A42; padding-top:10px; margin-top:10px;
  border-top:1px solid var(--pf-stone); }
.portfolio .card .rent-line strong { color:var(--pf-walnut); }
.portfolio .card .rent-line.overhead-line, .rent-line.overhead-line { border-top:0; padding-top:0; margin-top:2px; }
.portfolio .card .muted { font-family:'IBM Plex Mono', monospace; font-size:10.5px; letter-spacing:.1em;
  text-transform:uppercase; color:#8A8271; }
.portfolio .card .ability-line { background:rgba(228,186,142,.16); border-left:2px solid var(--pf-tan);
  padding:8px 11px; margin-top:10px; font-size:12.5px; }
.portfolio .empty { background:#FCFAF4; border:1px dashed var(--pf-stone); padding:34px;
  text-align:center; color:#8A8271; font-family:'Fraunces', serif; font-style:italic; font-size:15px; }
@media (max-width: 560px) {
  .portfolio .card { padding:16px; }
  .portfolio .portfolio-total .block { padding:14px 16px; }
}

/* The photograph on a holding. Particulars lead with the building — a column
   of addresses and percentages is an accounts page, not a portfolio. */
.portfolio .card-row { display:flex; gap:20px; align-items:flex-start; flex-wrap:wrap; }
.pf-shot { flex:0 0 232px; width:232px; padding:0; border:1px solid var(--pf-stone);
  background:var(--pf-linen); cursor:pointer; overflow:hidden; line-height:0;
  box-shadow:0 2px 0 rgba(203,193,169,.6); transition:box-shadow .14s ease, transform .14s ease; }
.pf-shot:hover { box-shadow:0 10px 24px rgba(81,55,37,.2); transform:translateY(-2px); }
.pf-shot:focus-visible { outline:2px solid var(--pf-tan); outline-offset:2px; }
.pf-shot img, .pf-shot svg { display:block; width:100%; height:auto; aspect-ratio:3/2; object-fit:cover; }
.portfolio .card h3.pf-title { cursor:pointer; display:inline-block;
  border-bottom:2px solid transparent; transition:border-color .14s ease, color .14s ease; }
.portfolio .card h3.pf-title:hover { border-bottom-color:var(--pf-tan); }
.portfolio .card h3.pf-title:focus-visible { outline:2px solid var(--pf-tan); outline-offset:3px; }
@media (max-width: 620px) { .pf-shot { flex-basis:100%; width:100%; } }

/* A masthead figure carries a caption now, because "3 of 5" is a number and
   "2 need attention" is a reason to click something. */
.portfolio .portfolio-total .value em { font-style:normal; font-family:'IBM Plex Sans', sans-serif;
  font-weight:400; font-size:14px; color:#9FB4A8; }
.portfolio .portfolio-total .foot { font-size:11.5px; line-height:1.4; color:#94AC9F; margin-top:1px; }
.portfolio .portfolio-total .feature .foot { color:#D9BC97; }

/* THE ABILITY IS THE REASON TO OWN THE BUILDING, so in the deed it is set
   like a heading rather than a footnote — it was previously the smallest
   thing in a modal full of numbers. */
.modal-inner .ability-line { margin:12px 0 4px; padding:13px 15px; font-size:15px; line-height:1.55;
  background:rgba(228,186,142,.18); border:1px solid rgba(176,140,30,.4); border-left:3px solid var(--gold); }
.modal-inner .ability-line strong { display:block; font-family:'Fraunces', serif; font-weight:700;
  font-size:18px; letter-spacing:-.005em; color:#513725; margin-bottom:3px; }
.modal-inner .ability-line.off { background:rgba(120,110,90,.1); border-color:var(--line);
  border-left-color:#948A72; }
.modal-inner .ability-line.off strong { color:#6b6455; }
.modal-inner .ability-line .set-count { display:inline-block; margin-top:5px;
  font-family:'IBM Plex Mono', monospace; font-size:13px; font-weight:600; letter-spacing:.06em; }

/* The Market Heat key answers a different question at each zoom, so it also
   has to say which one you are not looking at. */
.map-key .key-note { font-style:italic; opacity:.7; font-size:10px; margin-top:2px; }

/* ---- THE GAZETTE ------------------------------------------------------

   The paper is Aaron's, built in tools/gazette-workbench.html against the
   real DOM and dropped in whole. It is a broadsheet rather than a beige
   panel: a masthead with a volume line and a price, section heads with a
   running head on each, the briefs set as bordered classifieds, the day's
   items as justified copy under a rule, and a deckle edge clipped into the
   sheet itself.

   Measured before it went in. Every piece of body copy clears 8:1 against
   the ground it sits on and the smallest type on the page clears 4.6:1; the
   one exception is the repeated THE YORK GAZETTE running head at 3.2:1,
   which is furniture rather than information — it says nothing the masthead
   has not already said, and a running head that shouted would be wrong.

   Everything below is scoped to .gaz-* and touches nothing else on the
   Gaming Council tab. --------------------------------------------------- */

.gaz-paper { position:relative; padding:22px 24px 26px; margin:10px 0 14px;
  color:#26201A; background:
    radial-gradient(ellipse at 18% 8%, rgba(160,132,82,.10), transparent 46%),
    radial-gradient(ellipse at 84% 92%, rgba(120,96,58,.10), transparent 44%),
    linear-gradient(#F3ECD9, #E9DFC5);
  border:1px solid #BCAE85;
  box-shadow:inset 0 0 44px rgba(126,102,58,.14), 0 2px 10px rgba(40,32,18,.12); }
/* A fibrous tooth, so the ground reads as paper and not as a beige box. */
.gaz-paper::before { content:""; position:absolute; inset:0; pointer-events:none; opacity:.5;
  background:repeating-linear-gradient(94deg, rgba(120,98,56,.05) 0 1px, transparent 1px 4px),
             repeating-linear-gradient(3deg, rgba(120,98,56,.04) 0 1px, transparent 1px 6px); }
.gaz-paper > * { position:relative; }

.gaz-masthead { text-align:center; margin-bottom:16px; padding-bottom:10px;
  border-bottom:3px double #A8996F; }
.gaz-masthead b { display:block; font-family:'Fraunces',Georgia,serif; font-weight:700;
  font-size:31px; letter-spacing:.04em; color:#1D1811; }
.gaz-masthead em { display:block; margin-top:3px; font-style:normal;
  font-family:'IBM Plex Mono',monospace; font-size:9.5px; letter-spacing:.17em;
  text-transform:uppercase; color:#7C6E4E; }

.gaz-head { margin:20px 0 4px; padding-bottom:4px; border-bottom:1px solid #C6B78E;
  font-family:'IBM Plex Mono',monospace; font-size:9.5px; letter-spacing:.2em;
  text-transform:uppercase; color:#7A6B47; }
.gaz-standfirst { margin:6px 0 10px; font-size:13px; color:#554B38; max-width:62ch; }
.gaz-empty { margin:8px 0; font-size:13px; font-style:italic; color:#6E634C; }

/* The notices. Two columns of small ads, which is exactly what they are. */
.gaz-briefs { display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); gap:1px;
  background:#C9BB94; border:1px solid #C9BB94; }
.gaz-brief { padding:9px 12px 10px; background:#F2EAD5; }
.gaz-brief b { display:block; font-family:'Fraunces',Georgia,serif; font-size:14.5px; }
.gaz-brief p { margin:2px 0 0; font-size:12.5px; line-height:1.45; color:#4C4231; }
.gaz-brief.is-picked { background:#EDE3C7; box-shadow:inset 3px 0 0 #8A7A4E; }
/* Yours is marked, because there is no game in hiding it from you. */
.gaz-brief.is-mine { background:#EFE7CB; box-shadow:inset 3px 0 0 var(--forest); }
.gaz-yours { display:inline-block; margin-top:5px; padding:1px 6px;
  border:1px solid var(--forest); color:var(--forest);
  font-family:'IBM Plex Mono',monospace; font-size:8px; letter-spacing:.13em;
  text-transform:uppercase; }

.gaz-hand, .gaz-filed { display:flex; gap:14px; align-items:flex-start; margin-top:14px;
  padding:12px 14px; background:#EEE5CA; border:1px solid #C3B58C; }
.gaz-hand b, .gaz-filed b { font-family:'Fraunces',Georgia,serif; font-size:15px; }
.gaz-hand p, .gaz-filed p { margin:3px 0 0; font-size:12.5px; color:#4C4231; max-width:60ch; }
.gaz-hand-kicker { display:block; font-family:'IBM Plex Mono',monospace; font-size:8px;
  letter-spacing:.14em; text-transform:uppercase; color:#8A7A52; }

/* The seal. It breathes while the column is open and is struck still the
   moment it is filed — the whole of its job is to say which of those two
   states you are in, from across the room. */
.gaz-seal { flex:0 0 auto; width:38px; height:38px; border-radius:50%;
  background:radial-gradient(circle at 34% 30%, #B4432F, #8C2E20 58%, #6B2115);
  box-shadow:inset 0 -2px 4px rgba(0,0,0,.35), 0 1px 3px rgba(40,20,12,.4);
  animation:gaz-seal-breathe 3.4s ease-in-out infinite; }
.gaz-seal.is-set { animation:none; background:radial-gradient(circle at 34% 30%, #8E5B4A, #6E3B2D 58%, #522619); }
/* An impression in the wax rather than a plain disc — a ring and a bar,
   which is as much as a 38px seal can carry and still read as pressed. */
.gaz-seal::after { content:""; position:absolute; inset:9px; border-radius:50%;
  border:1px solid rgba(255,225,210,.3);
  box-shadow:inset 0 1px 1px rgba(0,0,0,.35), 0 1px 0 rgba(255,220,200,.16); }
.gaz-seal { position:relative; }
.gaz-seal.is-set::after { border-color:rgba(255,225,210,.18); }
@keyframes gaz-seal-breathe {
  0%,100% { transform:scale(1); box-shadow:inset 0 -2px 4px rgba(0,0,0,.35), 0 1px 3px rgba(40,20,12,.4); }
  50% { transform:scale(1.05); box-shadow:inset 0 -2px 4px rgba(0,0,0,.35), 0 0 11px rgba(176,66,46,.5); }
}

.gaz-day { margin-top:10px; }
.gaz-day h5 { margin:0 0 3px; font-family:'Fraunces',Georgia,serif; font-size:13px;
  color:#3B3324; border-bottom:1px solid #D6C9A4; padding-bottom:2px; }
.gaz-day ul { margin:0; padding:0; list-style:none;
  columns:2; column-gap:26px; column-rule:1px solid #D9CCA8; }
.gaz-day li { font-size:12.5px; line-height:1.5; color:#463D2D;
  break-inside:avoid; padding:1px 0; }
.gaz-day li b { font-weight:600; color:#241E15; }

.gaz-column { display:grid; grid-template-columns:repeat(auto-fit,minmax(215px,1fr));
  gap:8px 16px; margin:8px 0 12px; }
.gaz-column label { display:flex; flex-direction:column; gap:3px; font-size:12.5px; }
.gaz-column label span { font-family:'Fraunces',Georgia,serif; font-size:13.5px; color:#2A2318; }
.gaz-column select { font:inherit; font-size:12.5px; padding:4px 6px; color:#26201A;
  background:#F7F1E0; border:1px solid #B6A77E; }
.gaz-act { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.gaz-act .hint { margin:0; max-width:52ch; }

/* The ladder, as a ledger rather than a chart — six numbers do not need a
   chart, and the only thing a reader wants from it is "what do I lose by
   waiting", which is two rows and today picked out. */
.gaz-ladder { margin-top:12px; border-collapse:collapse; font-size:12px;
  font-family:'IBM Plex Mono',monospace; font-variant-numeric:tabular-nums; }
.gaz-ladder th { text-align:right; padding:3px 10px 3px 0; font-weight:500;
  font-size:9.5px; letter-spacing:.11em; text-transform:uppercase; color:#7A6B47; }
.gaz-ladder td { padding:3px 9px; text-align:center; border-left:1px solid #D6C9A4; }
.gaz-ladder td.now { background:#E4D8B4; color:#1D1811; font-weight:600; }

.gaz-settled ul.gaz-truth { margin:8px 0 0; padding:0; list-style:none; }
.gaz-truth li { padding:4px 0 4px 10px; font-size:13px; border-bottom:1px dotted #CDBF9A;
  border-left:3px solid transparent; }
.gaz-truth li.right { border-left-color:var(--gain); }
.gaz-truth li.wrong { border-left-color:var(--loss); }
.gaz-truth em { font-style:normal; font-family:'Fraunces',Georgia,serif; }
.gaz-truth span { color:#7A6B47; font-size:12px; }

@media (max-width:620px) {
  .gaz-paper { padding:16px 14px 20px; }
  .gaz-masthead b { font-size:24px; }
  .gaz-day ul { columns:1; }
}
@media (prefers-reduced-motion: reduce) { .gaz-seal { animation:none; } }

/* Gazette study 01 — an identifiable York broadsheet rather than a beige panel. */
.gaz-paper {
  --gaz-ink:#201d18;
  --gaz-muted:#665d4b;
  --gaz-rule:#7c6c4e;
  --gaz-oxblood:#63251f;
  isolation:isolate;
  padding:29px 34px 34px;
  color:var(--gaz-ink);
  background-color:#eee6d2;
  background-image:
    radial-gradient(circle at 14% 17%,rgba(129,93,43,.075),transparent 22%),
    radial-gradient(circle at 81% 72%,rgba(115,79,36,.06),transparent 25%),
    linear-gradient(92deg,transparent 0 48.8%,rgba(92,72,42,.055) 49.6%,rgba(255,255,255,.16) 50%,transparent 50.8%),
    repeating-linear-gradient(4deg,rgba(101,78,42,.028) 0 1px,transparent 1px 11px),
    linear-gradient(165deg,#f5efde 0%,#ece3cd 53%,#e6dac0 100%);
  border:1px solid #9d8c68;
  border-top:9px solid var(--gaz-oxblood);
  box-shadow:0 20px 36px rgba(41,31,18,.2),0 3px 7px rgba(41,31,18,.16),
    inset 0 0 0 4px rgba(255,252,238,.38),inset 0 0 70px rgba(104,77,36,.09);
  clip-path:polygon(0 .3%,4% 0,9% .2%,15% 0,22% .18%,29% 0,38% .16%,47% 0,
    55% .2%,63% 0,72% .16%,81% 0,90% .2%,96% 0,100% .3%,99.8% 99.6%,
    94% 100%,87% 99.78%,79% 100%,70% 99.8%,61% 100%,52% 99.76%,43% 100%,
    34% 99.8%,25% 100%,16% 99.78%,8% 100%,.2% 99.6%);
}
.gaz-paper::before {
  z-index:0;
  opacity:.36;
  background:
    repeating-linear-gradient(93deg,rgba(73,55,30,.045) 0 1px,transparent 1px 7px),
    repeating-linear-gradient(2deg,rgba(74,54,27,.032) 0 1px,transparent 1px 13px),
    radial-gradient(circle at 30% 40%,transparent 0 1px,rgba(85,59,28,.05) 1.4px,transparent 2px);
  background-size:auto,auto,19px 17px;
  mix-blend-mode:multiply;
}
.gaz-paper::after {
  content:"";
  position:absolute;
  z-index:0;
  inset:13px;
  pointer-events:none;
  border:1px solid rgba(83,66,39,.2);
  box-shadow:inset 0 0 0 1px rgba(255,252,236,.35);
  /* THE YORK WATERMARK GOES HERE, AS A DATA URI.

     The study referenced gazette-york-watermarks-v1.svg as a separate file.
     It is parked rather than shipped for one reason: a stylesheet that needs
     a second file to look right is a stylesheet that can be deployed
     half-finished, and this project lost an afternoon to exactly that this
     morning. The paper grain a few hundred lines up is already an inline
     data:image/svg+xml — the watermark goes in the same way, and then the
     Gazette is one file that either arrives or does not.

     One command drops it in, and the slot below is what it replaces:

       python3 tools/inline-svg.py art/gazette-york-watermarks-v1.svg GAZ-WATERMARK-SLOT

     The slot is a comment on a line of its own rather than the last line
     of this one. A marker sharing a line with this block's closing
     delimiter would leave the whole block unterminated the moment it was
     replaced — and writing that sentence with the delimiter spelled out
     in it closed this comment early and ate the rule below, which is how
     the watermark came to be invisible the first time it went in. */
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 900' aria-hidden='true'%3E%3Cg fill='none' stroke='%236d5838' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg opacity='.12' stroke-width='2'%3E%3Cpath d='M35 76h180M985 76h180M35 824h180M985 824h180'/%3E%3Cpath d='M35 66v20m12-14v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8m12-8v8'/%3E%3Cpath d='M1165 66v20m-12-14v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8m-12-8v8'/%3E%3C/g%3E%3Cg opacity='.10' stroke-width='2.2' transform='translate(516 52)'%3E%3Cpath d='M16 54h152l-10 31H26Z'/%3E%3Cpath d='M23 53 7 13l43 25L65 3l27 33 27-33 15 35 43-25-16 40'/%3E%3Cpath d='M38 66h108M49 75h86'/%3E%3Ccircle cx='7' cy='13' r='5'/%3E%3Ccircle cx='65' cy='3' r='5'/%3E%3Ccircle cx='119' cy='3' r='5'/%3E%3Ccircle cx='177' cy='13' r='5'/%3E%3C/g%3E%3Cg opacity='.085' stroke-width='2.8' transform='translate(600 466)'%3E%3Ccircle r='136'/%3E%3Ccircle r='119' stroke-dasharray='2 9'/%3E%3Cg%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(72)'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(144)'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(216)'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(288)'/%3E%3C/g%3E%3Cg transform='rotate(36) scale(.72)'%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(72)'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(144)'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(216)'/%3E%3Cpath d='M0-31C-22-69-19-112 0-128c19 16 22 59 0 97Z' transform='rotate(288)'/%3E%3C/g%3E%3Ccircle r='28'/%3E%3Ccircle r='14'/%3E%3C/g%3E%3Cg opacity='.11' stroke-width='2' transform='translate(822 212)'%3E%3Cpath d='M8 231h314M34 231V104h66v127M230 231V104h66v127M111 231V73h108v158'/%3E%3Cpath d='m31 104 12-18h48l12 18M227 104l12-18h48l12 18M108 73l16-22h82l16 22'/%3E%3Cpath d='M48 86V48h38v38M244 86V48h38v38M139 51V20h52v31'/%3E%3Cpath d='M44 48h46M240 48h46M135 20h60M52 48V31m10 17V25m12 23V31M248 48V31m10 17V25m12 23V31'/%3E%3Cpath d='M145 231v-74c0-33 40-33 40 0v74M51 128h32v46H51zM247 128h32v46h-32z'/%3E%3Ccircle cx='165' cy='116' r='25'/%3E%3Ccircle cx='165' cy='116' r='16'/%3E%3Cpath d='M165 91v50M140 116h50m-43-18 36 36m0-36-36 36'/%3E%3Cpath d='M22 231c23-14 44-14 67 0m153 0c23-14 44-14 67 0'/%3E%3C/g%3E%3Cg opacity='.105' stroke-width='2.2' transform='translate(54 620)'%3E%3Cpath d='M0 170h330M18 170V84h42v86M270 170V84h42v86M60 170V113h210v57'/%3E%3Cpath d='M14 84h12V70h13v14h13V70h12v14M266 84h12V70h13v14h13V70h12v14'/%3E%3Cpath d='M60 113h18V98h18v15h18V98h18v15h18V98h18v15h18V98h18v15h18V98h18v15h18V98h14'/%3E%3Cpath d='M137 170v-28c0-36 56-36 56 0v28M29 112h18v30H29zM283 112h18v30h-18z'/%3E%3Cpath d='M164 98V34m-17 20 17-20 17 20M137 62h54'/%3E%3C/g%3E%3Cg opacity='.13' stroke-width='1.8'%3E%3Cg transform='translate(112 252) scale(.42)'%3E%3Ccircle r='78'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(72)'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(144)'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(216)'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(288)'/%3E%3Ccircle r='12'/%3E%3C/g%3E%3Cg transform='translate(1085 705) scale(.42)'%3E%3Ccircle r='78'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(72)'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(144)'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(216)'/%3E%3Cpath d='M0-18C-14-43-12-68 0-78c12 10 14 35 0 60Z' transform='rotate(288)'/%3E%3Ccircle r='12'/%3E%3C/g%3E%3C/g%3E%3Cg opacity='.12' stroke-width='1.5'%3E%3Cpath d='M430 828h340M458 817h284'/%3E%3Cpath d='M420 828l20-10-8 10 8 10Zm360 0-20-10 8 10-8 10Z'/%3E%3C/g%3E%3C/g%3E%3Cg fill='%236d5838' opacity='.09' font-family='Georgia,serif' text-anchor='middle'%3E%3Ctext x='600' y='624' font-size='17' letter-spacing='8'%3EEBORACUM%3C/text%3E%3Ctext x='600' y='648' font-size='10' letter-spacing='5'%3ECIVITAS · MERCATURA · FIDES%3C/text%3E%3Ctext x='987' y='467' font-size='11' letter-spacing='3'%3EYORK MINSTER%3C/text%3E%3Ctext x='217' y='819' font-size='11' letter-spacing='3'%3ETHE CITY WALLS%3C/text%3E%3C/g%3E%3C/svg%3E") center top/100% auto no-repeat;
}
.gaz-paper > * { z-index:1; }

.gaz-masthead {
  position:relative;
  margin:-2px 0 21px;
  padding:17px 94px 13px;
  border-top:4px double var(--gaz-ink);
  border-bottom:4px double var(--gaz-ink);
}
.gaz-masthead::before,.gaz-masthead::after {
  position:absolute;
  top:50%;
  width:76px;
  color:var(--gaz-oxblood);
  transform:translateY(-50%);
  font:600 8px 'IBM Plex Mono',monospace;
  letter-spacing:.12em;
  line-height:1.35;
}
.gaz-masthead::before { content:"VOL. VI\A EST. YORK"; left:5px; white-space:pre; text-align:left; }
.gaz-masthead::after { content:"EVENING EDITION\A ✦  ✦  ✦"; right:5px; white-space:pre; text-align:right; }
.gaz-masthead b {
  font-size:40px;
  line-height:1;
  letter-spacing:-.015em;
  color:#171510;
  text-shadow:.7px .7px 0 rgba(99,37,31,.16);
}
.gaz-masthead b::before,.gaz-masthead b::after {
  content:"✦";
  display:inline-block;
  margin:0 13px;
  color:var(--gaz-oxblood);
  font-size:16px;
  vertical-align:middle;
}
.gaz-masthead em {
  margin-top:8px;
  color:#544c3e;
  font-size:8.5px;
  letter-spacing:.19em;
}

/* THE LEADER.

   The city's own comment, in the biggest type on the page after the
   masthead, and it sits above the briefs because nothing in it is
   evidence. Every other block on this paper is a predicate over somebody's
   log; this one is a total over the whole field and names nobody, so no
   hand gains by reading it first and no hand loses by skipping it. The
   words come from lib/leader.js, which cannot reach a trader's name. */
.gaz-leader-block {
  margin:14px 0 0;
  padding:12px 10px 13px;
  border-top:1px solid rgba(69,57,37,.34);
  border-bottom:1px solid rgba(69,57,37,.34);
  text-align:center;
}
.gaz-lead-kicker {
  display:block;
  margin-bottom:5px;
  font-family:'IBM Plex Mono',monospace;
  font-size:7.5px;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:#8a7d63;
}
.gaz-lead-head {
  margin:0;
  font-family:'Fraunces',Georgia,serif;
  font-weight:700;
  font-size:27px;
  line-height:1.14;
  color:#1d1811;
  text-wrap:balance;
}
.gaz-lead-body {
  margin:8px auto 0;
  max-width:60ch;
  font-family:'Fraunces',Georgia,serif;
  font-size:13.5px;
  line-height:1.55;
  color:#3f392f;
  /* Centred text with a ragged last line reads as a mistake rather than a
     choice, and this is only ever two or three lines long. */
  text-wrap:balance;
}

.gaz-head {
  position:relative;
  margin:24px 0 7px;
  /* Room on the right for the masthead label, so a long heading wraps
     rather than running into it ("The week on the Exchange", 1 Oct 2026). */
  padding:5px 100px 4px 8px;
  border-top:2px solid var(--gaz-ink);
  border-bottom:1px solid var(--gaz-ink);
  color:#2b2720;
  background:rgba(68,56,37,.035);
  font-size:9px;
  letter-spacing:.24em;
}
.gaz-head::after {
  content:"THE YORK GAZETTE";
  position:absolute;
  right:8px;
  color:#8a7d63;
  font-size:6.5px;
  letter-spacing:.13em;
}
.gaz-head::before { content:"✤"; margin-right:8px; color:var(--gaz-oxblood); font-size:10px; }
.gaz-standfirst {
  max-width:none;
  padding:0 8px 10px;
  border-bottom:1px solid rgba(69,57,37,.34);
  color:#3f392f;
  font-family:'Fraunces',Georgia,serif;
  font-size:14px;
  line-height:1.45;
  text-align:center;
}
.gaz-standfirst::first-letter { color:var(--gaz-oxblood); font-size:22px; font-weight:700; }

.gaz-briefs {
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:0;
  border:2px solid #6e6046;
  background:transparent;
  box-shadow:inset 0 0 0 3px rgba(255,250,232,.36);
}
.gaz-brief {
  min-height:106px;
  padding:13px 14px 12px;
  background:rgba(247,241,222,.48);
  border-right:1px solid #aa9a76;
  border-bottom:1px solid #aa9a76;
}
.gaz-brief:nth-child(3n) { border-right:0; }
.gaz-brief:nth-last-child(-n+3) { border-bottom:0; }
.gaz-brief b {
  padding-bottom:4px;
  border-bottom:1px solid rgba(81,66,42,.35);
  color:#252119;
  font-size:15px;
  line-height:1.15;
}
.gaz-brief p { margin-top:6px; color:#4b4335; line-height:1.4; }
.gaz-brief.is-picked { background:rgba(229,218,188,.72); box-shadow:inset 4px 0 0 #8a7a4e; }
.gaz-brief.is-mine {
  position:relative;
  background:linear-gradient(145deg,rgba(235,229,205,.92),rgba(224,214,181,.82));
  box-shadow:inset 4px 0 0 var(--forest),inset 0 0 20px rgba(51,76,54,.07);
}
.gaz-brief.is-mine::after {
  content:"PRIVATE COPY";
  position:absolute;
  right:7px;
  bottom:7px;
  color:rgba(31,75,63,.45);
  font:600 6px 'IBM Plex Mono',monospace;
  letter-spacing:.12em;
  transform:rotate(-5deg);
}
.gaz-yours { padding:2px 6px; border:1px double var(--forest); background:rgba(247,243,225,.45); }

.gaz-hand,.gaz-filed {
  position:relative;
  max-width:720px;
  margin:20px auto 17px;
  padding:16px 22px 16px 72px;
  border:1px dashed #857555;
  border-left:7px solid var(--gaz-oxblood);
  background:
    repeating-linear-gradient(0deg,rgba(84,64,34,.035) 0 1px,transparent 1px 9px),
    linear-gradient(145deg,#f4ecd6,#e8dcc0);
  box-shadow:4px 7px 12px rgba(57,43,22,.14);
  transform:rotate(-.25deg);
}
.gaz-hand::before,.gaz-filed::before {
  content:"CONFIDENTIAL";
  position:absolute;
  right:13px;
  top:9px;
  color:rgba(99,37,31,.5);
  font:600 7px 'IBM Plex Mono',monospace;
  letter-spacing:.17em;
  transform:rotate(2deg);
}
.gaz-hand .gaz-seal,.gaz-filed .gaz-seal { position:absolute; left:17px; top:50%; width:43px; height:43px; transform:translateY(-50%); }
/* 8px letterspaced caps on the darker end of the card's own gradient came
   out at 3.9:1 — under AA for small text, and this line is the one that
   tells a player the brief is theirs alone. Two steps darker clears it at
   5.3:1 and changes nothing anybody would notice. */
.gaz-hand-kicker { color:#665537; }
.gaz-hand b,.gaz-filed b { color:#2a241b; font-size:17px; }

.gaz-day {
  padding:7px 9px 10px;
  border-bottom:1px solid #9d8c69;
}
.gaz-day h5 {
  display:flex;
  align-items:center;
  gap:10px;
  color:#252118;
  border-bottom:0;
  font-size:15px;
}
.gaz-day h5::after { content:""; flex:1; height:1px; background:#978765; }
.gaz-day ul { column-gap:34px; column-rule:1px solid #9f8f6d; }
.gaz-day li { padding:3px 7px 3px 0; color:#3f382c; text-align:justify; }
.gaz-day li::before { content:"▪"; margin-right:6px; color:var(--gaz-oxblood); }

.gaz-column {
  /* 180px, not 215px: five rivals then sit on ONE row. auto-fit collapses
     the tracks it does not fill, so this is five columns on a desktop and
     still wraps on a phone — where at 215px the fifth name dropped to a row
     of its own beside three empty, borderless cells. */
  grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  gap:0;
  border-top:1px solid #9c8b67;
  border-left:1px solid #9c8b67;
}
.gaz-column label {
  min-height:76px;
  padding:9px 10px;
  border-right:1px solid #9c8b67;
  border-bottom:1px solid #9c8b67;
  background:rgba(246,240,221,.42);
}
.gaz-column label span { color:#29231a; }
.gaz-column select {
  padding:4px 2px;
  border:0;
  border-bottom:1px solid #8e7d58;
  border-radius:0;
  color:#342e24;
  background:rgba(255,252,238,.42);
}
.gaz-act { padding:8px 10px; border-left:4px solid var(--gaz-oxblood); background:rgba(99,37,31,.055); }

.gaz-ladder {
  width:100%;
  margin:16px 0 5px;
  border-top:2px solid #514633;
  border-bottom:2px solid #514633;
}
.gaz-ladder th,.gaz-ladder td { border-bottom:1px solid #bbad88; }
.gaz-ladder td { border-left:1px solid #bbad88; }
.gaz-ladder td.now { position:relative; color:#f7edda; background:var(--gaz-oxblood); }
.gaz-ladder td.now::after { content:"TODAY"; position:absolute; inset:auto 0 -9px; color:var(--gaz-oxblood); font-size:6px; }

.gaz-settled { padding:5px 8px 10px; }
.gaz-truth li { border-bottom:1px dotted #9f906f; }
.gaz-truth li.right { background:linear-gradient(90deg,rgba(47,107,69,.08),transparent 42%); }
.gaz-truth li.wrong { background:linear-gradient(90deg,rgba(176,52,42,.08),transparent 42%); }

@media(max-width:760px) {
  .gaz-paper { padding:22px 18px 27px; clip-path:none; }
  .gaz-masthead { padding-inline:58px; }
  .gaz-masthead b { font-size:30px; }
  .gaz-masthead b::before,.gaz-masthead b::after { display:none; }
  .gaz-masthead::before,.gaz-masthead::after { width:54px; font-size:6px; }
  .gaz-briefs { grid-template-columns:1fr 1fr; }
  .gaz-brief:nth-child(3n) { border-right:1px solid #aa9a76; }
  .gaz-brief:nth-child(2n) { border-right:0; }
  .gaz-brief:nth-last-child(-n+3) { border-bottom:1px solid #aa9a76; }
  .gaz-brief:nth-last-child(-n+2) { border-bottom:0; }
}
@media(max-width:520px) {
  .gaz-paper { padding-inline:13px; }
  .gaz-masthead { padding-inline:8px; }
  .gaz-masthead::before,.gaz-masthead::after { display:none; }
  .gaz-masthead b { font-size:27px; }
  .gaz-lead-head { font-size:21px; }
  .gaz-lead-body { font-size:13px; }
  .gaz-briefs { grid-template-columns:1fr; }
  .gaz-brief { border-right:0!important; border-bottom:1px solid #aa9a76!important; }
  .gaz-brief:last-child { border-bottom:0!important; }
  .gaz-hand,.gaz-filed { padding-left:64px; }
}

/* ---- THE THREE MOMENTS ------------------------------------------------

   The background above is still, deliberately: this page is read closely
   for five minutes at a time and anything moving behind the type costs
   legibility without buying anything. What moves is the three instants
   where state the player owns actually changes, and nothing else.

   Each is punctuation on a change that has already happened. The page must
   read correctly with all of them switched off, which is what the
   reduced-motion block at the bottom asserts. */

/* 1. FILING THE COLUMN. The one worth the most work. A filed column is
      secret and cannot be withdrawn, and until now that was carried by a
      sentence. So the seal is lifted, struck, and squashed into the wax —
      the overshoot on the way down and the spread at the bottom are the
      whole effect, and the card takes the blow a beat later because that
      is the order the two things happen in.

      The transform has to carry translateY(-50%) through every frame: the
      seal is absolutely positioned and centred with it, so a keyframe that
      forgets it drops the seal half its own height. */
.gaz-paper.is-pressing .gaz-seal {
  animation:gaz-press 1.1s cubic-bezier(.3,.9,.4,1) forwards !important; }
@keyframes gaz-press {
  0%   { transform:translateY(-50%) scale(1); filter:brightness(1); }
  20%  { transform:translateY(calc(-50% - 10px)) scale(1.05) rotate(-3deg); filter:brightness(1.2); }
  40%  { transform:translateY(-50%) scale(.88,.8) rotate(1deg); filter:brightness(.8); }
  56%  { transform:translateY(-50%) scale(1.14,1.06) rotate(0deg); filter:brightness(1.05); }
  74%  { transform:translateY(-50%) scale(.98,1.02); }
  100% { transform:translateY(-50%) scale(1); filter:brightness(1); }
}
/* The wax spreading out from under it — one ring, gone in half a second.
   ::before on this card is already spoken for by CONFIDENTIAL. */
.gaz-paper.is-pressing .gaz-hand::after {
  content:""; position:absolute; left:38px; top:50%; width:44px; height:44px;
  margin:-22px 0 0 -22px; border-radius:50%; pointer-events:none;
  border:3px solid rgba(140,46,32,.75);
  box-shadow:0 0 0 1px rgba(255,244,228,.5), inset 0 0 0 1px rgba(255,244,228,.35);
  animation:gaz-wax .7s .36s ease-out forwards; }
/* Starts AT the seal's own size rather than inside it. The first draft
   opened at 55% and spent its whole life behind the 43px disc, which is a
   ring nobody ever saw. */
@keyframes gaz-wax {
  0%   { opacity:0; transform:scale(.98); }
  18%  { opacity:.9; }
  100% { opacity:0; transform:scale(2.6); border-width:.5px; }
}
/* And the paper itself takes it, once, very slightly. */
.gaz-paper.is-pressing .gaz-hand { animation:gaz-struck .42s .34s ease-out; }
@keyframes gaz-struck {
  0%,100% { transform:rotate(-.25deg) translateY(0); }
  35%     { transform:rotate(-.25deg) translateY(2px); }
}

/* 2. TONIGHT'S EDITION. Once a day, only for the day that is new. Ink
      rises out of the paper rather than sliding in from somewhere else —
      so it starts blurred and slightly low and resolves in place. The rule
      under the day's name draws across first, the way a compositor would
      set the header before the copy.

      Six items at 40ms apart is the whole cascade in a quarter of a
      second. A reader who blinks does not have to wait for it. */
.gaz-day.is-inking h5::after { animation:gaz-rule .34s ease-out both; transform-origin:left; }
@keyframes gaz-rule { 0% { transform:scaleX(0); } 100% { transform:scaleX(1); } }
.gaz-day.is-inking li { animation:gaz-ink .44s both; }
.gaz-day.is-inking li:nth-child(1) { animation-delay:.06s }
.gaz-day.is-inking li:nth-child(2) { animation-delay:.10s }
.gaz-day.is-inking li:nth-child(3) { animation-delay:.14s }
.gaz-day.is-inking li:nth-child(4) { animation-delay:.18s }
.gaz-day.is-inking li:nth-child(5) { animation-delay:.22s }
.gaz-day.is-inking li:nth-child(6) { animation-delay:.26s }
.gaz-day.is-inking li:nth-child(n+7) { animation-delay:.30s }
@keyframes gaz-ink {
  0%   { opacity:0; filter:blur(2.4px); transform:translateY(2.5px); }
  55%  { opacity:1; filter:blur(.5px); }
  100% { opacity:1; filter:blur(0); transform:none; }
}

/* 3. SUNDAY. The hands are published and you find out who held what — the
      Gazette's one big moment of the week, and the only place it is
      allowed anything theatrical. Each name turns over on its top edge
      like a card being laid down, and the verdict stripe washes in AFTER
      the turn rather than being there waiting: the point is that you learn
      it, not that it was always true.

      The stagger lives in the client (180ms apart) rather than in nth-child
      here, because the number of rivals is five today and will not always
      be. */
.gaz-truth li.is-turning {
  transform-origin:top center;
  animation:gaz-turn .8s cubic-bezier(.26,.86,.36,1) both; }
@keyframes gaz-turn {
  0%   { opacity:0; transform:perspective(620px) rotateX(-84deg); }
  50%  { opacity:1; }
  78%  { transform:perspective(620px) rotateX(5deg); }
  100% { opacity:1; transform:perspective(620px) rotateX(0deg); }
}
/* The verdict, arriving a beat late. A wash the width of the row that
   fades back to the resting gradient underneath. */
.gaz-truth li.is-turning::before {
  content:""; position:absolute; inset:0; pointer-events:none;
  animation:gaz-verdict .5s .42s ease-out both; }
.gaz-truth li { position:relative; }
.gaz-truth li.right.is-turning::before { background:linear-gradient(90deg,rgba(47,107,69,.34),transparent 62%); }
.gaz-truth li.wrong.is-turning::before { background:linear-gradient(90deg,rgba(176,52,42,.34),transparent 62%); }
@keyframes gaz-verdict { 0% { opacity:0; } 35% { opacity:1; } 100% { opacity:0; } }

/* Everything above is punctuation. With motion turned down the page still
   says exactly the same things — the seal is still dark and still, the
   day is still printed, the verdict stripes are still on the rows. */
@media (prefers-reduced-motion: reduce) {
  .gaz-seal,
  .gaz-paper.is-pressing .gaz-seal,
  .gaz-paper.is-pressing .gaz-hand,
  .gaz-day.is-inking h5::after,
  .gaz-day.is-inking li,
  .gaz-truth li.is-turning,
  .gaz-truth li.is-turning::before { animation:none !important; }
  .gaz-paper.is-pressing .gaz-hand::after { display:none; }
}

/* The plain-words brief that now opens every game's rules. Numbered because
   these genuinely are steps in order — the one place in this interface where
   a numbered list is describing a sequence rather than decorating a stack. */
.game-brief { margin:0 0 4px; padding:0 0 0 22px; counter-reset:gb; list-style:none; }
.game-brief li { position:relative; margin:0 0 7px; font-size:14px; line-height:1.5;
  /* The same measure as the prose below it, or the brief runs the full
     width of the panel and the two halves stop looking like one page. */
  max-width:62ch; color:var(--ink); }
.game-brief li::before { counter-increment:gb; content:counter(gb);
  position:absolute; left:-22px; top:2px; width:16px; height:16px; border-radius:50%;
  display:grid; place-items:center; background:var(--forest); color:#F2EFE4;
  font-family:'IBM Plex Mono',monospace; font-size:9.5px; font-weight:600; }
.game-detail-head { margin:14px 0 2px; padding-top:10px; border-top:1px solid var(--line);
  font-family:'IBM Plex Mono',monospace; font-size:9.5px; letter-spacing:.18em;
  text-transform:uppercase; color:#7A7058; font-weight:500; }
.game-synopsis .game-detail-head + p { margin-top:4px; }

/* ---- ARMED SHIELDS ----------------------------------------------------

   The only cards that live across the daily discard, and the only ones with
   an order that means anything — one shield answers each attack and it is
   the first on this list that can. So the list is read top-down as "what I
   am willing to spend first", and the number is the point of it. */
.armed-shields .deck-sub { max-width:66ch; }
.armed-list { margin:8px 0 10px; padding:0; list-style:none;
  border-top:1px solid var(--line); }
.armed-list li { display:flex; align-items:center; gap:12px; padding:8px 4px;
  border-bottom:1px solid var(--line); }
.armed-n { flex:0 0 auto; width:21px; height:21px; border-radius:50%;
  display:grid; place-items:center; background:var(--forest); color:#F2EFE4;
  font-family:'IBM Plex Mono',monospace; font-size:10.5px; font-weight:600; }
.armed-what { flex:1 1 auto; min-width:0; }
.armed-what b { font-family:'Fraunces',Georgia,serif; font-size:14.5px; }
.armed-what em { display:block; font-style:normal; font-size:11.5px; color:#6b6455; }
.armed-acts { flex:0 0 auto; display:flex; gap:6px; align-items:center; flex-wrap:wrap; }
/* The arrows are a pair, so they get a fixed width — ragged arrows in a
   column of them read as a mistake. */
.armed-acts .btn.small { padding:3px 9px; font-size:11.5px; }
.armed-acts .btn.small[title] { min-width:32px; }
@media (max-width:560px) {
  .armed-list li { flex-wrap:wrap; }
  .armed-acts { width:100%; justify-content:flex-end; }
}

/* The two things you can do with last night's committee, side by side —
   watch it happen, or read what happened. Neither is the default. */
.minutes-acts { display:flex; gap:10px; flex-wrap:wrap; align-items:center;
  margin:10px 0 4px; }

/* The map at full screen. The wrapper becomes the whole screen, so the
   SVG has to be told it may take all of it — without this it keeps the
   aspect box it had inside the page and sits in a letterbox. */
.map-svg-wrap:fullscreen { width:100vw; height:100vh; border:none; border-radius:0; }
.map-svg-wrap:fullscreen svg { width:100%; height:100%; }
.map-svg-wrap:-webkit-full-screen { width:100vw; height:100vh; border:none; }
.map-svg-wrap:-webkit-full-screen svg { width:100%; height:100%; }

/* ---- CALL THE MEETING, AND THE AGREEMENT LINE ----
   The four open cards are numbered by the seat you give them rather than
   reordered on screen: dragging cards about is fiddly on a phone, and a
   number in the corner says the same thing in one glance. An unplaced card
   shows an em dash, so the control reads as "four seats, some empty"
   rather than as "nothing has happened". */
.scry-open { border-color: var(--gold); }
.scry-card { position: relative; }
.scry-card .scry-seat {
  /* TOP LEFT, NOT TOP RIGHT. The rarity ribbon already lives in the right
     corner of every card, and a seat number dropped on top of it clipped
     "COMMON" to "COM" — two labels fighting over one corner. */
  position: absolute; top: 6px; left: 6px;
  min-width: 22px; height: 22px; border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 12px/1 var(--mono);
  background: rgba(12, 20, 15, .82); color: #f2efe4;
  border: 1px solid rgba(242, 239, 228, .35);
}
.scry-card.is-placed .scry-seat { background: var(--gold); color: #17201a; border-color: var(--gold); }
.scry-card.is-placed { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 6px; }

.deck-truce {
  margin: 0 0 10px; padding: 8px 12px;
  border-left: 3px solid var(--gold);
  background: rgba(168, 135, 31, .10);
  font-size: 13px; line-height: 1.45;
}

/* THE ONE WARNING IN THE GUIDE. Everything else in these cards explains how
   the game works; this one says what will happen to you if you do nothing,
   so it is marked rather than left to read as more explanation. */
.guide-line.guide-warn {
  margin-top: 14px; padding: 10px 12px;
  border-left: 3px solid var(--brick);
  background: rgba(162, 62, 39, .08);
}

/* ---- THE DEFENCE BEAT ----
   The one genuinely unknown thing in an evening is whether a shield is
   armed, and it is unknown to the attacker and often to the owner too. The
   replay now stops on that question instead of running a bar past it, so
   these are the styles for the beat: the deed arriving out of the dark, the
   held moment, and the two ways it can end. */

/* Before the order gets there the plate is a shape, not a building. */
.reck-target.is-dark { opacity: .38; filter: saturate(.25) blur(.4px); }
.reck-target.is-found { animation: reck-found .42s cubic-bezier(.2,.8,.25,1) both; }
@keyframes reck-found {
  0%   { opacity: .38; transform: scale(.97); filter: saturate(.25) blur(2px); }
  60%  { opacity: 1; filter: saturate(1) blur(0); }
  100% { opacity: 1; transform: scale(1); filter: none; }
}
.reck-unknown { letter-spacing: .18em; opacity: .5; }

/* The held moment. A slow pulse rather than a spinner: a spinner says "the
   computer is busy", and nothing here is busy — it is waiting. */
.reckoning.is-holding .reck-route { animation: reck-hold 1.5s ease-in-out infinite; }
@keyframes reck-hold {
  0%, 100% { box-shadow: 0 0 0 rgba(176,140,30,0); }
  50%      { box-shadow: 0 0 22px rgba(176,140,30,.30); }
}

.reck-counter.is-waiting { border-style: dashed; opacity: .9; animation: reck-ask 1.5s ease-in-out infinite; }
.reck-counter.is-waiting span { color: var(--gold); }
@keyframes reck-ask { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }

/* Nothing was armed. Deliberately quiet — an empty deed is the ordinary
   case and should not be dressed as an event. */
.reck-counter.is-clear { opacity: .6; border-style: dotted; }
.reck-counter.is-clear span { color: var(--muted); }

@media (prefers-reduced-motion: reduce) {
  .reck-target.is-found,
  .reckoning.is-holding .reck-route,
  .reck-counter.is-waiting { animation: none; }
}

/* ---- YOUR MAN INSIDE ----
   Shown to one player and invisible to the one being watched. Marked with
   the super-rare vermilion because that is where it comes from, and kept
   deliberately plain otherwise: it is a list of facts somebody paid a lot
   for, not a dashboard. */
.inside-man { border-left: 3px solid #7E1F33; }
.inside-row { padding: 8px 0; border-bottom: 1px dotted var(--line); }
.inside-row:last-child { border-bottom: 0; }
.inside-who { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.inside-who .muted { font-size: 11px; }
.inside-orders { list-style: none; margin: 0; padding: 0; }
.inside-orders li {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px; padding: 4px 0; font-size: 13px;
}
.inside-orders li b { font-weight: 600; }
@media (max-width: 560px) { .inside-orders li { grid-template-columns: 1fr; gap: 2px; } }

/* ---- THE OPENING WEEK ----
   Seven cards in a row, and the state of each one is the message: a taken
   day is settled, a missed day is plainly gone rather than quietly absent,
   and today is the only one lit. The gap in the row is what makes tomorrow
   matter, so it is drawn rather than tidied away. */
/* ── MUTUAL MATCHES ───────────────────────────────────────────────────────
   The one panel in the trade tab that is about two people at once, so it is
   the only one drawn as a pair: two sides and the exchange between them,
   rather than a list. */
.mutual-matches { border-left-color: var(--brick); }
.match-row .gap-head b { font-size: 16px; }
.match-swap { display: flex; align-items: stretch; gap: 14px; margin: 9px 0 11px;
  flex-wrap: wrap; }
.match-side { flex: 1 1 200px; min-width: 0; padding: 9px 11px;
  border: 1px solid var(--line); background: var(--paper-dark); }
.match-side b { display: block; margin: 2px 0 3px; font: 600 14px 'Fraunces', serif; }
.match-label { display: block; font: 9px 'IBM Plex Mono', monospace;
  letter-spacing: .13em; color: var(--muted, #6b6455); }
.match-closes { font-size: 11.5px; color: var(--muted, #6b6455); }
.match-arrow { align-self: center; flex: none; font-size: 20px; color: var(--brick); }
@media (max-width: 620px) {
  .match-swap { flex-direction: column; gap: 8px; }
  .match-arrow { align-self: flex-start; transform: rotate(90deg); }
}

/* ── THE WANTED REGISTER ──────────────────────────────────────────────────
   Quiet by design. A declaration that costs nothing should not look like a
   bid, so this is a line in the deed rather than a panel with a border and a
   colour of its own. The owner's version is the same line saying the answer
   instead of asking the question. */
.wanted-line { display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin-top: 12px; padding: 11px 13px;
  border: 1px solid var(--line); background: var(--paper-dark); }
.wanted-line b { display: block; font: 600 13.5px 'Fraunces', serif; }
.wanted-line p { margin: 3px 0 0; max-width: 46ch;
  font-size: 12px; line-height: 1.45; color: var(--muted, #6b6455); }
.wanted-say { flex: 1 1 220px; min-width: 0; }
.wanted-line .btn { flex: none; }
.wanted-line.is-owner { border-left: 3px solid var(--gold); display: block; }
.wanted-from-me { border-left-color: var(--forest); }
@media (max-width: 620px) {
  .wanted-line { flex-direction: column; align-items: stretch; }
  .wanted-line .btn { width: 100%; }
}

/* ── ONE AWAY ─────────────────────────────────────────────────────────────
   The Trade tab's new first panel. Reads as a short list of near misses, not
   as a shop: every row is a set you could close today, and every button is a
   person who can close it. */
.one-away { border-left: 3px solid var(--gold); }
.one-away h3 { margin: 0 0 4px; }
.one-away-intro { margin: 0 0 14px; max-width: 62ch;
  font-size: 13px; line-height: 1.5; color: var(--muted, #6b6455); }
.gap-row { padding: 12px 0; border-top: 1px solid var(--line); }
.gap-row:first-of-type { border-top: 0; padding-top: 4px; }
.gap-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; }
.gap-head b { font: 600 15px 'Fraunces', serif; }
.gap-count { font: 11px 'IBM Plex Mono', monospace; letter-spacing: .06em;
  color: var(--muted, #6b6455); }
.gap-what { margin: 4px 0 9px; font-size: 13px; line-height: 1.45; }
.gap-holders { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
/* One button per holder: the property is the headline because the property is
   what you want; the name is how you get it. */
.gap-holder { display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 7px 11px; cursor: pointer; text-align: left;
  border: 1px solid var(--line); background: var(--paper-dark);
  font-family: inherit; color: inherit; }
.gap-holder:hover { border-color: var(--gold); background: var(--paper); }
.gap-prop { font: 600 13px 'Fraunces', serif; }
.gap-owner { font: 10.5px 'IBM Plex Mono', monospace; letter-spacing: .05em;
  color: var(--muted, #6b6455); }
.gap-more, .gap-none { font-size: 12.5px; color: var(--muted, #6b6455); }
.gap-none { margin: 0; }
@media (max-width: 620px) {
  .gap-holders { flex-direction: column; align-items: stretch; }
  .gap-holder { flex-direction: row; justify-content: space-between; align-items: baseline; }
}

/* ── THE OPENING WEEK ─────────────────────────────────────────────────────
   Ported from Aaron's bench. Literal colours rather than tokens, as the wheel
   is: the modal carries its own dark ground and must read the same in all
   four palettes. The bench's purple is gone throughout — purple is the
   Historic property tier and cannot also mean "the finale". */

.ow-backdrop { background: rgba(10, 20, 17, .72); }
.ow-box { --ow-accent: #B08C1E;
  max-width: min(1280px, 100%); width: min(1280px, 100%);
  position: relative; overflow: hidden; isolation: isolate;
  border: 1px solid #8F8362; outline: 6px double rgba(224,196,104,.72);
  outline-offset: -14px; color: #EBE4CE;
  background: radial-gradient(circle at 50% 42%, rgba(74,115,97,.34), transparent 43%), #15382F;
  box-shadow: 0 35px 95px rgba(0,0,0,.65), inset 0 0 75px rgba(0,0,0,.27); }
.ow-box .modal-inner { position: relative; z-index: 4; padding: 26px 30px 22px; }
.ow-patina { position: absolute; inset: 0; z-index: 0; opacity: .36; pointer-events: none;
  background:
    repeating-linear-gradient(17deg, rgba(255,255,255,.025) 0 1px, transparent 1px 5px),
    radial-gradient(circle at 17% 35%, #061A15 0 1px, transparent 1.5px);
  background-size: auto, 5px 5px; }

.ow-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 22px; padding-bottom: 17px; border-bottom: 1px solid rgba(226,205,133,.38); }
.ow-kicker { display: block; margin-bottom: 7px; color: #E4C860; white-space: nowrap;
  font: 700 11px 'IBM Plex Mono', monospace; letter-spacing: .16em; }
.ow-box h3 { margin: 0; color: #FFF4DC;
  font: 700 clamp(24px, 3vw, 38px)/1 'Fraunces', serif; letter-spacing: -.02em; }
.ow-intro { margin: 8px 0 0; color: #C9C0A5; font: 15px 'Fraunces', serif; }
.ow-box .switch-link { color: #E9E1CA; border-bottom-color: #D7CCB0; flex: none; }

.ow-progress { height: 4px; margin: 16px 2px 18px; display: grid;
  grid-template-columns: repeat(7, 1fr); gap: 6px; }
.ow-progress i { background: rgba(231,217,164,.15); }
.ow-progress i.done { background: #6D9B75; }
.ow-progress i.missed { background: #8C4B3D; }
.ow-progress i.current { background: var(--ow-accent);
  box-shadow: 0 0 14px var(--ow-accent); animation: ow-live 1s ease-in-out infinite alternate; }
@keyframes ow-live { to { filter: brightness(1.55); } }

/* THE TRACK. The day you are on takes more than twice the width of the
   others, which is what turns seven equal boxes into a week with a today in
   it. Everything else is legible but subordinate. */
.ow-track { display: flex; align-items: stretch; gap: 10px; min-height: 370px; }
.ow-card { --card-accent: #8A826C;
  position: relative; flex: 1 1 0; min-width: 0; overflow: hidden;
  display: grid; grid-template-rows: auto 132px 1fr auto;
  padding: 15px 12px 12px; border: 1px solid rgba(211,196,147,.3); color: #D6CDB4;
  background: linear-gradient(160deg, rgba(244,237,215,.11), rgba(4,24,19,.16));
  box-shadow: inset 0 0 24px rgba(0,0,0,.18);
  transition: flex .65s cubic-bezier(.2,.75,.2,1), opacity .45s, filter .45s, transform .65s; }
.ow-card::before { content: ""; position: absolute; inset: 6px;
  border: 1px solid rgba(238,217,147,.1); pointer-events: none; }
.ow-card > header { display: flex; align-items: center; justify-content: space-between;
  color: #AAA187; font: 9px 'IBM Plex Mono', monospace; letter-spacing: .14em; }
.ow-card > header b { font-size: 15px; color: #D8CA9D; }
.ow-copy { position: relative; z-index: 3; }
.ow-copy h4 { margin: 12px 0 7px; color: #F2EAD5; font: 700 17px/1.08 'Fraunces', serif; }
.ow-copy p { margin: 0; color: #AAA38E; font: 12px/1.38 'Fraunces', serif; }
.ow-card > footer { position: relative; z-index: 3; display: flex; align-items: center;
  justify-content: space-between; gap: 7px; padding-top: 11px;
  border-top: 1px solid rgba(218,202,151,.2); }
.ow-state { color: #A7A08C; font: 9px 'IBM Plex Mono', monospace; letter-spacing: .08em; }
.ow-stamp { opacity: 0; padding: 4px 6px; border: 2px double var(--card-accent);
  color: var(--card-accent); font: 700 8px 'IBM Plex Mono', monospace;
  letter-spacing: .1em; transform: rotate(-8deg) scale(.6); }

.ow-card.is-taken { opacity: .7; filter: saturate(.65); }
.ow-card.is-taken .ow-stamp { opacity: .75; transform: rotate(-8deg) scale(1); }
.ow-card.is-missed { opacity: .35; filter: grayscale(.8); }
.ow-card.is-missed::after { content: "MISSED"; position: absolute; left: 50%; top: 48%;
  z-index: 6; padding: 6px 9px; border: 2px solid #9D5D4D; color: #C17B68;
  background: rgba(20,29,25,.83); font: 700 10px 'IBM Plex Mono', monospace;
  letter-spacing: .14em; transform: translate(-50%,-50%) rotate(-9deg); }
.ow-card.is-ahead { opacity: .56; }
.ow-card.is-locked { opacity: .85; border-color: rgba(157,93,77,.6); }
.ow-card.is-active { flex: 2.3 1 0; z-index: 5; border-color: var(--card-accent); color: #fff;
  background:
    radial-gradient(circle at 50% 34%, color-mix(in srgb, var(--card-accent) 25%, transparent), transparent 50%),
    linear-gradient(155deg, rgba(248,240,213,.2), rgba(4,24,19,.15));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--card-accent) 38%, transparent),
    0 0 40px color-mix(in srgb, var(--card-accent) 34%, transparent),
    inset 0 0 38px rgba(255,255,255,.06);
  transform: translateY(-7px); opacity: 1; filter: none; }
.ow-card.is-active .ow-copy h4 { font-size: 25px; }
.ow-card.is-active .ow-copy p { color: #DDD4BA; font-size: 14px; }
.ow-card.is-active > header { color: #EADDAE; }
.ow-card.is-active > header b { color: #FFF4BD; font-size: 20px; }
.ow-card.is-active.is-awarded .ow-stamp {
  animation: ow-stamp .48s 1.05s cubic-bezier(.2,.8,.26,1.3) forwards; }
@keyframes ow-stamp { to { opacity: 1; transform: rotate(-8deg) scale(1); } }

/* ── the seven drawings ──────────────────────────────────────────────── */
.ow-art { position: relative; display: grid; place-items: center; margin: 8px 0 0;
  perspective: 800px; }

.ow-art-brief i { position: absolute; width: 64px; height: 86px; border: 1px solid #BDA95E;
  background: #E8DFC5; box-shadow: 0 9px 15px rgba(0,0,0,.28); transform-origin: left; }
.ow-art-brief i:first-child { transform: rotateY(-28deg) rotate(-3deg); }
.ow-art-brief i:nth-child(2) { transform: rotateY(24deg) rotate(3deg); }
.ow-art-brief em { z-index: 2; color: #714329; font: 700 15px 'Fraunces', serif;
  letter-spacing: .12em; font-style: normal; }
.is-awarded .ow-art-brief i:first-child { animation: ow-page-l 1.2s .3s ease-out; }
.is-awarded .ow-art-brief i:nth-child(2) { animation: ow-page-r 1.2s .3s ease-out; }
@keyframes ow-page-l { 0% { transform: rotateY(0); }
  55% { transform: rotateY(-75deg) translateX(-11px); }
  100% { transform: rotateY(-28deg) rotate(-3deg); } }
@keyframes ow-page-r { 0% { transform: rotateY(0); }
  55% { transform: rotateY(75deg) translateX(11px); }
  100% { transform: rotateY(24deg) rotate(3deg); } }

.ow-art-coins span { position: relative; z-index: 3; width: 64px; height: 64px;
  display: grid; place-items: center; border: 6px double #F2D77A; border-radius: 50%;
  color: #FFE99B; background: #84611D; font: 700 36px 'Fraunces', serif;
  box-shadow: 0 0 18px rgba(238,202,74,.38); }
.ow-art-coins i { position: absolute; width: 52px; height: 24px; border: 2px solid #D0B453;
  border-radius: 50%; background: #8D681E; }
.ow-art-coins i:nth-of-type(1) { transform: translate(-36px, 29px); }
.ow-art-coins i:nth-of-type(2) { transform: translate(34px, 34px); }
.ow-art-coins i:nth-of-type(3) { transform: translate(4px, 47px); }
.is-awarded .ow-art-coins span { animation: ow-coin 1.05s .35s cubic-bezier(.17,.8,.25,1.28); }
.is-awarded .ow-art-coins i { animation: ow-scatter .9s .45s ease-out; }
@keyframes ow-coin { 40% { transform: translateY(-24px) scale(1.17); filter: brightness(1.5); }
  70% { transform: translateY(3px) scale(.95); } }
@keyframes ow-scatter { 45% { transform: translate(18px,-16px) rotate(150deg); filter: brightness(1.6); } }

.ow-art-skill span { position: relative; z-index: 3; width: 70px; height: 70px;
  display: grid; place-items: center;
  clip-path: polygon(50% 0, 61% 36%, 100% 50%, 63% 62%, 50% 100%, 38% 63%, 0 50%, 36% 38%);
  color: #F7E59E; background: #354E78; font: 700 22px 'Fraunces', serif; }
.ow-art-skill i { position: absolute; width: 8px; height: 8px; border-radius: 50%;
  background: #E8D77C; }
.is-awarded .ow-art-skill span { animation: ow-star 1.3s .25s ease-out; }
.is-awarded .ow-art-skill i { animation: ow-orbit 1.2s .3s ease-out; }
@keyframes ow-star { 35% { transform: rotate(120deg) scale(1.35);
  filter: drop-shadow(0 0 25px #E8D77C); } 100% { transform: rotate(360deg); } }
@keyframes ow-orbit { 50% { transform: rotate(240deg) translateX(64px) scale(1.8); }
  100% { opacity: 0; transform: rotate(480deg) translateX(15px); } }

/* The veto: a permit, and the stamp that stops it. */
.ow-art-veto b { position: relative; z-index: 2; width: 74px; height: 96px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; border: 1px solid #B9A96A; background: #E9E1C7;
  box-shadow: 0 9px 16px rgba(0,0,0,.3); }
.ow-art-veto b em { color: #6C5B33; font: 700 8px 'IBM Plex Mono', monospace;
  letter-spacing: .14em; font-style: normal; }
.ow-art-veto b s { width: 44px; height: 3px; background: #C2B892; text-decoration: none; }
.ow-art-veto span { position: absolute; z-index: 4; padding: 6px 10px;
  border: 3px double #E4785A; color: #F0A085; background: rgba(38,16,11,.72);
  font: 700 13px 'IBM Plex Mono', monospace; letter-spacing: .16em;
  transform: rotate(-14deg) scale(1); }
.is-awarded .ow-art-veto span { animation: ow-veto 1.1s .3s cubic-bezier(.2,.9,.24,1.3); }
.is-awarded .ow-art-veto b { animation: ow-permit 1.1s .3s ease-out; }
@keyframes ow-veto { 0% { opacity: 0; transform: rotate(-38deg) scale(3.4); }
  45% { opacity: 1; transform: rotate(-11deg) scale(.88); }
  60% { transform: rotate(-16deg) scale(1.08); }
  100% { opacity: 1; transform: rotate(-14deg) scale(1);
    filter: drop-shadow(0 0 14px rgba(228,120,90,.8)); } }
@keyframes ow-permit { 46% { transform: translateY(5px) scale(.97); } }

/* The wheel in miniature, and it turns. */
.ow-art-wheel b { position: relative; z-index: 2; width: 84px; height: 84px;
  border-radius: 50%; border: 5px ridge #B08C1E;
  background: repeating-conic-gradient(from 0deg,
    #7E1F33 0deg 45deg, #315E4D 45deg 90deg, #8B6723 90deg 135deg, #31486D 135deg 180deg);
  box-shadow: 0 0 0 2px #533914, 0 10px 20px rgba(0,0,0,.4); }
.ow-art-wheel em { position: absolute; z-index: 4; width: 28px; height: 28px;
  display: grid; place-items: center; border-radius: 50%; border: 2px solid #E8CF6D;
  background: #17372F; color: #EAD47D; font: 700 14px 'Fraunces', serif; font-style: normal; }
.ow-art-wheel i { position: absolute; z-index: 5; top: -6px; width: 0; height: 0;
  border-left: 7px solid transparent; border-right: 7px solid transparent;
  border-top: 16px solid #E8CF6D; filter: drop-shadow(0 2px 3px rgba(0,0,0,.5)); }
.is-awarded .ow-art-wheel b { animation: ow-spin 1.6s .25s cubic-bezier(.16,.72,.2,1); }
.is-awarded .ow-art-wheel i { animation: ow-tongue 1.6s .25s ease-out; }
@keyframes ow-spin { 0% { transform: rotate(0); }
  100% { transform: rotate(1100deg); filter: drop-shadow(0 0 18px #E2C468); } }
@keyframes ow-tongue { 0%, 70% { transform: rotate(-12deg); } 100% { transform: rotate(0); } }

/* A rate falling, which is the only reward that is a number getting smaller. */
.ow-art-rate b { position: relative; z-index: 2; width: 78px; height: 78px;
  display: grid; place-items: center; border: 5px double #E4C860; border-radius: 50%;
  color: #FFEFB4; background: #234A3C; font: 700 36px 'Fraunces', serif;
  box-shadow: 0 0 20px rgba(232,202,90,.32); }
.ow-art-rate i { position: absolute; z-index: 1; width: 3px; height: 74px;
  background: linear-gradient(#E8CA5A, transparent); opacity: 0; }
.ow-art-rate span { position: absolute; z-index: 4; bottom: 4px; color: #8FD3A6;
  font-size: 22px; }
.is-awarded .ow-art-rate b { animation: ow-rate 1.4s .28s cubic-bezier(.2,.8,.24,1.2); }
.is-awarded .ow-art-rate span { animation: ow-arrow 1.4s .4s ease-out; }
.is-awarded .ow-art-rate i { animation: ow-fall 1.2s .35s ease-in; }
@keyframes ow-rate { 0% { transform: translateY(-30px) scale(1.25); filter: brightness(1.6); }
  55% { transform: translateY(6px) scale(.95); } 100% { transform: none; } }
@keyframes ow-arrow { 0% { opacity: 0; transform: translateY(-26px); }
  45% { opacity: 1; transform: translateY(6px); }
  100% { opacity: 1; transform: none; filter: drop-shadow(0 0 10px #8FD3A6); } }
@keyframes ow-fall { 0% { opacity: 0; transform: translateY(-34px) scaleY(.3); }
  50% { opacity: .9; } 100% { opacity: 0; transform: translateY(30px) scaleY(1.2); } }

.ow-art-vault span { position: relative; z-index: 2; width: 96px; height: 70px;
  display: grid; place-items: center; border: 7px ridge #AB842B; color: #FFE696;
  background: #32453F; font: 700 19px 'Fraunces', serif;
  box-shadow: 0 10px 22px rgba(0,0,0,.4); }
.ow-art-vault i { position: absolute; z-index: 3; width: 34px; height: 34px;
  border: 5px double #E1C35E; border-radius: 50%; }
.ow-art-vault i:last-child { width: 118px; height: 17px; border: 0; border-radius: 0;
  opacity: 0; background: repeating-linear-gradient(90deg, #F1D56D 0 8px, transparent 8px 14px); }
.is-awarded .ow-art-vault i:first-of-type { animation: ow-vault 1.2s .25s ease-out; }
.is-awarded .ow-art-vault i:last-child { animation: ow-shower 1.3s .55s ease-out; }
@keyframes ow-vault { to { transform: rotate(540deg); filter: drop-shadow(0 0 14px #F1D56D); } }
@keyframes ow-shower { 25% { opacity: 1; transform: translateY(-34px); }
  100% { opacity: 0; transform: translateY(50px) rotate(18deg); } }

/* ── the verdict, the confetti and the rays ──────────────────────────── */
.ow-celebration { inset: -20%; z-index: 18; }
.ow-box.awarded .celebration-particle {
  animation: particle-flight var(--duration) var(--delay) cubic-bezier(.16,.66,.26,1) forwards; }
.ow-box.awarded .burst-ring {
  animation: burst-ring var(--ring-duration) var(--ring-delay) cubic-bezier(.1,.7,.18,1) forwards; }

.ow-rays { position: absolute; left: 50%; top: 48%; z-index: 10; width: 830px; height: 830px;
  border-radius: 50%; opacity: 0; pointer-events: none; transform: translate(-50%,-50%);
  background: repeating-conic-gradient(from 0deg, rgba(255,240,145,.95) 0 2deg,
    transparent 3deg 8deg, rgba(176,140,30,.7) 9deg 11deg, transparent 12deg 18deg);
  -webkit-mask: radial-gradient(circle, transparent 0 16%, #000 25%, transparent 69%);
  mask: radial-gradient(circle, transparent 0 16%, #000 25%, transparent 69%); }
.ow-box.day-7.awarded .ow-rays { animation: ow-rays 3.5s ease-out; }
@keyframes ow-rays { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.2) rotate(0); }
  14%, 48% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(1.35) rotate(150deg); } }

.ow-banner { position: absolute; left: 50%; top: 49%; z-index: 25;
  min-width: min(380px, calc(100% - 28px)); max-width: calc(100% - 28px);
  padding: 18px 34px 15px; border: 5px double var(--ow-accent); opacity: 0;
  color: #FFF5CA; text-align: center; pointer-events: none;
  background: linear-gradient(120deg, #173A31, #2D5E4F 48%, #112E27);
  box-shadow: 0 0 0 4px #74551A, 0 0 75px color-mix(in srgb, var(--ow-accent) 75%, transparent),
    inset 0 0 30px rgba(255,245,200,.15);
  transform: translate(-50%,-50%) scale(.3) rotate(-7deg); }
.ow-banner small { display: block; font: 9px 'IBM Plex Mono', monospace; letter-spacing: .17em; }
.ow-banner strong { display: block; margin: 4px 0;
  font: 700 34px/1.02 'Fraunces', serif; letter-spacing: .035em; text-wrap: balance; }
.ow-banner p { margin: 5px 0 0; font: 13px 'Fraunces', serif; }
.ow-marquee { position: absolute; inset: -12px; border: 5px dotted #FFF0A2;
  box-shadow: 0 0 24px var(--ow-accent); opacity: 0; }
.ow-crown { position: absolute; left: 50%; top: -58px; color: #FFE580;
  font: 52px 'Fraunces', serif; font-style: normal;
  filter: drop-shadow(0 0 9px #FFF2A7); transform: translateX(-50%); }
.ow-box.awarded .ow-banner {
  animation: ow-arrive 2.45s .72s cubic-bezier(.17,.82,.21,1.18) forwards; }
.ow-box.day-7 .ow-banner { color: #FFF1AD;
  background: linear-gradient(120deg, #24402F, #3E6B45 48%, #1C3527);
  box-shadow: 0 0 0 4px #A87F24, 0 0 100px #D69D31, 0 0 160px rgba(176,140,30,.85),
    inset 0 0 34px rgba(255,235,142,.25); }
.ow-box.day-7.awarded .ow-banner {
  animation: ow-finale 3.6s .7s cubic-bezier(.17,.82,.21,1.18) forwards; }
.ow-box.day-7.awarded .ow-marquee { opacity: 1; animation: ow-blaze .28s .9s steps(2,end) 9; }
.ow-box.day-7.awarded { animation: ow-shake 2.5s .6s ease-out; }
@keyframes ow-arrive { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.25) rotate(-7deg); }
  30% { opacity: 1; transform: translate(-50%,-50%) scale(1.14) rotate(2deg); }
  48% { transform: translate(-50%,-50%) scale(.96) rotate(-1deg); }
  65%, 82% { opacity: 1; transform: translate(-50%,-50%) scale(1) rotate(-1deg); }
  100% { opacity: 0; transform: translate(-50%,-56%) scale(1.07) rotate(-1deg); } }
@keyframes ow-finale { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.12) rotate(-12deg); }
  20% { opacity: 1; transform: translate(-50%,-50%) scale(1.25) rotate(3deg); }
  31% { transform: translate(-50%,-50%) scale(.9) rotate(-2deg); }
  42%, 58%, 74% { opacity: 1; transform: translate(-50%,-50%) scale(1.1); filter: brightness(1.5); }
  50%, 66%, 82% { opacity: 1; transform: translate(-50%,-50%) scale(1); filter: brightness(1); }
  100% { opacity: 0; transform: translate(-50%,-58%) scale(1.12); filter: brightness(1.35); } }
@keyframes ow-blaze { 50% { border-color: #B08C1E;
  box-shadow: 0 0 28px #FFF5AE, 0 0 50px #E8CA5A; } }
@keyframes ow-shake { 0%, 100% { box-shadow: 0 35px 95px rgba(0,0,0,.65), inset 0 0 75px rgba(0,0,0,.27); }
  12%, 44%, 72% { box-shadow: 0 35px 95px rgba(0,0,0,.65), inset 0 0 170px rgba(255,220,69,.7); }
  26%, 58% { box-shadow: 0 35px 95px rgba(0,0,0,.65), inset 0 0 150px rgba(176,140,30,.6); } }

.ow-foot { position: relative; z-index: 3; display: grid;
  grid-template-columns: 210px 1fr 68px; align-items: center; gap: 18px;
  margin-top: 18px; padding: 15px 17px; border: 1px solid rgba(224,202,127,.31);
  background: rgba(5,24,19,.35); }
.ow-attend span { display: block; color: #B7AA81;
  font: 8px 'IBM Plex Mono', monospace; letter-spacing: .13em; }
.ow-attend strong { display: block; margin-top: 5px; color: #F0E5C5;
  font: 700 14px 'Fraunces', serif; }
.ow-next { margin: 0; color: #C8BEA0; text-align: center;
  font: italic 14px 'Fraunces', serif; }
.ow-seal { width: 56px; height: 56px; display: grid; place-items: center; align-content: center;
  border: 5px double #E0C862; border-radius: 50%; color: #F5E7A2; background: #823B29;
  transform: rotate(-8deg); }
.ow-seal span { font: 700 23px/.8 'Fraunces', serif; }
.ow-seal small { margin-top: 4px; font: 6px 'IBM Plex Mono', monospace; }

@media (max-width: 1100px) {
  .ow-track { display: grid; grid-template-columns: repeat(4, 1fr); }
  .ow-card { min-height: 310px; }
  .ow-card.is-active { grid-column: span 2; min-height: 330px; transform: none; }
  .ow-foot { grid-template-columns: 1fr 1fr 60px; }
}
@media (max-width: 680px) {
  .ow-box .modal-inner { padding: 20px 15px 16px; }
  .ow-intro { font-size: 13px; }
  .ow-kicker { font-size: 9.5px; letter-spacing: .1em; }
  .ow-track { grid-template-columns: 1fr 1fr; }
  .ow-card.is-active { grid-column: 1 / -1; }
  .ow-card { min-height: 280px; }
  .ow-foot { grid-template-columns: 1fr; text-align: center; }
  .ow-seal { display: none; }
  .ow-banner { min-width: 0; padding-inline: 16px; }
  .ow-banner strong { font-size: 25px; }
  .ow-crown { top: -44px; font-size: 40px; }
}
@media (prefers-reduced-motion: reduce) {
  .ow-box, .ow-box *, .ow-progress i { animation: none !important; }
  .ow-box .ow-banner { opacity: 1; transform: translate(-50%,-50%); }
  .ow-card.is-active.is-awarded .ow-stamp { opacity: 1; transform: rotate(-8deg) scale(1); }
}
@media (max-width: 720px) {
  .ow-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 420px) {
  .ow-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- THE WHEEL ----
   A placeholder face, deliberately. The real one is Aaron's, and it drops in
   by replacing WheelFace and keeping the one prop it reads — so this needs
   to be legible rather than good. */
/* ---- THE WHEEL OF FORTUNE ------------------------------------------
   Ported from Aaron's v1 bench rather than reinterpreted. The SVG carries
   the wedges, labels, numbers, studs and the engraved ring; everything
   below layers the brass over it — the ridged rim, the inner bezel, the
   hub, and a crowned pointer the wheel passes under.

   It lives on its own ground under the Market. It was on the tactics
   baize, where a green wheel on a green table had nothing to sit against.
   -------------------------------------------------------------------- */
.wheel-panel {
  margin: 22px 0 0; padding: 22px 18px 24px; text-align: center; position: relative;
  background:
    radial-gradient(ellipse at 50% 0%, rgba(232,202,90,.10), transparent 62%),
    linear-gradient(#17372f, #122a24 62%, #0E211C);
  border: 1px solid #0a1a16;
  box-shadow: inset 0 0 0 1px rgba(232,202,90,.20), inset 0 0 90px rgba(0,0,0,.45);
  color: #E9E5D7; overflow: hidden;
}
.wheel-panel::before {            /* the gold frame line, as the bench has it */
  content: ""; position: absolute; inset: 9px; pointer-events: none;
  border: 1px solid rgba(232,202,90,.26); box-shadow: inset 0 0 0 3px rgba(10,26,22,.5);
}
.wheel-head { position: relative; z-index: 1; margin-bottom: 6px; }
.wheel-head h3 { font-family: 'Fraunces', serif; font-size: 21px; margin: 0 0 4px; color: #FFF4DC; }
.wheel-head p { margin: 0 auto; max-width: 52ch; font-size: 13px; line-height: 1.55; color: #B9C9BE; }

.wheel-rig { position: relative; width: min(430px, 88%); aspect-ratio: 1;
  margin: 14px auto 8px; display: grid; place-items: center; z-index: 1; }
.wheel-shadow { position: absolute; inset: 10% 8% 5%; border-radius: 50%;
  background: rgba(0,0,0,.56); filter: blur(25px); transform: translateY(23px); }
/* NO TRANSITION. The spin is driven frame by frame in app.jsx, because the
   tick sounds and the pointer's ratchet both need the wheel's speed at each
   instant and a CSS transition cannot tell anyone what it is doing. */
.wheel-rig .wheel { position: relative; width: 88%; height: 88%; border-radius: 50%;
  will-change: transform; filter: drop-shadow(0 18px 24px rgba(0,0,0,.45)); }
.wheel-rig .wheel > svg { width: 100%; height: 100%; display: block; border-radius: 50%; }
.wheel-rim { position: absolute; border-radius: 50%; pointer-events: none; }
.rim-outer { inset: -3.2%; border: 14px ridge #88651e;
  box-shadow: inset 0 0 0 3px #d9be62, 0 0 0 3px #3e2a0d, 0 0 24px rgba(232,202,90,.22); }
.rim-inner { inset: 3.1%; border: 2px solid rgba(255,235,159,.72);
  box-shadow: inset 0 0 0 5px rgba(67,39,11,.34); }
.hub { position: absolute; left: 50%; top: 50%; width: 19%; height: 19%;
  display: grid; place-items: center; align-content: center;
  border: 8px double #f1dc82; border-radius: 50%; color: #f7eab3;
  background: radial-gradient(circle at 34% 27%, #b98a30, #705019 55%, #2c1d09);
  box-shadow: 0 8px 18px rgba(0,0,0,.5), inset 0 0 16px rgba(255,230,131,.25);
  transform: translate(-50%,-50%); }
.hub span { font: 700 clamp(19px, 3.6vw, 30px)/.8 'Fraunces', serif; text-shadow: 0 2px 1px #3a2508; }
.hub small { margin-top: 6px; font: 6.5px 'IBM Plex Mono', monospace; letter-spacing: .14em; }

.pointer-assembly { position: absolute; left: 50%; top: -1.5%; z-index: 12;
  width: 96px; height: 124px; transform: translateX(-50%);
  filter: drop-shadow(0 7px 5px rgba(0,0,0,.5)); }
.pointer-crown { position: absolute; left: 50%; top: 0; color: #e8cc67;
  font: 26px 'Fraunces', serif; transform: translateX(-50%); text-shadow: 0 2px #573c12; }
.pointer { position: absolute; left: 50%; top: 25px; width: 38px; height: 74px;
  transform-origin: 50% 8px; transform: translateX(-50%); }
.pointer span { display: block; width: 100%; height: 100%;
  clip-path: polygon(50% 100%, 3% 12%, 23% 0, 77% 0, 97% 12%);
  background: linear-gradient(90deg, #6f4c18 0, #f3dd80 37%, #fff2b3 50%, #be8d2e 68%, #58380d 100%);
  box-shadow: inset 0 0 0 3px #5c3c0e; }
.pointer-pin { position: absolute; left: 50%; top: 29px; z-index: 2; width: 20px; height: 20px;
  border: 5px double #f5df80; border-radius: 50%; background: #6d4a16; transform: translateX(-50%); }
/* The tongue is positioned by the spin loop too — a keyframe cannot know
   which division it is riding. */

.wheel-slice { stroke: rgba(225,201,128,.78); stroke-width: 2; filter: saturate(.82) sepia(.12); }
.wheel-label { fill: #fff8db; font-family: 'IBM Plex Mono', monospace; font-size: 12px;
  font-weight: 700; letter-spacing: .02em; text-anchor: middle; paint-order: stroke;
  stroke: rgba(20,21,17,.48); stroke-width: 3px; stroke-linejoin: round; }
.wheel-number { fill: rgba(255,244,198,.72); font-family: 'IBM Plex Mono', monospace;
  font-size: 9px; text-anchor: middle; }
.wheel-stud { fill: #f0d979; stroke: #654613; stroke-width: 3; }

.wheel-act { position: relative; z-index: 1; margin-top: 4px; }
.wheel-go { background: #C49123; border-color: #7A6115; color: #20261F; font-weight: 700;
  padding: 11px 26px; font-size: 15px; }
.wheel-go:hover:not(:disabled) { background: #D9A93A; }
.wheel-note { margin: 10px auto 0; max-width: 52ch; font-size: 12.5px; line-height: 1.5; color: #A9BCAE; }

.wheel-result { position: relative; z-index: 1; margin: 16px auto 0; max-width: 460px;
  font-size: 14.5px; line-height: 1.5; color: #EFEAD9; }
.wheel-result.is-jackpot { padding: 12px 16px; border: 2px solid #7E1F33;
  background: rgba(126,31,51,.28); font-weight: 600; color: #FFE9EE; }

/* An unclaimed jackpot is the only thing on this panel that needs
   answering, so it takes the whole floor and the spin button goes quiet. */
.wheel-claim { position: relative; z-index: 1; margin: 16px auto 0; max-width: 520px;
  padding: 16px 18px; border: 2px solid #7E1F33; background: rgba(126,31,51,.30); }
.wheel-claim h4 { margin: 0 0 4px; font: 600 17px 'Fraunces', serif; color: #FFE9EE; }
.wheel-claim p { margin: 0 0 12px; font-size: 13px; line-height: 1.5; color: #E8CCD3; }
.wheel-choices { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.wheel-choices .btn { background: #7E1F33; border-color: #5A1524; color: #fff; font-weight: 600; }
.wheel-choices .btn:hover:not(:disabled) { background: #93253C; }

/* ── THE CELEBRATION ──────────────────────────────────────────────────────
   Three of the twenty divisions get a treatment of their own, and they must
   not be mistakable for each other:

     super rare    claret and gold, rays, rings, and the panel itself moving
     rare          gold only, rays, rings, panel still
     another pull  green glow, no rays, no rings

   Ported from the v1 bench. Every purple in it has become claret — purple is
   the Historic property tier and cannot also mean jackpot. The colours are
   literal rather than tokens, exactly as the wheel drawing above is, because
   the panel carries its own dark ground in all four palettes. */

.wheel-stage { position: relative; width: min(430px, 88%); margin: 14px auto 8px;
  z-index: 1; display: grid; place-items: center; }
.wheel-stage > .wheel-rig { width: 100%; margin: 0; }

/* Too fast to read. Sits over the face while the wheel is in motion. */
.speed-lines { position: absolute; inset: 4%; border-radius: 50%; opacity: 0;
  pointer-events: none; z-index: 3;
  background: repeating-conic-gradient(from 0deg, rgba(255,238,172,0) 0 4deg,
    rgba(255,238,172,.16) 4.5deg 5deg, transparent 5.5deg 11deg);
  -webkit-mask: radial-gradient(circle, transparent 0 52%, #000 67%, transparent 78%);
  mask: radial-gradient(circle, transparent 0 52%, #000 67%, transparent 78%);
  transition: opacity .35s ease; }
.wheel-stage.is-spinning .speed-lines { opacity: 1; animation: speed-haze .24s linear infinite; }
@keyframes speed-haze { to { transform: rotate(11deg); } }

/* Every landing gets the flare. It is the full stop on the spin. */
.result-flare { position: absolute; inset: 10%; border-radius: 50%; opacity: 0;
  pointer-events: none; z-index: 18;
  background: radial-gradient(circle at 50% 4%, rgba(255,248,196,.95),
    rgba(241,205,73,.28) 13%, transparent 39%); }
.wheel-panel.is-result .result-flare { animation: result-flare .9s ease-out; }
@keyframes result-flare { 0% { opacity: 0; transform: scale(.75); } 22% { opacity: 1; }
  100% { opacity: 0; transform: scale(1.18); } }

/* Rays: rare sweeps once in gold, super rare sweeps four times as long with
   claret cut into it. Another pull gets none, which is the difference. */
.celebration-rays { position: absolute; inset: -26%; z-index: 20; border-radius: 50%;
  opacity: 0; pointer-events: none;
  background: repeating-conic-gradient(from 0deg, rgba(255,238,153,.82) 0 2deg,
    transparent 3deg 10deg);
  -webkit-mask: radial-gradient(circle, transparent 0 17%, #000 25%, transparent 72%);
  mask: radial-gradient(circle, transparent 0 17%, #000 25%, transparent 72%); }
.wheel-panel.result-rare .celebration-rays { animation: rare-rays 1.8s ease-out; }
.wheel-panel.result-super-rare .celebration-rays {
  background: repeating-conic-gradient(from 0deg, rgba(255,240,145,.95) 0 2deg,
    transparent 3deg 8deg, rgba(196,64,92,.8) 9deg 11deg, transparent 12deg 18deg);
  animation: jackpot-rays 3.2s cubic-bezier(.12,.7,.22,1); }
@keyframes rare-rays { 0% { opacity: 0; transform: scale(.5) rotate(0); }
  20% { opacity: .85; } 100% { opacity: 0; transform: scale(1.28) rotate(38deg); } }
@keyframes jackpot-rays { 0% { opacity: 0; transform: scale(.25) rotate(0); }
  13%, 45% { opacity: 1; } 75% { opacity: .55; }
  100% { opacity: 0; transform: scale(1.55) rotate(140deg); } }

/* The pieces. Thrown by wheelCelebration in app.jsx, which sets every
   custom property below; the stylesheet only says how they fly. */
.celebration-layer { position: absolute; inset: -35%; z-index: 28;  /* in front of
  the banner: pieces launched late appear at the centre, and behind the
  banner they would be hidden for the whole first half of their flight */
  overflow: visible; pointer-events: none; }
.celebration-particle { position: absolute; left: 50%; top: 44%;
  width: var(--size); height: calc(var(--size) * .42); opacity: 0;
  background: var(--particle);
  box-shadow: 0 0 10px color-mix(in srgb, var(--particle) 80%, transparent);
  transform: translate(-50%,-50%) rotate(var(--start-rotation)); }
.celebration-particle.coin { height: var(--size); border: 2px solid #FFF0A4;
  border-radius: 50%; background: #B9871E; }
.celebration-particle.star { height: var(--size);
  clip-path: polygon(50% 0, 61% 36%, 100% 50%, 63% 62%, 50% 100%, 38% 63%, 0 50%, 36% 38%); }
.celebration-particle.streamer { width: calc(var(--size) * .38);
  height: calc(var(--size) * 2.5); border-radius: 50%; }
.wheel-panel.result-rare .celebration-particle,
.wheel-panel.result-super-rare .celebration-particle,
.wheel-panel.result-again .celebration-particle {
  animation: particle-flight var(--duration) var(--delay) cubic-bezier(.16,.66,.26,1) forwards; }
/* The bench's own curve faded the pieces out across the whole flight and
   shrank them on the way, which left them at three pixels and a fifth of an
   opacity for most of their life — they were there and nobody could see
   them. They now hold their colour to seven tenths of the way out and grow
   slightly rather than shrink. */
@keyframes particle-flight {
  0% { opacity: 0; transform: translate(-50%,-50%) rotate(var(--start-rotation)) scale(.45); }
  9% { opacity: 1; }
  70% { opacity: .92; }
  100% { opacity: 0;
    transform: translate(calc(-50% + var(--travel-x)), calc(-50% + var(--travel-y)))
      rotate(var(--end-rotation)) scale(1.05); } }

.burst-ring { position: absolute; left: var(--ring-x); top: var(--ring-y);
  width: 35px; height: 35px; border: 4px solid var(--ring-color); border-radius: 50%;
  opacity: 0; box-shadow: 0 0 18px var(--ring-color), inset 0 0 12px var(--ring-color);
  transform: translate(-50%,-50%) scale(.15); }
.wheel-panel.result-rare .burst-ring,
.wheel-panel.result-super-rare .burst-ring {
  animation: burst-ring var(--ring-duration) var(--ring-delay) cubic-bezier(.1,.7,.18,1) forwards; }
@keyframes burst-ring { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.15); }
  12% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(9); border-width: 1px; } }

/* What the rig and the panel themselves do. */
.wheel-panel.result-rare .wheel-rig { animation: rare-rig-glow 2.4s ease-out; }
.wheel-panel.result-rare { animation: rare-stage 1.35s ease-out; }
.wheel-panel.result-super-rare .wheel-rig { animation: jackpot-rig 3.4s ease-out; }
.wheel-panel.result-super-rare { animation: jackpot-stage 1.6s ease-out; }
.wheel-panel.result-super-rare::before { animation: jackpot-border 2.8s ease-out; }
.wheel-panel.result-super-rare::after { animation: jackpot-felt 3.2s ease-out; }
/* Filter only, deliberately: the wheel's own transform is written frame by
   frame from script, and a keyframe touching transform would fight it. */
.wheel-panel.result-again .wheel-rig .wheel { animation: free-spin-wheel 1.1s ease-in-out; }

@keyframes rare-rig-glow { 0%, 100% { filter: none; }
  16%, 48% { filter: drop-shadow(0 0 38px rgba(255,224,94,.95)); }
  32%, 68% { filter: drop-shadow(0 0 18px rgba(255,246,184,.7)); } }
@keyframes rare-stage { 18% { box-shadow: inset 0 0 110px rgba(255,216,74,.5); }
  38% { transform: translateX(-2px); } 41% { transform: translateX(2px); } }
@keyframes jackpot-rig { 0%, 100% { filter: none; }
  8%, 28%, 49%, 70% { filter: drop-shadow(0 0 52px rgba(255,220,73,1)) brightness(1.18);
    transform: scale(1.018); }
  18%, 39%, 60%, 82% { filter: drop-shadow(0 0 72px rgba(196,64,92,1)) brightness(1.32);
    transform: scale(.995); } }
@keyframes jackpot-stage {
  0%, 100% { transform: translate(0); box-shadow: inset 0 0 0 rgba(0,0,0,0); }
  8% { transform: translate(-5px,2px); box-shadow: inset 0 0 150px rgba(255,221,76,.72); }
  15% { transform: translate(5px,-2px); }
  23% { transform: translate(-4px,1px); box-shadow: inset 0 0 170px rgba(160,40,66,.7); }
  32% { transform: translate(3px,-1px); }
  43% { transform: translate(-2px,1px); box-shadow: inset 0 0 150px rgba(255,234,118,.62); }
  62% { transform: translate(1px); box-shadow: inset 0 0 135px rgba(140,38,60,.45); } }
@keyframes jackpot-border { 15%, 48%, 78% { border-color: rgba(255,239,153,.98);
  box-shadow: inset 0 0 45px rgba(255,228,105,.42), inset 0 0 0 3px rgba(200,70,100,.85); } }
@keyframes free-spin-wheel { 0%, 100% { filter: none; }
  35% { filter: drop-shadow(0 0 35px rgba(121,232,181,.85)); } }

/* The ground flash behind everything, jackpot only. Invisible at rest. */
.wheel-panel::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  opacity: 0; background: radial-gradient(ellipse at 50% 40%, rgba(232,202,90,.42),
    rgba(196,64,92,.16) 46%, transparent 72%); }
@keyframes jackpot-felt { 0%, 100% { opacity: 0; filter: none; }
  12%, 44%, 72% { opacity: .9; filter: brightness(1.9); }
  26%, 58% { opacity: .5; filter: brightness(1.35); } }

/* How the verdict arrives. Three shapes, matching the three outcomes. */
@keyframes rare-arrive { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.25) rotate(-7deg); }
  28% { opacity: 1; transform: translate(-50%,-50%) scale(1.17) rotate(2deg); }
  44% { transform: translate(-50%,-50%) scale(.95) rotate(-1deg); }
  58%, 100% { opacity: 1; transform: translate(-50%,-50%) scale(1.03) rotate(-1deg); } }
@keyframes free-spin-arrive { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.45) rotate(5deg); }
  60%, 100% { opacity: 1; transform: translate(-50%,-50%) scale(1) rotate(1deg); } }
@keyframes jackpot-arrive { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.18) rotate(-11deg); }
  18% { opacity: 1; transform: translate(-50%,-50%) scale(1.24) rotate(3deg); }
  29% { transform: translate(-50%,-50%) scale(.9) rotate(-2deg); }
  39%, 53%, 67%, 81% { opacity: 1; transform: translate(-50%,-50%) scale(1.08) rotate(1deg);
    filter: brightness(1.45); }
  46%, 60%, 74%, 88%, 100% { opacity: 1; transform: translate(-50%,-50%) scale(1) rotate(-1deg);
    filter: brightness(1); } }

/* The crown and the marquee belong to the jackpot alone, and are not drawn
   at all otherwise — the claim panel only ever appears for it. */
/* THE VERDICT, OVER THE WHEEL.

   This is the piece the first port dropped, and it is the piece that carries
   the moment: the wheel stops, and the answer lands on top of it. All three
   banners sit in the stage at all times and all three are invisible until an
   outcome class picks one, so nothing has to be mounted at the instant it is
   needed. The jackpot's is claret and gold where the bench had purple. */
.award-banner { position: absolute; left: 50%; top: 48%; z-index: 26;
  min-width: min(330px, 78%); padding: 15px 30px 13px; opacity: 0;
  text-align: center; pointer-events: none;
  transform: translate(-50%,-50%) scale(.5) rotate(-3deg); }
.award-banner small, .award-banner span { display: block;
  font: 9px 'IBM Plex Mono', monospace; letter-spacing: .17em; }
.award-banner strong { display: block; margin: 3px 0;
  font: 700 38px/.95 'Fraunces', serif; letter-spacing: .04em; }
.rare-banner { border: 5px double #FFF1A1; color: #FFF2B0;
  background: linear-gradient(115deg, #6D4B0B, #BD8C20 48%, #563708);
  box-shadow: 0 0 0 4px #4D340B, 0 0 64px rgba(255,220,78,.85),
    inset 0 0 25px rgba(255,244,176,.24); }
.jackpot-banner { border: 5px double #FFE995; color: #FFEDDF;
  background: linear-gradient(115deg, #4A1020, #93253C 48%, #3E0D1B);
  box-shadow: 0 0 0 4px #A57C24, 0 0 70px rgba(242,216,91,.88),
    inset 0 0 25px rgba(255,226,107,.25); }
.free-spin-banner { border: 5px double #CBE9C8; color: #F0F4D6;
  background: linear-gradient(115deg, #153D35, #28725D 48%, #15362F);
  box-shadow: 0 0 0 4px #8FA76A, 0 0 55px rgba(115,220,171,.6),
    inset 0 0 25px rgba(202,244,199,.18); }
.jackpot-crown { position: absolute; left: 50%; top: -70px; opacity: 0;
  font: 64px/1 'Fraunces', serif; font-style: normal; color: #FFE682;
  filter: drop-shadow(0 0 9px #FFF3AA) drop-shadow(0 0 25px #D7A72C);
  transform: translateX(-50%); }
.marquee-lights { position: absolute; inset: -13px; opacity: 0; pointer-events: none;
  border: 5px dotted #FFF1A1; box-shadow: 0 0 18px #FFDE64; }
.wheel-panel.result-rare .rare-banner {
  animation: rare-arrive 2.2s .14s cubic-bezier(.17,.82,.21,1.18) forwards; }
.wheel-panel.result-super-rare .jackpot-banner {
  animation: jackpot-arrive 3.25s .1s cubic-bezier(.17,.82,.21,1.22) forwards; }
.wheel-panel.result-again .free-spin-banner {
  animation: free-spin-arrive .85s .14s cubic-bezier(.17,.82,.21,1.18) forwards; }
.wheel-panel.result-super-rare .jackpot-crown {
  animation: crown-jump 1.55s .45s cubic-bezier(.15,.8,.22,1.25) both; }
.wheel-panel.result-super-rare .marquee-lights {
  opacity: 1; animation: marquee-blaze .28s .72s steps(2,end) 9; }
@keyframes crown-jump {
  0% { opacity: 0; transform: translateX(-50%) translateY(45px) scale(.25) rotate(-16deg); }
  55% { opacity: 1; transform: translateX(-50%) translateY(-10px) scale(1.25) rotate(7deg); }
  100% { opacity: 1; transform: translateX(-50%) scale(1) rotate(-2deg); } }
@keyframes marquee-blaze { 50% { border-color: #C4405C;
  box-shadow: 0 0 28px #FFF5AE, 0 0 50px #C4405C; } }

/* On a phone the banner has to fit inside the panel, which clips. */
@media (max-width: 620px) {
  .award-banner { min-width: min(250px, 62vw); padding: 12px 14px 10px; }
  .award-banner strong { font-size: 26px; }
  .award-banner small, .award-banner span { font-size: 8px; letter-spacing: .12em; }
  .jackpot-crown { top: -46px; font-size: 44px; }
  .marquee-lights { inset: -9px; border-width: 4px; }
}

/* Asked not to be moved: keep the colour, drop everything that travels. */
@media (prefers-reduced-motion: reduce) {
  .wheel-panel, .wheel-panel::before, .wheel-panel::after,
  .wheel-panel .wheel-rig, .wheel-panel .wheel-rig .wheel,
  .speed-lines, .result-flare, .celebration-rays, .celebration-particle,
  .burst-ring, .marquee-lights,
  .award-banner, .jackpot-crown { animation: none !important; }
  .wheel-panel.result-rare .rare-banner,
  .wheel-panel.result-super-rare .jackpot-banner,
  .wheel-panel.result-again .free-spin-banner {
    opacity: 1; transform: translate(-50%,-50%); }
  .jackpot-crown { opacity: 1; }
}


/* Reduced motion is handled in app.jsx: the wheel is placed at its result
   with no spin, no whirr and no ticks. The verdict chord still plays — that
   is an announcement, not motion. */

/* ---------------------------------------------------------------------
   THE REGISTER, AND THE TWO FIGURES CORRUPT THE REGISTER MOVES
   --------------------------------------------------------------------- */

/* A MARKED FIGURE IS STILL SHOWN, JUST NOT TRUSTED.

   Slight on purpose. Enough blur that the eye catches it without hunting,
   not so much that the number cannot be read — a figure you cannot read at
   all is a broken screen, and the player reports a fault instead of playing
   around a card. It is never removed on hover: the number underneath is
   wrong too, and un-blurring it would say otherwise. */
.is-suspect {
  filter: blur(0.85px);
  opacity: .88;
  border-bottom: 1px dotted var(--loss);
  padding-bottom: 1px;
  cursor: help;
}
@media (prefers-reduced-motion: reduce) { .is-suspect { filter: blur(0.6px); } }

.reg-panel {
  margin: 0 0 14px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--loss);
  background: var(--paper-dark);
}
.reg-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 9px 13px 8px;
  border-bottom: 1px solid var(--line);
}
.reg-head h4 {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 15px;
  color: var(--ink);
}
.reg-count {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: .72;
}
.reg-list { margin: 0; padding: 0; list-style: none; }
.reg-item { border-bottom: 1px solid var(--line); }
.reg-item:last-child { border-bottom: 0; }

/* The whole row is the control. A small chevron beside a long label is a
   target nobody hits on a phone. */
.reg-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 13px;
  font: inherit; font-size: 13.5px; text-align: left;
  color: var(--ink); background: transparent; border: 0; cursor: pointer;
}
.reg-row:hover { background: var(--paper); }
.reg-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--loss); }
.tone-good .reg-dot { background: var(--gain); }
.tone-watch .reg-dot { background: var(--gold); }
.reg-title { flex: 1; min-width: 0; }
.reg-until {
  flex: none;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 11px; opacity: .7;
}
.reg-chev { flex: none; width: 1em; text-align: center; opacity: .55; font-family: var(--mono); }
.reg-item.is-open { background: var(--paper); }

.reg-detail { padding: 0 13px 12px 30px; }
.reg-detail p { margin: 0 0 8px; font-size: 13px; line-height: 1.55; max-width: 62ch; opacity: .92; }
.reg-card {
  margin-top: 4px; padding: 8px 11px 9px;
  border: 1px solid var(--line); background: var(--paper-dark);
}
.reg-card b { font-family: 'Fraunces', Georgia, serif; font-size: 14px; }
.reg-card-rarity {
  margin-left: 8px;
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .14em;
  text-transform: uppercase; opacity: .6;
}
.reg-card p { margin: 4px 0 0; font-size: 12.5px; opacity: .85; }
.reg-nocard { font-style: italic; opacity: .7; }

@media (max-width: 620px) {
  .reg-row { flex-wrap: wrap; gap: 6px 9px; }
  .reg-title { flex: 1 1 100%; order: 2; }
  .reg-detail { padding-left: 13px; }
}

/* THE COST OF AN ORDER, QUOTED BEFORE IT IS SEALED.

   It reuses the order-quote shell so it sits flush with the security
   reading beneath it, and takes the brick accent because it is the only
   figure on the panel that leaves the player's own account. When the cash
   will not cover it the whole block turns, rather than a small word
   somewhere in the sentence. */
.order-cost { border-left-color: var(--brick); }
.order-cost strong {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 19px;
  color: var(--brick);
}
.order-cost.is-short {
  background: rgba(176, 52, 42, .09);
  border-left-color: var(--loss);
}
.order-cost.is-short strong { color: var(--loss); }

/* ---------------------------------------------------------------------
   A DODGY TENANT, ON THE TILE

   Loud enough that an owner scrolling a portfolio cannot miss which
   building has stopped earning, and quiet enough not to look like an
   error. The brick accent is the same one the order cost uses: both are
   money leaving this player's account.
   --------------------------------------------------------------------- */
.tenant-box {
  margin: 8px 0 0;
  padding: 8px 10px 9px;
  border: 1px solid var(--brick);
  border-left-width: 4px;
  background: rgba(162, 62, 39, .07);
  cursor: default;
}
.tenant-box.is-theirs { border-color: var(--line); background: var(--paper-dark); }
.tenant-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tenant-head b { font-size: 13px; color: var(--brick); }
.is-theirs .tenant-head b { color: var(--ink); opacity: .75; }
.tenant-mark {
  flex: none; width: 9px; height: 9px; border-radius: 2px;
  background: var(--brick); transform: rotate(45deg);
}
.is-theirs .tenant-mark { background: var(--line); }
.tenant-clock {
  margin-left: auto;
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em;
  font-variant-numeric: tabular-nums; opacity: .72;
}
.tenant-sums { display: flex; gap: 16px; flex-wrap: wrap; margin: 7px 0 0; }
.tenant-sums div { display: flex; flex-direction: column; gap: 1px; }
.tenant-sums span {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .13em;
  text-transform: uppercase; opacity: .68;
}
.tenant-sums strong {
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 15px;
}
.tenant-sums div:first-child strong { color: var(--brick); }
.tenant-note { margin: 6px 0 7px; font-size: 12px; line-height: 1.45; opacity: .85; }

/* ---- the district leader's reward (25 Sep 2026) ----
   Magenta is the role's colour on the map (#C2439B), chosen because neither
   the rarity scheme nor the ownership scheme uses it; the chooser borrows it
   so the title reads as the same thing wherever it appears. */
.leader-bar { display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:12px;
  padding:7px 20px; background:#4a1d3d; color:#F7E9F2; font-size:12.5px; border-bottom:1px solid var(--ink); }
.leader-bar .leader-crown { color:#f0a6d6; font-size:15px; line-height:1; }
.leader-bar-go { padding:3px 10px; cursor:pointer; font-size:12px; color:#2a0f22; background:#f0a6d6;
  border:1px solid #f0a6d6; }
.leader-bar-go:hover, .leader-bar-go:focus-visible { background:#f7c6e5; }
@media (max-width: 640px) { .leader-bar { font-size:11.5px; padding:6px 12px; gap:8px; } }

.leader-rewards { display:grid; gap:14px; margin:14px 0 18px; }
.leader-reward-card { border:1px solid #C2439B; border-left-width:4px; padding:12px 14px; background:rgba(194,67,155,.05); }
.leader-reward-card header { display:flex; gap:10px; align-items:flex-start; }
.leader-reward-card .leader-crown { color:#C2439B; font-size:22px; line-height:1.1; }
.leader-reward-card h4 { margin:0; font-size:16px; }
.leader-reward-card header p { margin:3px 0 0; font-size:12.5px; color:#6b6455; max-width:70ch; }
.leader-reward-options { display:grid; grid-template-columns:repeat(auto-fit, minmax(190px, 1fr)); gap:8px; margin-top:12px; }
.leader-reward { display:flex; flex-direction:column; gap:4px; text-align:left; padding:10px 12px; cursor:pointer;
  background:#fbf7ee; border:1px solid var(--line); color:inherit; font:inherit; }
.leader-reward b { font-size:13.5px; display:flex; flex-wrap:wrap; gap:6px; align-items:baseline; }
.leader-reward b em { font-style:normal; font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.1em;
  text-transform:uppercase; color:#8e2c70; }
.leader-reward span { font-size:12.5px; line-height:1.45; color:#4d473b; }
.leader-reward i { font-style:normal; font-family:'IBM Plex Mono', monospace; font-size:11.5px; color:#6b6455;
  font-variant-numeric:tabular-nums; margin-top:auto; }
.leader-reward:hover:not(:disabled), .leader-reward:focus-visible { border-color:#C2439B; }
.leader-reward.is-on { border:2px solid #C2439B; background:#fff; cursor:default; }
.leader-reward:disabled:not(.is-on) { opacity:.55; cursor:not-allowed; }
/* The magnate, who owns the whole district (30 Sep 2026): royal indigo. */
.leader-reward-card.is-magnate { border-color:#2A2896; background:rgba(42,40,150,.05); }
.leader-reward-card.is-magnate .leader-crown { color:#2A2896; }
.leader-reward-card.is-magnate .leader-reward:hover:not(:disabled),
.leader-reward-card.is-magnate .leader-reward:focus-visible { border-color:#2A2896; }
.leader-reward-card.is-magnate .leader-reward.is-on { border-color:#2A2896; }
.leader-reward-card.is-magnate .leader-reward b em { color:#2A2896; }
.leader-slot-label { margin-top:12px; font:600 11px 'IBM Plex Mono', monospace; letter-spacing:.06em; color:#2A2896; }
.leader-slot-label + .leader-reward-options { margin-top:6px; }

/* ---- the evening, unfolding (25 Sep 2026) ----
   Night ink with the brass of the reckoning theatre, so the two read as one
   place. The only moving parts are the card arriving, the defence line, and
   the verdict stamp: the suspense lives in the gap before the stamp. */
.eve-bar { display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:12px;
  padding:8px 20px; background:#141c2b; color:#E9E4D4; font-size:12.5px; border-bottom:1px solid #cba94e; }
.eve-bar-moon { color:#cba94e; font-size:16px; line-height:1; }
.eve-bar-go { padding:4px 12px; cursor:pointer; font-size:12.5px; font-weight:600; color:#141c2b;
  background:#cba94e; border:1px solid #cba94e; }
.eve-bar-go:hover, .eve-bar-go:focus-visible { background:#e2c46c; }
.eve-bar-skip { padding:4px 10px; cursor:pointer; font-size:12px; color:#E9E4D4; background:transparent;
  border:1px solid rgba(233,228,212,.35); }
@media (max-width: 640px) { .eve-bar { font-size:11.5px; padding:7px 12px; gap:8px; } }

.eve-rewatch { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px;
  padding:10px 14px; margin:0 0 14px; background:#141c2b; color:#E9E4D4; border-left:3px solid #cba94e; }
.eve-rewatch button { padding:5px 12px; cursor:pointer; color:#141c2b; background:#cba94e; border:1px solid #cba94e; font-weight:600; }

.eve-overlay { z-index:90; }
.eve-stage { width:min(760px, 100%); max-height:94vh; overflow:auto; padding:20px 22px 24px;
  background:linear-gradient(180deg, #19233a, #0f1522); color:#EDE7D5; border:1px solid #cba94e;
  box-shadow:0 30px 70px rgba(0,0,0,.55); display:flex; flex-direction:column; gap:16px; }
.eve-head { display:flex; flex-wrap:wrap; justify-content:space-between; align-items:flex-end; gap:10px; }
.eve-kicker { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:#cba94e; }
.eve-head h3 { margin:2px 0 0; font-size:22px; color:#F4EDDC; }
.eve-controls { display:flex; flex-wrap:wrap; gap:6px; }
.eve-controls button { padding:5px 10px; cursor:pointer; font-size:12px; color:#EDE7D5; background:transparent;
  border:1px solid rgba(203,169,78,.5); }
.eve-controls button[aria-pressed="true"] { background:rgba(203,169,78,.18); }
.eve-controls .eve-close { color:#141c2b; background:#cba94e; border-color:#cba94e; font-weight:600; }
.eve-progress { display:flex; gap:4px; }
.eve-progress i { flex:1; height:3px; background:rgba(237,231,213,.15); }
.eve-progress i.is-done { background:#cba94e; }
.eve-progress i.is-now { background:#EDE7D5; }

.eve-beat { display:grid; grid-template-columns:auto 1fr; grid-template-areas:"dir dir" "card lines"; gap:12px 20px; align-items:start; }
.eve-dir { grid-area:dir; font-family:'IBM Plex Mono', monospace; font-size:11px; letter-spacing:.16em; text-transform:uppercase; }
.eve-beat.is-mine .eve-dir { color:#9fd1b3; }
.eve-beat.is-against .eve-dir { color:#f09a82; }
.eve-beat.is-street .eve-dir { color:#e8c98a; }
.eve-card { grid-area:card; }
.eve-lines { grid-area:lines; display:flex; flex-direction:column; gap:12px; min-width:0; }
.eve-target { margin:0; font-size:16px; line-height:1.45; }
.eve-target b { color:#F4EDDC; }
.eve-defence, .eve-security, .eve-consequence, .eve-cost { margin:0; font-size:15px; line-height:1.5; color:#d8d1bf; }
.eve-cost { font-family:'IBM Plex Mono', monospace; font-size:13px; color:#b9b19c; }
.eve-verdict { margin:4px 0; align-self:flex-start; padding:4px 14px; font-family:'IBM Plex Mono', monospace;
  font-size:24px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; border:3px solid currentColor; }
.eve-verdict.tone-good { color:#7fd3a0; }
.eve-verdict.tone-bad { color:#f0826a; }
.eve-verdict.tone-grey { color:#b9b19c; }

.eve-tally { display:flex; flex-direction:column; gap:10px; }
.eve-tally .eve-dir { color:#cba94e; }
.eve-tally p { margin:0; font-size:17px; line-height:1.5; }
.eve-tally .eve-city { font-size:13.5px; color:#b9b19c; border-top:1px solid rgba(203,169,78,.3); padding-top:10px; }
.eve-again button { padding:6px 14px; cursor:pointer; color:#EDE7D5; background:transparent; border:1px solid rgba(203,169,78,.5); }

@media (prefers-reduced-motion: no-preference) {
  .eve-card { animation:eveCardIn .55s cubic-bezier(.2,.8,.2,1) both; }
  .eve-defence, .eve-security, .eve-consequence, .eve-cost { opacity:0; transform:translateY(6px); transition:opacity .35s ease, transform .35s ease; }
  .eve-defence.is-on, .eve-security.is-on, .eve-consequence.is-on, .eve-cost.is-on { opacity:1; transform:none; }
  .eve-verdict { opacity:0; transform:scale(1.9) rotate(-6deg); }
  .eve-verdict.is-on { animation:eveStamp .32s cubic-bezier(.2,.9,.3,1.3) forwards; }
}
@keyframes eveCardIn { from { opacity:0; transform:translateY(18px) rotateY(70deg); } to { opacity:1; transform:none; } }
@keyframes eveStamp { to { opacity:1; transform:scale(1) rotate(-3deg); } }

/* ON A PHONE THE VERDICT HAS TO ARRIVE ON SCREEN. A full size card pushed
   it below the fold, so the stamp — the one moment the whole theatre is
   built around — landed where nobody was looking. The card is drawn smaller
   beside the lines instead of above them, and the controls shrink to one row. */
@media (max-width: 560px) {
  .eve-stage { padding:14px 14px 18px; gap:12px; max-height:100vh; }
  .eve-head { align-items:flex-start; }
  .eve-head h3 { font-size:18px; }
  .eve-controls { gap:4px; }
  .eve-controls button { padding:4px 7px; font-size:11px; }
  .eve-beat { grid-template-columns:118px 1fr; gap:10px 12px; }
  .eve-card .tcard { --cw: 118px; }
  .eve-card .tcard-text, .eve-card .tcard-kind { display:none; }
  .eve-target, .eve-defence, .eve-security, .eve-consequence { font-size:14px; }
  .eve-lines { gap:8px; }
  .eve-verdict { font-size:17px; padding:3px 10px; border-width:2px; }
  .eve-tally p { font-size:15px; }
}

/* ---- diplomacy on the Gazette (25 Sep 2026) ----
   Set as the paper's own furniture, in its ink and rules, so the game reads
   as the Gazette's and not as a form bolted underneath it. */
.dip-field { display:flex; flex-direction:column; border-top:1px solid rgba(40,32,20,.25); }
.dip-row { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 14px;
  padding:10px 2px; border-bottom:1px solid rgba(40,32,20,.18); }
.dip-row.is-on { background:rgba(46,94,70,.07); }
.dip-who { display:flex; flex-direction:column; gap:2px; min-width:0; }
.dip-who b { font-size:15px; }
.dip-who span { font-size:13px; color:#5a5140; }
.dip-who .dip-warn { display:block; margin-top:3px; font-size:12.5px; color:#8C2F2F; }
.dip-walkout { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:10px 0 4px; font-size:13px; color:#5a5140; }
.dip-walkout span { flex:1 1 16rem; }
.dip-who i { font-style:italic; }
.dip-acts { display:flex; flex-wrap:wrap; gap:6px; }
.dip-acts button { padding:5px 10px; cursor:pointer; font-size:12.5px; color:#2a2418; background:transparent;
  border:1px solid rgba(40,32,20,.45); font-family:inherit; }
.dip-acts button.is-go { color:#f6f0e0; background:#2e5e46; border-color:#2e5e46; }
.dip-acts button:hover:not(:disabled), .dip-acts button:focus-visible { border-color:#2a2418; }
.dip-acts button:disabled { opacity:.5; cursor:not-allowed; }

.dip-board-wrap { overflow-x:auto; }
.dip-board { width:100%; border-collapse:collapse; font-size:13.5px; }
.dip-board th { text-align:left; font-weight:500; font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:#5a5140; padding:6px 8px; border-bottom:1px solid rgba(40,32,20,.35); }
.dip-board td { padding:8px; border-bottom:1px solid rgba(40,32,20,.15); vertical-align:top; }
.dip-board td span { display:block; font-size:11.5px; color:#6b614c; }
.dip-board td.is-hit { background:rgba(163,58,36,.08); }
.dip-board td.is-hit span { color:#8a2f1d; }
.dip-board tr.is-struck td { text-decoration-color:#8a2f1d; }
/* Scoped under .dip-board so it outranks `.dip-board td span`, which made
   the badge's text the grey of the member lines — dark on red, unreadable.
   The review screenshot is what showed it. */
.dip-board .dip-struck { display:inline-block; margin:2px 0 0 8px; padding:1px 6px; font-family:'IBM Plex Mono', monospace;
  font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:#f6f0e0; background:#8a2f1d; }
.dip-truces, .dip-events { margin:0; padding:0 0 0 18px; font-size:13.5px; line-height:1.7; }
.dip-events li.is-strike { font-weight:600; }
@media (max-width: 560px) {
  .dip-row { flex-direction:column; align-items:flex-start; }
}

/* Closing the deposit account: a quiet control at the foot of the card,
   opening into a short confirm that says exactly what is given up. */
.bank-close { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.bank-close-ask p { margin: 0 0 10px; font-size: 13px; line-height: 1.5; }
.bank-close-acts { display: flex; gap: 8px; flex-wrap: wrap; }

/* A compulsory sale: the price, the first refusal and the buy button, in one
   bordered note so it reads as an event on the building, not as its price. */
.cpo-sale { display: grid; gap: 8px; justify-items: start; margin: 8px 0; padding: 10px 12px;
  border: 1px solid var(--brick); border-radius: 6px; }
.cpo-sale p { margin: 0; font-size: 13px; line-height: 1.5; }
.cpo-sale-tag { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--brick); font-weight: 600; }
.cpo-sale.is-compact { margin: 0; max-width: 340px; }

/* The rules every tactics card is subject to, at the head of the library. */
.library-rules { margin: 0 0 14px; padding: 10px 14px; border-left: 3px solid var(--line); }
.library-rules b { display: block; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; margin-bottom: 4px; }
.library-rules p { margin: 0; font-size: 13px; line-height: 1.55; max-width: 68ch; }

/* Messages to your field, inside the Gazette. */
.dip-messages { display: grid; gap: 12px; }
.dip-say { display: grid; gap: 6px; }
.dip-say-label { font-size: 13px; }
.dip-say textarea { width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 4px; background: transparent; color: inherit; resize: vertical; }
.dip-say-foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.dip-say-count { font-size: 12px; opacity: .7; font-variant-numeric: tabular-nums; }
.dip-say-count.is-near { color: var(--brick); opacity: 1; }
.dip-msg-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.dip-msg-list li { padding: 8px 10px; border-left: 3px solid var(--line); }
.dip-msg-list li.is-mine { border-left-color: var(--gold); }
.dip-msg-list b { font-size: 13px; }
.dip-msg-when { font-size: 12px; opacity: .65; margin-left: 8px; }
.dip-msg-list p { margin: 4px 0 0; font-size: 14px; line-height: 1.45; overflow-wrap: anywhere; }

/* The Gazette's summary on the Intelligence tab: plain type, no paper. */
.intel-summary-head { margin: 8px 0 4px; font-size: 16px; font-weight: 600; line-height: 1.35; text-wrap: balance; }
.intel-summary-body { margin: 0; font-size: 14px; line-height: 1.55; max-width: 68ch; }

/* The portfolio's price history: what you paid, what it has done since, and
   a chart over a day, a week, a month or the whole time you have held it. */
.price-track { display: grid; gap: 6px; margin: 6px 0 2px; max-width: 360px; }
.price-track-paid { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; font-size: 13px; }
.price-track-paid b { font-variant-numeric: tabular-nums; }
.price-track-ranges { display: flex; flex-wrap: wrap; gap: 4px; }
.price-range { font: inherit; font-size: 12px; padding: 3px 8px; border: 1px solid var(--line); border-radius: 999px;
  background: transparent; color: inherit; cursor: pointer; }
.price-range.on { border-color: var(--navy); box-shadow: inset 0 0 0 1px var(--navy); font-weight: 600; }
.price-range:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.price-track-foot { font-size: 12.5px; }
.price-track-foot .muted-plain { opacity: .7; }
.price-track svg { max-width: 100%; height: auto; }

/* ---- THE BUILD TAB -------------------------------------------------------
   Plots as surveyor's particulars, the drawing board as two columns (the
   choices, and the house and its bill), the build as a stage list beside
   its own drawing. Colour follows the rest of the game: gold for the
   current stage and chosen options, brick for anything that went wrong. */
.bld { display: grid; gap: 14px; }
.bld-head { margin: 8px 0 0; font-size: 17px; }
.bld-plots { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.bld-plot { border: 1px solid var(--line); border-radius: 6px; padding: 12px 14px; display: grid; gap: 8px; align-content: start; }
.bld-plot.is-open { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.bld-plot-head { display: grid; gap: 2px; }
.bld-plot-head b { font-size: 15px; }
.bld-plot-head span { font-size: 12.5px; opacity: .75; }
.bld-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; margin: 0; }
.bld-facts div { display: grid; }
.bld-facts dt { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; opacity: .65; }
.bld-facts dd { margin: 0; font-size: 13.5px; font-variant-numeric: tabular-nums; }
.bld-report { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; font-size: 13px; }
.bld-unsurveyed { font-size: 12.5px; opacity: .7; }
.bld-tier { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; padding: 2px 7px; border-radius: 3px;
  border: 1px solid var(--line); font-weight: 600; }
.bld-tier.t-uncommon { border-color: #8E979F; }
.bld-tier.t-rare { border-color: var(--gold); color: var(--gold); }
.bld-tier.t-ultra { border-color: #B4342E; color: #B4342E; }
.bld-plot-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.muted-plain { font-size: 12.5px; opacity: .72; }

.bld-board, .bld-progress { display: grid; gap: 12px; }
.bld-board-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.bld-board-head h3 { margin: 0; }
.bld-board-head span { font-size: 12.5px; opacity: .75; }
.bld-board-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 760px) { .bld-board-grid { grid-template-columns: 1fr; } }
.bld-controls { display: grid; gap: 12px; }
.bld-group h4 { margin: 0 0 6px; font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; opacity: .75; font-weight: 600; }
.bld-opts { display: flex; flex-wrap: wrap; gap: 6px; }
.bld-opt { font: inherit; font-size: 13px; display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px;
  border: 1px solid var(--line); border-radius: 4px; background: transparent; color: inherit; cursor: pointer; }
.bld-opt em { font-style: normal; font-size: 11.5px; opacity: .7; font-variant-numeric: tabular-nums; }
.bld-opt.on { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); font-weight: 600; }
.bld-opt:disabled { opacity: .4; cursor: not-allowed; }
.bld-opt:focus-visible, .bld-spec:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.bld-sw { width: 12px; height: 12px; border-radius: 2px; border: 1px solid rgba(0,0,0,.25); }
.bld-specs { display: grid; gap: 6px; }
.bld-spec { font: inherit; text-align: left; display: grid; grid-template-columns: 16px 1fr auto; gap: 10px; align-items: start;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 4px; background: transparent; color: inherit; cursor: pointer; }
.bld-spec b { display: block; font-size: 13.5px; }
.bld-spec span span { display: block; font-size: 12.5px; opacity: .78; }
.bld-spec em { font-style: normal; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.bld-spec.on { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.bld-spec:disabled { opacity: .45; cursor: not-allowed; }
.bld-box { width: 14px; height: 14px; border: 1.5px solid currentColor; border-radius: 2px; margin-top: 2px; opacity: .7; }
.bld-spec.on .bld-box { background: var(--gold); border-color: var(--gold); opacity: 1; }
.bld-note { margin: 6px 0 0; font-size: 12.5px; opacity: .75; line-height: 1.5; }
.bld-name { width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; padding: 7px 10px; border: 1px solid var(--line);
  border-radius: 4px; background: transparent; color: inherit; }
.bld-preview { display: grid; gap: 10px; }
.bld-preview svg, .bld-progress svg { border-radius: 4px; max-width: 100%; height: auto; }
.bld-bill { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.bld-bill th { text-align: left; font-weight: 400; padding: 3px 0; }
.bld-bill td { text-align: right; font-variant-numeric: tabular-nums; padding: 3px 0; }
.bld-bill .bld-total th, .bld-bill .bld-total td { font-weight: 700; border-top: 1px solid var(--line); padding-top: 6px; }
.bld-next { font-size: 12.5px; }
.bld-stages { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 6px; }
.bld-stages li { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.bld-stages li::before { content: ""; width: 11px; height: 11px; border-radius: 50%; border: 1.5px solid var(--line); flex: none; }
.bld-stages li.done { opacity: .6; }
.bld-stages li.done::before { background: var(--gain); border-color: var(--gain); }
.bld-stages li.now { font-weight: 600; }
.bld-stages li.now::before { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(176,140,30,.22); }
.bld-flaw { margin-top: 6px; font-size: 13px; color: var(--brick); display: grid; gap: 6px; justify-items: start; }
.bld-find { margin-top: 6px; font-size: 13px; color: var(--gold); }
.bld-diary-head { margin: 4px 0 0; font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; opacity: .75; }
.bld-diary { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.bld-diary li { font-size: 13.5px; line-height: 1.45; display: grid; grid-template-columns: 74px 1fr; gap: 8px; }
.bld-diary time { font-size: 12px; opacity: .65; font-variant-numeric: tabular-nums; }
/* Builds under way, on the portfolio and a trader's profile. */
.bld-under { display: grid; gap: 8px; margin: 12px 0; }
.bld-under-h { margin: 0; font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; opacity: .75; }
.bld-under-row { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 12px; align-items: center;
  border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; background: var(--paper, transparent); }
.bld-under-art { width: 120px; height: 60px; border-radius: 3px; display: block; }
.bld-under-body { display: grid; gap: 3px; min-width: 0; }
.bld-under-body b { font-family: 'Fraunces', serif; font-size: 15px; font-weight: 600; }
.bld-under-body .muted-plain { font-size: 12.5px; }
.bld-under-bar { height: 6px; border-radius: 3px; background: rgba(0,0,0,.08); overflow: hidden; margin-top: 3px; }
.bld-under-bar i { display: block; height: 100%; background: var(--gold); border-radius: 3px; min-width: 6px; }
.bld-under-stage { font-size: 12px; opacity: .8; }
@media (max-width: 480px) { .bld-under-row { grid-template-columns: 90px minmax(0, 1fr); } .bld-under-art { width: 90px; height: 45px; } }
.bld-houses { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.bld-house { display: grid; grid-template-columns: 110px 1fr; gap: 10px; align-items: start; border: 1px solid var(--line); border-radius: 6px; padding: 10px; }
.bld-house-art { padding: 0; border: 0; background: none; cursor: pointer; }
.bld-house-art svg { width: 110px; height: 55px; border-radius: 3px; }
.built-credit { font-size: 12.5px; margin: 6px 0; opacity: .85; }
.bld-plot-art { display: block; border-radius: 4px; max-width: 100%; height: auto; }

/* The survey asks before it charges: the price sits on the second step. */
.bld-confirm { border:1px solid var(--line); border-left:3px solid var(--gold); background:var(--paper-dark, #DCD5C2);
  padding:10px 12px; border-radius:4px; display:grid; gap:8px; }
.bld-confirm p { margin:0; font-size:13px; line-height:1.45; }
.bld-confirm .bld-short { color:var(--loss); }
.bld-confirm-acts { display:flex; gap:8px; flex-wrap:wrap; }

/* Trade, property first: what you want, then who holds it. */
.want-box { display:grid; gap:6px; margin:4px 0 14px; }
.want-box > label { font-weight:600; font-size:13px; }
.want-box .search-input { width:100%; max-width:34rem; }
.want-results { display:grid; gap:6px; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); }
.want-row { display:grid; gap:1px; text-align:left; background:var(--paper); border:1px solid var(--line); border-radius:4px;
  padding:8px 10px; cursor:pointer; font:inherit; color:inherit; }
.want-row:hover { border-color:var(--forest); }
.want-row.is-picked { border-color:var(--forest); box-shadow:inset 3px 0 0 var(--forest); }
.want-row span { font-size:12px; color:var(--muted); }
.want-row .want-price { font-family:'IBM Plex Mono', monospace; color:var(--ink); }

/* Earlier evenings, each by its date, to watch again. */
.eve-past { margin:8px 0 14px; display:grid; gap:6px; }
.eve-past-h { font:500 10.5px 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
.eve-past-list { display:flex; flex-wrap:wrap; gap:6px; }
.eve-past-list button { display:grid; gap:1px; text-align:left; font:inherit; color:inherit; cursor:pointer;
  background:var(--paper); border:1px solid var(--line); border-radius:4px; padding:6px 10px; }
.eve-past-list button:hover { border-color:var(--forest); }
.eve-past-list b { font-size:12.5px; }
.eve-past-list span { font-size:11.5px; color:var(--muted); }

/* The opening week, in the Library. */
.owr { margin-top:22px; }
.owr-track { display:grid; gap:8px; grid-template-columns:repeat(auto-fill, minmax(118px, 1fr)); margin:8px 0 12px; }
.owr-card { display:grid; gap:4px; align-content:start; border:1px solid var(--line); border-top:3px solid var(--card-accent, var(--gold));
  border-radius:4px; padding:8px; background:var(--paper); font-size:12px; }
/* The popup's art, drawn for a card four times this size, shrunk into a
   fixed window so it can never spill over the words. */
.owr-art { height:86px; overflow:hidden; display:grid; place-items:center; position:relative; }
.owr-art .ow-art { transform:scale(.52); transform-origin:center center; margin:0; }
.owr-day { font:600 10.5px 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
.owr-state { color:var(--muted); font-size:11.5px; line-height:1.35; }
.owr-card.is-missed { opacity:.55; }
.owr-card.is-taken .owr-state { color:var(--gain); }
.owr-card.is-today { box-shadow:0 0 0 2px var(--card-accent, var(--gold)); }

/* The ability's description on its own line under its name, no dash. */
.ability-line strong { display:block; }
.ability-line .ability-text { display:block; }

/* Improvement and security levels on a portfolio card, spelled out. */
.pf-levels { display:flex; flex-wrap:wrap; gap:4px 14px; font-size:12.5px; margin:4px 0; }
.pf-levels b { font-weight:600; }

/* THE PRIZE, READ AT A GLANCE (26 Sep 2026). A plaque in the winning
   slice's colour, and the slice itself lit on the wheel. Below the
   confetti the rarer outcomes throw: a flip into place, one shine across
   the plaque, and a glow that breathes twice and settles. */
.wheel-prize { position:relative; z-index:1; overflow:hidden; display:grid; gap:4px; justify-items:center;
  margin:18px auto 0; max-width:440px; padding:14px 22px 16px;
  background:var(--prize);
  background:linear-gradient(180deg, color-mix(in srgb, var(--prize) 88%, #fff 12%), var(--prize));
  border:2px solid #E8CF6D; border-radius:6px; color:#FFF8E6;
  box-shadow:0 0 0 1px rgba(0,0,0,.35), 0 10px 26px rgba(0,0,0,.35), 0 0 0 0 color-mix(in srgb, #E8CF6D 60%, transparent);
  transform-origin:50% 0%; animation:prizeIn .55s cubic-bezier(.2,.9,.3,1.25) both, prizeGlow 1.6s ease-out .55s 2; }
.wheel-prize::after { content:""; position:absolute; inset:-20% auto -20% -40%; width:35%;
  background:linear-gradient(100deg, transparent, rgba(255,246,200,.55), transparent);
  transform:skewX(-18deg); animation:prizeShine .9s ease-out .45s both; pointer-events:none; }
.wheel-prize-kicker { font:600 10.5px 'IBM Plex Mono', monospace; letter-spacing:.16em; text-transform:uppercase; color:#F3DE93; }
.wheel-prize-name { font:700 30px/1.1 'Fraunces', Georgia, serif; letter-spacing:.01em; text-shadow:0 2px 0 rgba(0,0,0,.35); }
.wheel-prize-msg { font-size:13.5px; line-height:1.45; color:#F2EAD4; max-width:36ch; }
.wheel-prize.is-jackpot { border-color:#FFE7A0; }
@keyframes prizeIn { from { opacity:0; transform:perspective(600px) rotateX(-70deg) scale(.85); }
  to { opacity:1; transform:none; } }
@keyframes prizeShine { from { left:-40%; } to { left:120%; } }
@keyframes prizeGlow { 0% { box-shadow:0 0 0 1px rgba(0,0,0,.35), 0 10px 26px rgba(0,0,0,.35), 0 0 0 0 rgba(232,207,109,.65); }
  100% { box-shadow:0 0 0 1px rgba(0,0,0,.35), 0 10px 26px rgba(0,0,0,.35), 0 0 0 18px rgba(232,207,109,0); } }
.wheel-slice.is-won { stroke:#FFF1B8; stroke-width:5; filter:saturate(1.15) brightness(1.25);
  animation:sliceWon 1s ease-in-out 3; }
@keyframes sliceWon { 50% { filter:saturate(1.3) brightness(1.55); } }
@media (prefers-reduced-motion: reduce) {
  .wheel-prize, .wheel-prize::after, .wheel-slice.is-won { animation:none; }
}

/* THE ALLIANCE STANDINGS (26 Sep 2026): each pair's name large, both
   members linked, the score a figure you read before anything else. */
.ally-list { list-style:none; margin:10px 0 0; padding:0; display:grid; gap:8px; }
.ally-row { display:grid; grid-template-columns:34px minmax(0, 1fr) auto; align-items:center; gap:12px;
  padding:10px 12px; border:1px solid var(--line); border-radius:6px; background:var(--paper); }
.ally-row.is-mine { border-color:var(--forest); box-shadow:inset 4px 0 0 var(--forest); }
.ally-row.is-broken { opacity:.6; }
.ally-rank { width:30px; height:30px; display:grid; place-items:center; border-radius:50%;
  background:var(--ink); color:var(--paper); font:700 14px 'IBM Plex Mono', monospace; }
.ally-row:first-child .ally-rank { background:var(--gold); color:#1B2420; }
.ally-main { display:grid; gap:2px; min-width:0; }
.ally-name { font:700 18px/1.2 'Fraunces', Georgia, serif; display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; }
.ally-you, .ally-gone { font:600 10px 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase; font-style:normal;
  padding:2px 6px; border-radius:2px; background:var(--forest); color:#F3EEE1; }
.ally-gone { background:var(--muted, #6b6455); }
.ally-members { font-size:13px; color:var(--muted, #6b6455); }
.ally-score { display:grid; justify-items:center; line-height:1; min-width:54px; }
.ally-score b { font:700 26px 'IBM Plex Mono', monospace; color:var(--ink); }
.ally-score small { font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--muted, #6b6455); margin-top:3px; }
.ally-board.is-compact { margin-top:14px; }
.ally-chip { font:600 11px 'IBM Plex Mono', monospace; letter-spacing:.06em; padding:2px 7px; border-radius:2px;
  background:var(--gold); color:#1B2420; vertical-align:middle; margin-left:6px; }
.deposit-uplift { font-size:11.5px; color:var(--gain); margin-top:3px; }
.deposit-uplift s { color:var(--muted, #6b6455); margin-right:3px; }

/* The Gazette's declared rivals (27 Sep 2026). */
.gaz-rivals { display:grid; gap:14px 22px; grid-template-columns:repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); margin:6px 0 4px; }
.gaz-rivals h5 { margin:0 0 6px; font:600 11px 'IBM Plex Mono', monospace; letter-spacing:.12em; text-transform:uppercase; color:#4a4232; }
.gaz-rival-list { list-style:none; margin:0; padding:0; display:grid; gap:6px; }
.gaz-rival-list li { display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; padding:6px 0; border-top:1px solid rgba(42,36,24,.25); }
.gaz-rival-list li.is-against { border-top-color:rgba(140,47,47,.4); }
.gaz-rival-meta { font-size:12.5px; color:#5a5140; flex:1 1 10rem; }
.gaz-rival-pick { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:8px; }
.gaz-rival-warn { font-size:12.5px; color:#8C2F2F; }
.sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }

/* The leaderboard's own key (27 Sep 2026). */
.lb-key { display:flex; flex-wrap:wrap; gap:6px 16px; margin:8px 0 14px; font-size:12.5px; color:var(--muted, #5A6560); }
.lb-key span { display:inline-flex; align-items:center; gap:6px; }
.lb-key .lb-key-off { flex-basis:100%; }
.lb-key-sw { width:14px; height:12px; border-radius:2px; display:inline-block; }
.lb-key-sw.is-you { background:rgba(31,75,63,.16); }
.lb-key-sw.is-grant { background:rgba(176,140,30,.14); box-shadow:inset 3px 0 0 var(--gold); }
.lb-key-sw.is-support { background:rgba(35,57,93,.1); box-shadow:inset 3px 0 0 var(--navy); }
.support-glyph { vertical-align:-.12em; }

/* ---- the paper plane on "Send offer" (27 Sep 2026) -------------------
   One second. The plane rides the curve with offset-path; the dotted trail
   behind it is revealed by a mask drawn along the same curve, then fades. */
.plane-flight { position:fixed; z-index:9999; width:0; height:0; pointer-events:none; color:#1F4B3F; }
.plane-trail { position:absolute; left:0; top:0; overflow:visible; animation:planeTrailFade 1000ms linear forwards; }
.plane-trail-reveal { stroke-dasharray:1; stroke-dashoffset:1; animation:planeTrailDraw 1000ms cubic-bezier(.45,.05,.55,.95) forwards; }
.plane-body { position:absolute; left:0; top:0; width:36px; height:26px; margin:-13px 0 0 -18px;
  filter:drop-shadow(0 3px 3px rgba(20,24,20,.25)); will-change:transform, offset-distance, opacity; }
.plane-body svg { display:block; }
.plane-body.on-path { left:18px; top:13px; offset-rotate:auto; offset-anchor:50% 50%;
  animation:planeFly 1000ms cubic-bezier(.45,.05,.55,.95) forwards; }
.plane-body.no-path { animation:planeFlyFallback 1000ms cubic-bezier(.45,.05,.55,.95) forwards; }
@keyframes planeFly {
  0%   { offset-distance:0%;   transform:scale(.55); opacity:0; }
  8%   { offset-distance:1%;   transform:scale(1.05); opacity:1; }
  70%  { opacity:1; }
  100% { offset-distance:100%; transform:scale(.5); opacity:0; }
}
@keyframes planeFlyFallback {
  0%   { transform:translate(0, 0) rotate(8deg) scale(.55); opacity:0; }
  10%  { transform:translate(4px, 6px) rotate(12deg) scale(1.05); opacity:1; }
  45%  { transform:translate(calc(var(--dx) * .45), calc(var(--dy) * .2)) rotate(-24deg) scale(.9); }
  70%  { opacity:1; }
  100% { transform:translate(var(--dx), var(--dy)) rotate(-38deg) scale(.5); opacity:0; }
}
@keyframes planeTrailDraw { to { stroke-dashoffset:0; } }
@keyframes planeTrailFade { 0%, 60% { opacity:.55; } 100% { opacity:0; } }
.btn.send-offer.is-sent, .btn.send-offer.is-sent:disabled { background:#2F7D6B; border-color:#1C5246; color:#F4EFE2; opacity:1; }
@media (prefers-reduced-motion: reduce) { .plane-flight { display:none; } }

/* ---- INTELLIGENCE: THE WIRE ROOM (27 Sep 2026) --------------------------
   A slate masthead with a live lamp, the brief on a strip of teleprinter
   paper, and the wire set in mono time stamps with a small kind tag per
   line. Everything else keeps the exchange's own cards. */
.intel { display:grid; gap:14px; }
.intel .card { margin:0; }
.intel-mast { display:flex; align-items:flex-end; justify-content:space-between; gap:12px; flex-wrap:wrap;
  background:linear-gradient(180deg,#22313A,#1A262D); color:#EDE7D6; padding:16px 18px 14px; border-radius:6px;
  box-shadow:inset 0 -3px 0 rgba(0,0,0,.25); }
.intel-kicker { font:500 11px 'IBM Plex Mono', monospace; letter-spacing:.16em; text-transform:uppercase; color:#9FB3B8; }
.intel-mast h2 { margin:2px 0 0; font:700 26px/1.1 'Fraunces', serif; letter-spacing:-.01em; color:#F3EEDF; }
.intel-feed-chip { display:inline-flex; align-items:center; gap:8px; font:600 12px 'IBM Plex Mono', monospace;
  letter-spacing:.04em; padding:6px 10px; border:1px solid rgba(237,231,214,.35); border-radius:20px; color:#EDE7D6; }
.intel-feed-chip i { width:8px; height:8px; border-radius:50%; background:#D0452C; box-shadow:0 0 0 3px rgba(208,69,44,.25);
  animation:intelLamp 2.4s ease-in-out infinite; }
@keyframes intelLamp { 0%, 100% { opacity:1; } 50% { opacity:.35; } }
@media (prefers-reduced-motion: reduce) { .intel-feed-chip i { animation:none; } }

.intel-brief { position:relative; background:#F6F1E3; border:1px solid #D8CFB6; border-radius:4px; padding:14px 18px 14px 22px;
  background-image:repeating-linear-gradient(180deg, transparent 0 27px, rgba(31,75,63,.07) 27px 28px); }
.intel-brief::before { content:""; position:absolute; left:0; top:0; bottom:0; width:6px;
  background:repeating-linear-gradient(180deg,#D8CFB6 0 4px, transparent 4px 12px); }
.intel-brief-tag { font:500 11px 'IBM Plex Mono', monospace; letter-spacing:.12em; text-transform:uppercase; color:#8C2F2F; margin-bottom:6px; }
.intel-brief-head { margin:0 0 6px; font:700 19px/1.3 'Fraunces', serif; text-wrap:balance; }
.intel-brief-body { margin:0; font-size:14.5px; line-height:1.6; max-width:62ch; }

.intel-gauges { display:grid; grid-template-columns:repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); gap:10px 18px; margin-top:8px; }
.intel-gauge { display:grid; grid-template-columns:1fr auto; gap:4px 10px; align-items:center; }
.intel-gauge-top { grid-column:1 / -1; display:flex; justify-content:space-between; font-size:13px; }
.intel-gauge-top b { font:600 11px 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase; color:#5A6560; }
.intel-gauge.is-pos .intel-gauge-top b { color:var(--gain); }
.intel-gauge.is-neg .intel-gauge-top b { color:var(--loss); }
.intel-gauge-track { position:relative; height:8px; border-radius:4px; background:rgba(27,36,32,.08); overflow:hidden; }
.intel-gauge-mid { position:absolute; left:50%; top:-2px; bottom:-2px; width:1px; background:rgba(27,36,32,.35); }
.intel-gauge-fill { position:absolute; top:0; bottom:0; background:var(--gain); border-radius:4px; }
.intel-gauge.is-neg .intel-gauge-fill { background:var(--loss); }
.intel-gauge:not(.is-pos):not(.is-neg) .intel-gauge-fill { background:#8A948F; }
.intel-gauge-num { font:500 12px 'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums; min-width:3ch; text-align:right; }

.intel-wire-head { display:flex; align-items:baseline; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.intel-wire-head h3 { margin:0; }
.intel-filters { display:flex; flex-wrap:wrap; gap:6px; }
.intel-filter { font:500 12.5px 'IBM Plex Sans', sans-serif; padding:5px 10px; border-radius:16px; border:1px solid var(--line);
  background:transparent; color:inherit; cursor:pointer; display:inline-flex; gap:6px; align-items:center; }
.intel-filter em { font:600 11px 'IBM Plex Mono', monospace; font-style:normal; opacity:.6; }
.intel-filter.on { background:#22313A; border-color:#22313A; color:#F3EEDF; }
.intel-filter:focus-visible { outline:2px solid #22313A; outline-offset:2px; }
.intel-day { margin-top:12px; }
.intel-day-h { position:sticky; top:0; margin:0 0 4px; padding:4px 0; background:inherit; font:600 11.5px 'IBM Plex Mono', monospace;
  letter-spacing:.12em; text-transform:uppercase; color:#5A6560; border-bottom:1px solid var(--line); }
.intel-lines { list-style:none; margin:0; padding:0; }
.intel-line { display:grid; grid-template-columns:4.6rem 5.6rem minmax(0, 1fr); gap:10px; align-items:baseline;
  padding:6px 0; border-bottom:1px dashed rgba(27,36,32,.1); font-size:13.5px; line-height:1.45; }
.intel-line time { font:500 12px 'IBM Plex Mono', monospace; color:#5A6560; font-variant-numeric:tabular-nums; }
.intel-line.is-routine { color:#5A6560; font-size:12.5px; }
.intel-kind { justify-self:start; font:600 10px 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase;
  padding:2px 6px; border-radius:3px; background:rgba(27,36,32,.07); color:#3F4A45; }
.intel-kind.k-deal { background:rgba(31,75,63,.12); color:#1F4B3F; }
.intel-kind.k-auction { background:rgba(35,57,93,.12); color:#23395D; }
.intel-kind.k-tactic { background:rgba(162,62,39,.12); color:#8C2F2F; }
.intel-kind.k-pact { background:rgba(194,67,155,.12); color:#8E2F72; }
.intel-hidden { margin-top:10px; font-size:12.5px; color:#5A6560; }
@media (max-width: 560px) {
  .intel-line { grid-template-columns:3.8rem minmax(0, 1fr); }
  .intel-line .intel-kind { display:none; }
}

.intel-tiers { display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); gap:10px; margin-top:10px; }
.intel-tier { border:1px solid var(--line); border-radius:6px; padding:12px; display:grid; gap:6px; align-content:start; }
.intel-tier.is-current { border-color:#22313A; box-shadow:inset 0 3px 0 #22313A; }
.intel-tier.is-past { opacity:.6; }
.intel-tier-name { font:700 15px 'Fraunces', serif; }
.intel-tier-cost { font:600 12px 'IBM Plex Mono', monospace; color:#5A6560; }
.intel-tier p { margin:0; font-size:13px; line-height:1.5; }
.intel-tier-now { font:600 11px 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:#22313A; }

/* ---- The field as a race: one thin rail (27 Sep 2026) ------------------ */
.race-rail { position:relative; height:88px; margin:2px 14px 8px; }
/* Two rails (28 Sep 2026), so each horse's name tag has room. */
.race-rail-line { position:absolute; left:0; right:0; height:1px; background:var(--line); }
.race-rail-line.lane-0 { bottom:3px; }
.race-rail-line.lane-1 { bottom:45px; }
.race-rail-post { position:absolute; right:0; bottom:3px; width:2px; height:52px;
  background:repeating-linear-gradient(180deg, var(--ink) 0 3px, transparent 3px 5px); opacity:.55; }
.race-rail-post { height:60px; }
.race-mini { position:absolute; bottom:2px; padding:0; border:0; background:none; cursor:pointer; color:#2E3833; line-height:0;
  display:flex; flex-direction:column; align-items:flex-end; gap:1px;
  transition:left 1.6s cubic-bezier(.3,.1,.3,1); }
.race-mini.lane-1 { bottom:44px; }
.race-mini.is-you { color:var(--forest); }
.race-mini:hover { color:var(--ink); }
.race-mini:focus-visible { outline:2px solid var(--gold); outline-offset:1px; border-radius:3px; }
.race-tag { display:block; font:700 10px/1.35 'IBM Plex Mono', monospace; letter-spacing:.02em; white-space:nowrap;
  padding:0 5px; border:1.5px solid; border-radius:3px; margin-right:6px; }
.race-mini.is-you .race-tag { box-shadow:0 0 0 1.5px var(--forest); }
.race-tag-short { display:none; }
@media (max-width: 560px) {
  .race-tag-full { display:none; }
  .race-tag-short { display:inline; }
  .race-tag { font-size:9.5px; padding:0 3px; margin-right:4px; }
}
/* Mud off the hooves: thrown back and up, then falling away. How far is
   --mud, set per horse from its speed; how many flecks is set in the page. */
.mud-fleck { fill:#5C3B1E; opacity:0; animation:mudFly var(--stride, .7s) ease-out infinite; }
.mud-fleck.mf1 { animation-delay:calc(var(--stride, .7s) * -.2); }
.mud-fleck.mf2 { animation-delay:calc(var(--stride, .7s) * -.45); }
.mud-fleck.mf3 { animation-delay:calc(var(--stride, .7s) * -.65); --lift:-9px; }
.mud-fleck.mf4 { animation-delay:calc(var(--stride, .7s) * -.85); --lift:-3px; }
@keyframes mudFly {
  0% { opacity:0; transform:translate(0, 0); }
  12% { opacity:.95; }
  55% { opacity:.85; transform:translate(calc(var(--mud, 10px) * -.6), var(--lift, -6px)); }
  100% { opacity:0; transform:translate(calc(var(--mud, 10px) * -1), 3px); }
}
.pod-silk { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:5px; vertical-align:0; }
.mini-horse { display:block; overflow:visible; }
/* The gallop: the body rises and dips once a stride, the legs swing in the
   rotary order a galloping horse uses, the tail streams. */
.horse .horse-body { animation:gallopBob var(--stride, .7s) ease-in-out infinite; }
.horse .horse-tail { transform-origin:15px 21px; animation:tailFlow var(--stride, .7s) ease-in-out infinite; }
.horse .hl { animation:legSwing var(--stride, .7s) ease-in-out infinite; }
.horse .hl-hn { animation-delay:calc(var(--stride, .7s) * -.1); }
.horse .hl-hf { animation-delay:calc(var(--stride, .7s) * -.22); }
.horse .hl-fn { animation-name:legSwingFront; animation-delay:calc(var(--stride, .7s) * -.55); }
.horse .hl-ff { animation-name:legSwingFront; animation-delay:calc(var(--stride, .7s) * -.68); }
@keyframes gallopBob { 0%, 100% { transform:translateY(0); } 50% { transform:translateY(-2px) rotate(-1deg); } }
@keyframes tailFlow { 0%, 100% { transform:rotate(0deg); } 50% { transform:rotate(-12deg); } }
@keyframes legSwing { 0%, 100% { transform:rotate(34deg); } 50% { transform:rotate(-30deg); } }
@keyframes legSwingFront { 0%, 100% { transform:rotate(-40deg); } 50% { transform:rotate(28deg); } }
.horse.is-still .horse-body, .horse.is-still .horse-tail, .horse.is-still .hl { animation:none; }
.horse.is-still .mud { display:none; }
@media (prefers-reduced-motion: reduce) {
  .race-mini { transition:none; }
  .horse .horse-body, .horse .horse-tail, .horse .hl { animation:none; }
  .horse .mud { display:none; }
}

/* Leaderboard: your own name in bold, no shading (27 Sep 2026). */
.lb tr.is-me .trader-link, .lb tr.is-me .trader-name, .lb tr.is-me td:nth-child(2) > button { font-weight:700; }
/* The map's field report: who leads the district. */
.field-leader { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 10px; margin:6px 0 10px; font-size:13.5px; }
.field-leader-l { font:600 10.5px 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:#C2439B; }

/* ---- The profile page a Keystone unlocks (27 Sep 2026) -----------------
   A metal border with a slow sheen: one gradient on the border box, its
   position moved every few seconds. No layers, no blur, nothing a phone
   has to composite. None of the metals are rarity colours. */
.pf-head { display:grid; grid-template-columns:auto minmax(0, 1fr); gap:4px 14px; align-items:center; margin-bottom:12px; }
.pf-head:not(.is-dressed) { grid-template-columns:minmax(0, 1fr); }
.pf-head-text { min-width:0; }
.pf-name { display:flex; align-items:center; gap:8px; flex-wrap:wrap; font-family:'Fraunces', serif; font-size:20px; margin:0 0 2px; }
.pf-avatar { display:block; border-radius:50%; box-shadow:0 2px 6px rgba(20,24,20,.25); }
.pf-flag { display:inline-block; border-radius:2px; box-shadow:0 0 0 1px rgba(0,0,0,.18); vertical-align:middle; }
.pf-bio { grid-column:1 / -1; margin:8px 0 0; padding:8px 12px; border-left:3px solid var(--line); font:italic 400 14.5px/1.5 'Fraunces', Georgia, serif; color:#3B4540; overflow-wrap:anywhere; }
.pf-border { --m1:#8E969C; --m2:#E9EDF0; border:4px solid transparent !important;
  background:linear-gradient(var(--paper), var(--paper)) padding-box,
    linear-gradient(110deg, var(--m1) 0%, var(--m2) 38%, #FFFFFF 50%, var(--m2) 62%, var(--m1) 100%) border-box;
  background-size:100% 100%, 300% 100%; animation:pfSheen 7s ease-in-out infinite; }
.pf-border-silver { --m1:#7F878D; --m2:#DDE2E6; }
.pf-border-rose { --m1:#B0607A; --m2:#F2C9D4; }
.pf-border-copper { --m1:#8A4B2A; --m2:#E3A57E; }
.pf-border-jet { --m1:#141414; --m2:#4A4A4A; }
.pf-border-emerald { --m1:#0E5A3E; --m2:#6FC7A0; }
@keyframes pfSheen { 0%, 60% { background-position:0 0, 100% 0; } 100% { background-position:0 0, 0% 0; } }
@media (prefers-reduced-motion: reduce) { .pf-border { animation:none; background-position:0 0, 50% 0; } }
/* The frame round a trader's buildings. Outside the tiles, so each tile's
   rarity ring is untouched. Slate or marble, the trader's choice (27 Sep 2026). */
.pf-trim { padding:10px; border-radius:4px; }
/* Pale stone with soft grey veins. */
.pf-trim-marble { background:
    linear-gradient(115deg, transparent 0 22%, rgba(120,128,132,.28) 23%, transparent 25% 58%, rgba(120,128,132,.22) 59%, transparent 61%),
    linear-gradient(35deg, transparent 0 40%, rgba(150,156,160,.2) 41%, transparent 43%),
    linear-gradient(180deg, #F1F2EF, #E2E4E0);
  box-shadow:inset 0 0 0 1px #A9B0B3, inset 0 0 0 4px rgba(255,255,255,.55); }
/* Welsh slate, cool and plain. */
.pf-trim-slate { background:linear-gradient(160deg, #4B5760, #353F46); box-shadow:inset 0 0 0 1px #20272C, inset 0 0 0 3px #6B7780; }

/* The editor in Personalise. */
.pf-editor-grid { display:grid; gap:16px; grid-template-columns:repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); align-items:start; margin-top:10px; }
.pf-preview { position:relative; max-width:none; max-height:none; overflow:visible; }
.pf-preview .modal-inner { padding:14px 16px 16px; }
.pf-sample { position:absolute; top:8px; right:10px; font:600 10px 'IBM Plex Mono', monospace; letter-spacing:.12em; text-transform:uppercase;
  background:#1B2420; color:#F3EEE1; padding:2px 6px; border-radius:3px; }
.pf-preview-trim { display:grid; grid-template-columns:repeat(3, 1fr); gap:7px; }
.pf-preview-tile { aspect-ratio:1; background:linear-gradient(160deg, #C9D6DC, #E7E1D2 60%, #B8A98C); border:1px solid var(--line); }
.pf-controls { display:grid; gap:12px; }
.pf-field { display:grid; gap:6px; }
.pf-field select, .pf-field textarea { font:inherit; font-size:14px; padding:7px 9px; border:1px solid var(--line); background:var(--paper); color:inherit; border-radius:4px; }
.pf-count { font-size:12px; color:#5A6560; }
.pf-swatches { display:flex; flex-wrap:wrap; gap:6px; }
.pf-pick { padding:2px; border:2px solid transparent; border-radius:50%; background:none; cursor:pointer; line-height:0; }
.pf-pick.on { border-color:var(--ink); }
.pf-tint { width:26px; height:26px; border-radius:50%; border:2px solid transparent; cursor:pointer; box-shadow:inset 0 0 0 2px var(--paper); }
.pf-tint.on { border-color:var(--ink); }
.pf-chip { display:inline-flex; align-items:center; gap:6px; font:500 12.5px 'IBM Plex Sans', sans-serif; padding:5px 10px; border-radius:16px;
  border:1px solid var(--line); background:transparent; color:inherit; cursor:pointer; }
.pf-chip.on { border-color:var(--ink); background:rgba(27,36,32,.06); font-weight:600; }
.pf-chip-sw { width:12px; height:12px; border-radius:50%; display:inline-block; box-shadow:inset 0 0 0 1px rgba(0,0,0,.2); }
.pf-sw-none, .pf-tsw-none { background:transparent; box-shadow:inset 0 0 0 1px var(--line); }
.pf-sw-silver { background:linear-gradient(135deg,#7F878D,#E9EDF0); } .pf-sw-rose { background:linear-gradient(135deg,#B0607A,#F2C9D4); }
.pf-sw-copper { background:linear-gradient(135deg,#8A4B2A,#E3A57E); } .pf-sw-jet { background:linear-gradient(135deg,#141414,#4A4A4A); }
.pf-sw-emerald { background:linear-gradient(135deg,#0E5A3E,#6FC7A0); }
.pf-tsw-slate { background:#3F4A52; } .pf-tsw-marble { background:linear-gradient(135deg,#F1F2EF,#C9CED0); }
.pf-actions { display:flex; flex-wrap:wrap; gap:8px; }
.pf-sell { margin:0; padding-left:18px; display:grid; gap:6px; font-size:13.5px; line-height:1.45; }
.pf-pick:focus-visible, .pf-tint:focus-visible, .pf-chip:focus-visible { outline:2px solid var(--forest); outline-offset:2px; }

/* play.civexio.com's way in, simplified (28 Sep 2026). */
.land-simple .land-top { display:flex; align-items:baseline; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.land-more { font-size:14px; color:var(--forest); text-decoration:underline; text-underline-offset:3px; }
.land-steps { list-style:none; margin:0 0 16px; padding:0; display:grid; gap:10px; font-size:15px; line-height:1.5; }
.land-steps li { padding-left:14px; border-left:3px solid var(--line); }
.land-steps b { color:var(--forest); }
.land-bottom a { color:inherit; }
.pf-friend { font-size:13px; color:#5A6560; margin:0 0 10px; }
.pf-friend.is-on { color:var(--forest); font-weight:600; }

/* The tactics page's How it works (28 Sep 2026). */
.tactics-how { margin:10px 0 14px; border:1px solid var(--line); border-radius:6px; background:var(--paper); }
.tactics-how summary { cursor:pointer; padding:10px 14px; font:600 13px 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase; list-style:none; display:flex; align-items:center; gap:8px; }
.tactics-how summary::-webkit-details-marker { display:none; }
.tactics-how summary::before { content:"+"; display:inline-block; width:14px; font-weight:700; }
.tactics-how[open] summary::before { content:"\2212"; }
.tactics-how summary:focus-visible { outline:2px solid var(--forest); outline-offset:2px; }
.tactics-how-body { display:grid; gap:12px 28px; grid-template-columns:repeat(auto-fit, minmax(min(100%, 24rem), 1fr)); padding:0 14px 14px; }
.tactics-how-body h4 { margin:0 0 4px; font:700 15px 'Fraunces', serif; }
.tactics-how-body p { margin:0 0 6px; font-size:13.5px; line-height:1.55; }
.tactics-how-lib { margin:0; padding:10px 14px 14px; border-top:1px solid var(--line); font-size:13.5px; display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; }

/* A build under way that is yours opens the Build screen (28 Sep 2026). */
.bld-under-link { display: block; width: 100%; padding: 0; border: 0; background: none; color: inherit;
  font: inherit; text-align: left; cursor: pointer; border-radius: 6px; }
.bld-under-link:hover .bld-under-row, .bld-under-link:focus-visible .bld-under-row { box-shadow: 0 0 0 2px var(--gold); }
.bld-under-link:focus-visible { outline: none; }
.bld-under-go { font-size: 12px; font-weight: 600; color: var(--gold); margin-top: 2px; }

/* How growth is measured, under the leaderboard (28 Sep 2026). */
.lb-growth-note { margin:8px 0 0; font-size:12.5px; line-height:1.5; color:var(--muted, #6b6455); max-width:72ch; }

/* Keystones, from the top bar (28 Sep 2026). */
.ks-box { max-width:460px; }
.ks-box p { margin:0 0 10px; font-size:14px; line-height:1.55; }
.ks-lead { padding:10px 12px; border-left:3px solid var(--forest); background:rgba(31,75,63,.07); }
.ks-acts { display:flex; gap:10px; flex-wrap:wrap; margin-top:14px; }

/* Fast Grower counts up on a profile (28 Sep 2026). */

/* District leaders on the leaderboard, in the map's leader colour (29 Sep 2026). */
.lb .trader-link.is-leader, .lb .trader-link.is-leader:hover { color:#C2439B; }
.lb-key-sw.is-leader { background:#C2439B; }
.lb .trader-link.is-magnate, .lb .trader-link.is-magnate:hover, .lb .magnate-tag { color:#2A2896; }
.lb .magnate-tag { font-weight:600; }
.lb-key-sw.is-magnate { background:#2A2896; }
/* On the dark papers the indigo is lifted until it reads. */
.ukpx-root.theme-night-desk .lb .trader-link.is-magnate, .ukpx-root.theme-night-desk .lb .magnate-tag,
.ukpx-root.theme-blueprint .lb .trader-link.is-magnate, .ukpx-root.theme-blueprint .lb .magnate-tag,
.ukpx-root.theme-terminal .lb .trader-link.is-magnate, .ukpx-root.theme-terminal .lb .magnate-tag { color:#A9A6FF; }

/* The Keystone count on the top bar, in silver beside skill's gold (29 Sep 2026). */
.playerbar .stat-value.is-silver { color:var(--silver); }

/* The result of a trader's last Tontine table, under the panel (29 Sep 2026). */
.tont-last { margin:10px 0 0; font-size:13px; }
.tont-act .tont-figures { flex-basis:100%; }

/* Choosing a building's look, for a Keystone (29 Sep 2026); every option
   can be opened full size (30 Sep 2026). */
.look-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(96px, 1fr)); gap:8px; margin-bottom:10px; }
.look-thumb { position:relative; border:2px solid var(--line); border-radius:4px; background:var(--paper-dark); overflow:hidden; }
.look-thumb.picked { border-color:var(--gold); box-shadow:0 0 0 2px rgba(176,140,30,.35); }
.look-thumb-pick { display:block; width:100%; padding:0; border:0; background:none; cursor:pointer; }
.look-thumb-pick img { display:block; width:100%; aspect-ratio:3/2; object-fit:cover; }
.look-thumb-pick:focus-visible { outline:2px solid var(--forest); outline-offset:-2px; }
.look-thumb-tag { position:absolute; left:4px; bottom:4px; padding:1px 6px; border-radius:3px; background:rgba(14,28,21,.85);
  color:#F2EFE0; font:600 10px 'IBM Plex Mono', monospace; letter-spacing:.06em; pointer-events:none; }
.look-thumb-zoom { position:absolute; right:4px; top:4px; width:26px; height:26px; display:grid; place-items:center; padding:0;
  border:0; border-radius:3px; background:rgba(14,28,21,.78); color:#F2EFE0; cursor:zoom-in; }
.look-thumb-zoom:hover { background:rgba(14,28,21,.95); }
.look-thumb-zoom:focus-visible { outline:2px solid #F2EFE0; outline-offset:1px; }

/* Full size, over everything. Portalled to the body, outside the theme, so
   its colours are its own. */
.look-zoom { position:fixed; inset:0; z-index:2000; display:grid; place-items:center; padding:16px;
  background:rgba(10,16,13,.86); cursor:zoom-out; }
.look-zoom-frame { cursor:default; width:min(960px, 100%); display:flex; flex-direction:column; gap:10px; }
.look-zoom-frame img { display:block; width:100%; max-height:calc(100vh - 110px); object-fit:contain; border-radius:4px;
  background:#1B2420; }
.look-zoom-bar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; color:#F2EFE0;
  font:500 13px 'IBM Plex Sans', system-ui, sans-serif; }
.look-zoom-count { font-family:'IBM Plex Mono', monospace; letter-spacing:.04em; }
.look-zoom-bar button { font:600 13px 'IBM Plex Sans', system-ui, sans-serif; border-radius:3px; cursor:pointer; padding:7px 14px; }
.look-zoom-nav { background:transparent; color:#F2EFE0; border:1px solid rgba(242,239,224,.5); font-size:18px !important;
  line-height:1; padding:4px 12px !important; }
.look-zoom-pick { background:#C9A227; color:#14201A; border:1px solid #C9A227; }
.look-zoom-close { background:transparent; color:#F2EFE0; border:1px solid rgba(242,239,224,.5); }
.look-zoom-bar button:focus-visible { outline:2px solid #F2EFE0; outline-offset:2px; }

/* RECALL, IN ITS OWN COLOUR (Aaron, 30 Sep 2026). An outlined button on the
   baize read as one more label; amber is the one warm colour on the table,
   so taking an order back is found at a glance. */
.awaiting-orders .btn.recall-btn { background:#E3A93B; border:1px solid #E3A93B; color:#1B2420; font-weight:600; }
.awaiting-orders .btn.recall-btn:hover:not(:disabled), .awaiting-orders .btn.recall-btn:focus-visible { background:#F0BE5C; border-color:#F0BE5C; }
.awaiting-orders .btn.recall-btn:disabled { opacity:.55; }

/* CITY TASKS (1 Oct 2026). The Council's paid work: fixed fees on the
   paper's own cards, a trade task marked by its navy edge, the one in hand
   by the forest edge. The fee is the headline of each card. */
.city-tasks { display:grid; gap:18px; }
.task-lede { margin:0; max-width:70ch; font-size:14.5px; line-height:1.55; color:#4b463a; }
.task-note { margin:0; padding:9px 12px; border-left:3px solid #4C5A30; background:rgba(76,90,48,.08); font-size:13.5px; }
.task-h { font-family:'Fraunces', serif; font-size:19px; margin:0 0 12px; }
.task-grid { display:grid; gap:14px; grid-template-columns:repeat(auto-fill, minmax(min(100%, 290px), 1fr)); }
/* A task is a notice from the Council: white paper, a band of colour for
   the sort of work it is, its picture in a disc, and the fee as the
   headline. */
.task-card { --tg:#2F4C8A; --tg-soft:rgba(47,76,138,.10);
  display:flex; flex-direction:column; gap:10px; background:#FCFAF4; border:1px solid #CBC1A9;
  box-shadow:inset 0 4px 0 var(--tg), 0 2px 0 rgba(203,193,169,.5); padding:18px 18px 16px; transition:box-shadow .14s ease; }
.task-card:hover { box-shadow:inset 0 4px 0 var(--tg), 0 8px 22px rgba(60,44,30,.13); }
.task-card.tg-trade  { --tg:#2F4C8A; --tg-soft:rgba(47,76,138,.10); }
.task-card.tg-market { --tg:#8A5524; --tg-soft:rgba(138,85,36,.11); }
.task-card.tg-build  { --tg:#2F6B45; --tg-soft:rgba(47,107,69,.11); }
.task-card.tg-guard  { --tg:#5C6A26; --tg-soft:rgba(92,106,38,.12); }
.task-card.tg-bank   { --tg:#1D6470; --tg-soft:rgba(29,100,112,.11); }
.task-card.is-mine { background:#FFFDF7; outline:2px solid var(--tg); outline-offset:-2px; }
.task-head { display:grid; grid-template-columns:auto 1fr auto; align-items:center; gap:12px; }
.task-badge { width:40px; height:40px; border-radius:50%; display:grid; place-items:center; background:var(--tg-soft); color:var(--tg); }
.task-titles { min-width:0; }
.task-head h4 { margin:2px 0 0; font-family:'Fraunces', serif; font-weight:700; font-size:17px; line-height:1.2; color:#2A231B; }
.task-kind { font:600 10px 'IBM Plex Mono', monospace; letter-spacing:.14em; text-transform:uppercase; color:var(--tg); }
.task-fee { display:grid; justify-items:end; font:700 20px 'Fraunces', serif; font-variant-numeric:tabular-nums; color:var(--gain); white-space:nowrap; line-height:1.05; }
.task-fee small { font:500 9px 'IBM Plex Mono', monospace; letter-spacing:.16em; text-transform:uppercase; color:#8A8170; }
.task-brief { margin:0; font-size:14px; line-height:1.5; color:#3A352B; }
.task-link { align-self:flex-start; background:none; border:0; padding:0; color:var(--tg); text-decoration:underline; text-underline-offset:3px;
  font:500 13.5px 'IBM Plex Sans', sans-serif; cursor:pointer; }
.task-mine p { margin:0 0 8px; font-size:14px; }
.task-acts { display:flex; flex-wrap:wrap; gap:8px; margin-top:auto; padding-top:4px; }
.task-card .task-acts .btn:not(.secondary) { background:var(--tg); border-color:var(--tg); }
.task-history { list-style:none; margin:0; padding:0; display:grid; gap:0; background:#FCFAF4; border:1px solid #CBC1A9; }
.task-history li { display:flex; justify-content:space-between; gap:12px; padding:9px 14px; border-top:1px solid #E4DCC8; font-size:14px; }
.task-history li:first-child { border-top:0; }
.task-history b { font-variant-numeric:tabular-nums; color:var(--gain); }

/* ---- THE CITY GROWS (1 Oct 2026) ---------------------------------------
   How full York is, as a bar with the Council's milestones ticked on it,
   and a new district drawn on its own dashed boundary. */
.city-gauge { display: grid; gap: 6px; padding: 10px 12px; margin-bottom: 10px; }
.city-gauge-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.city-gauge-l { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; opacity: .7; }
.city-gauge-v { font-family: 'Fraunces', serif; font-size: 22px; font-variant-numeric: tabular-nums; }
.city-gauge-bar { position: relative; height: 8px; border-radius: 4px; background: rgba(128,128,128,.22); margin: 2px 0 4px; }
.city-gauge-bar > i { display: block; height: 100%; border-radius: 4px; background: currentColor; opacity: .78; }
.city-gauge-tick { position: absolute; top: -3px; width: 2px; height: 14px; margin-left: -1px; background: currentColor; opacity: .5; }
.city-gauge-tick.is-reached { background: var(--gold); opacity: 1; }
.city-gauge-note { margin: 0; font-size: 12.5px; line-height: 1.45; }
.zone-note { margin: 6px 0 8px; font-size: 12.5px; line-height: 1.45; border-left: 3px solid var(--gold); padding-left: 8px; }
.terr.is-zone { stroke-width: 2; }

/* ---- THE PLANNING BALLOT -------------------------------------------------- */
.ballot-card { display: grid; gap: 8px; }
.ballot-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ballot-head h3 { margin: 0; }
.ballot-next { font-size: 12.5px; opacity: .8; }
.ballot-days { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.ballot-days i { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--line); }
.ballot-days i.on { background: var(--forest); border-color: var(--forest); }
.ballot-days span { font-size: 12.5px; margin-left: 6px; font-variant-numeric: tabular-nums; }
.ballot-status { margin: 0; font-size: 14px; font-weight: 600; }
.ballot-owing, .ballot-last { margin: 0; font-size: 12.5px; opacity: .85; }
.bld-plot.is-granted { border-color: #6E1423; box-shadow: inset 0 0 0 1px #6E1423; }
.bld-grant { display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: center; font-size: 13px; line-height: 1.45; }
.bld-grant-seal { font-family: 'Fraunces', serif; font-weight: 700; font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: #6E1423; background: #F4E7C5; border: 2px solid #6E1423; border-radius: 999px; padding: 4px 9px; }

/* PLANNING PERMISSION GRANTED. The veil fades, the notice rises, the
   address is set in, and the seal comes down last with a small bounce.
   1.6 seconds in all; nothing moves for a reader who asked for stillness. */
.grant-veil { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 16px;
  background: rgba(16, 22, 30, .62); animation: grant-veil .3s ease-out both; }
.grant-notice { position: relative; width: min(440px, 100%); max-height: calc(100vh - 32px); overflow: auto; box-sizing: border-box;
  background: #FBF6E9; color: #1D2430; border: 1px solid #CDBF9C; border-radius: 6px; padding: 22px 22px 18px;
  box-shadow: 0 18px 50px rgba(0,0,0,.35); display: grid; gap: 10px;
  animation: grant-rise .5s cubic-bezier(.2,.8,.25,1) .2s both; }
.grant-crest { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: #6E1423; }
.grant-title { margin: 0; font-family: 'Fraunces', serif; font-size: 26px; line-height: 1.15; text-wrap: balance; padding-right: 104px; }
.grant-plot { border: 1px solid #DDD2B6; border-radius: 4px; overflow: hidden; animation: grant-ink .45s ease-out .65s both; }
.grant-address { margin: 0; display: grid; gap: 2px; animation: grant-ink .45s ease-out .8s both; }
.grant-address b { font-family: 'Fraunces', serif; font-size: 19px; }
.grant-address span { font-size: 13px; opacity: .75; }
.grant-terms { margin: 0; font-size: 13.5px; line-height: 1.5; animation: grant-ink .45s ease-out .95s both; }
.grant-seal { position: absolute; top: 16px; right: 22px; width: 92px; height: 92px; transform-origin: 50% 50%;
  animation: grant-stamp .5s cubic-bezier(.3,1.4,.5,1) 1.15s both; }
.grant-seal svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 2px 2px rgba(110,20,35,.25)); }
.grant-acts { display: flex; gap: 8px; flex-wrap: wrap; animation: grant-ink .4s ease-out 1.3s both; }
@keyframes grant-veil { from { opacity: 0; } to { opacity: 1; } }
@keyframes grant-rise { from { opacity: 0; transform: translateY(28px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes grant-ink { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes grant-stamp {
  0% { opacity: 0; transform: scale(1.45) rotate(-24deg); }
  60% { opacity: 1; transform: scale(.92) rotate(-11deg); }
  100% { opacity: 1; transform: scale(1) rotate(-12deg); }
}
@media (max-width: 480px) {
  .grant-title { font-size: 22px; padding-right: 84px; }
  .grant-seal { width: 72px; height: 72px; top: 12px; right: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .grant-veil, .grant-notice, .grant-plot, .grant-address, .grant-terms, .grant-acts { animation: none; }
  .grant-seal { animation: none; transform: rotate(-12deg); }
}

/* ---- BANK / STOCKS (1 Oct 2026) -------------------------------------------
   A ledger, not a trading terminal: one row a building, price and the day's
   move to the right where the eye looks for it, the prospectus opening
   under its row. Gain and loss are the game's own green and red. */
.bank-switch { display: flex; gap: 0; margin: 0 0 14px; }
.stk-live { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #5CC98A; margin-left: 7px; vertical-align: 1px;
  box-shadow: 0 0 0 2px rgba(92,201,138,.25); }
.stk { display: grid; gap: 12px; }
.stk-h { margin: 6px 0 0; font-family: 'Fraunces', serif; font-size: 18px; }
.stk-note { margin: 0; font-size: 12.5px; line-height: 1.5; opacity: .82; max-width: 70ch; }
.stk-list { display: grid; border-top: 1px solid var(--line); }
.stk-row { border-bottom: 1px solid var(--line); }
.stk-row.is-open { background: var(--paper-dark); }
.stk-line { width: 100%; font: inherit; color: inherit; background: none; border: 0; cursor: pointer; text-align: left;
  display: grid; grid-template-columns: minmax(0, 1fr) 92px 120px 72px; gap: 12px; align-items: center; padding: 10px 6px; }
.stk-line:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.stk-name { display: grid; gap: 2px; min-width: 0; }
.stk-name b { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stk-name span { font-size: 12px; opacity: .72; }
.stk-price { text-align: right; font-family: 'IBM Plex Mono', monospace; font-variant-numeric: tabular-nums; font-size: 15px; display: grid; }
.stk-price em { font-style: normal; font-size: 12px; }
.stk-yield { text-align: right; font-family: 'IBM Plex Mono', monospace; font-size: 13px; display: grid; }
.stk-yield span { font-family: inherit; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; opacity: .65; }
.stk-halt { grid-column: 1 / -1; font-size: 12px; color: var(--loss); font-weight: 600; }
.stk-row.is-halted .stk-price { opacity: .55; }
.stk-pro { display: grid; gap: 12px; padding: 4px 6px 14px; }
.stk-pro-chart { display: grid; gap: 6px; max-width: 420px; }
.stk-band { position: relative; display: flex; justify-content: space-between; font-size: 11px; opacity: .8; padding-top: 10px;
  border-top: 2px solid var(--line); font-variant-numeric: tabular-nums; }
.stk-band i { position: absolute; top: -6px; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%; background: var(--navy); }
.stk-facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px 16px; margin: 0; }
.stk-facts div { display: grid; gap: 1px; }
.stk-facts dt { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; opacity: .65; }
.stk-facts dd { margin: 0; font-size: 13.5px; font-variant-numeric: tabular-nums; }
.stk-orders { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.stk-orders li { display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 13.5px; border-bottom: 1px solid var(--line); padding: 4px 0; }
.stk-float { display: grid; gap: 10px; }
.stk-float h3 { margin: 0; }
.stk-float-row { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; }
.stk-float-row select { font: inherit; padding: 5px 8px; max-width: 100%; }
.stk-float-row input[type=range] { flex: 1 1 140px; }
.stk-float-k { font-family: 'IBM Plex Mono', monospace; min-width: 2ch; }
.stk-float-sum { margin: 0; font-size: 13.5px; }
.stk-float-row label { min-width: 7.5em; font-size: 12.5px; }
.stk-float-row input[type=number] { font: inherit; padding: 5px 8px; width: 9em; max-width: 100%; font-variant-numeric: tabular-nums; }
/* Hold, float, sell: three rows read across, the float lifted. */
.stk-compare { display: grid; gap: 6px; }
.stk-cmp { display: grid; grid-template-columns: 5.5em 1fr; gap: 10px; align-items: baseline; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 3px; font-size: 13px; line-height: 1.45; }
.stk-cmp b { font-family: 'Fraunces', serif; font-size: 14px; }
.stk-cmp.is-pick { border-color: var(--navy); background: rgba(31,53,83,.05); }
.stk-cmp strong { font-variant-numeric: tabular-nums; }
@media (max-width: 420px) { .stk-cmp { grid-template-columns: 1fr; gap: 2px; } }
.stk-offer { font-size: 11px; font-weight: 600; color: var(--navy); font-style: italic; opacity: 1 !important; }
.stk-yours { display: grid; gap: 12px; }
.stk-yours h3 { margin: 0; }
.stk-your { display: grid; gap: 6px; padding-top: 10px; border-top: 1px dashed var(--line); }
.stk-your:first-of-type { border-top: 0; padding-top: 0; }
.stk-your-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 12px; align-items: baseline; }
.stk-your-head span { font-variant-numeric: tabular-nums; font-size: 13px; }
.stk-your-head em { font-style: normal; opacity: .7; }
.stk-your > .btn { justify-self: start; }
.stk-your-act { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 13px; }
.rates-card { display: grid; gap: 8px; border-left: 4px solid #6E1423; }
.rates-head { display: flex; justify-content: space-between; align-items: baseline; }
.rates-head h3 { margin: 0; }
.rates-head b { font-family: 'Fraunces', serif; font-size: 24px; }
.rates-ways { margin: 0; padding-left: 18px; display: grid; gap: 4px; font-size: 13px; line-height: 1.45; }
.rates-tally { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.rates-tally div { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; background: rgba(110,20,35,.05); border-radius: 3px; min-width: 0; }
.rates-tally span { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted, #6b6455); }
.rates-tally b { font-family: 'Fraunces', serif; font-size: 18px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.rates-where { margin: 0; }
.rates-honour { display: grid; gap: 6px; padding: 8px 0 2px; border-top: 1px dashed var(--line); }
.rates-honour-line { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.rates-honour-line .medal-svg { flex: none; }
.rates-honour-line svg.medal-svg { opacity: 1; }
.rates-bar { height: 6px; border-radius: 3px; background: rgba(110,20,35,.12); overflow: hidden; }
.rates-bar i { display: block; height: 100%; background: linear-gradient(90deg, #9C7A14, #D9B24A); border-radius: 3px; }


/* ---- THE TRADING FLOOR (1 Oct 2026, second pass) ---------------------------
   Aaron: "more exciting and dynamic". The board is a dark exchange display,
   one world of its own whatever the theme: a lamp that glows while the
   market is open, the bell counted in seconds, the day's move for the whole
   market, the session filling its bar. Under it the tape. Prices count to
   their new value and flash once when a trade lands; nothing moves while a
   price is still, and nothing at all under reduced motion. */
.mkt-board { --mb-bg:#0F1A16; --mb-ink:#E8E3D4; --mb-dim:#9DA89F; --mb-up:#5CC98A; --mb-down:#F07A6A; --mb-gold:#D9B45A;
  background: var(--mb-bg); color: var(--mb-ink); border-radius: 6px; padding: 14px 16px 12px;
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 10px 18px; align-items: center; }
.mkt-state { display: flex; gap: 12px; align-items: center; }
.mkt-state b { display: block; font-family: 'Fraunces', serif; font-size: 22px; letter-spacing: .01em; }
.mkt-state span, .mkt-clock span, .mkt-index span { display: block; font: 500 10.5px 'IBM Plex Mono', monospace; letter-spacing: .1em; text-transform: uppercase; color: var(--mb-dim); }
.mkt-lamp { width: 14px; height: 14px; border-radius: 50%; background: #5A625C; flex: none; box-shadow: inset 0 0 0 2px rgba(0,0,0,.25); }
.mkt-board.is-open .mkt-lamp { background: var(--mb-up); box-shadow: 0 0 0 0 rgba(92,201,138,.55); animation: mkt-lamp 2s ease-out infinite; }
@keyframes mkt-lamp { 0% { box-shadow: 0 0 0 0 rgba(92,201,138,.55); } 70% { box-shadow: 0 0 0 10px rgba(92,201,138,0); } 100% { box-shadow: 0 0 0 0 rgba(92,201,138,0); } }
.mkt-clock b { display: block; font: 600 30px 'IBM Plex Mono', monospace; font-variant-numeric: tabular-nums; color: var(--mb-gold); letter-spacing: .02em; }
.mkt-index b { display: block; font: 600 22px 'IBM Plex Mono', monospace; font-variant-numeric: tabular-nums; }
.mkt-index b.up { color: var(--mb-up); } .mkt-index b.down { color: var(--mb-down); }
.mkt-session { grid-column: 1 / -1; position: relative; height: 6px; border-radius: 3px; background: rgba(232,227,212,.12); margin-top: 6px; }
.mkt-session i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: linear-gradient(90deg, var(--mb-up), var(--mb-gold)); }
.mkt-session span { position: absolute; top: 9px; font: 500 10px 'IBM Plex Mono', monospace; color: var(--mb-dim); }
.mkt-session span:first-of-type { left: 0; } .mkt-session span:last-of-type { right: 0; }
.mkt-note { grid-column: 1 / -1; margin: 14px 0 0; font-size: 12.5px; color: var(--mb-dim); }
@media (max-width: 640px) {
  .mkt-board { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .mkt-state { grid-column: 1 / -1; }
  .mkt-clock b { font-size: 24px; }
}

.stk-tape { overflow: hidden; background: #0F1A16; color: #E8E3D4; border-radius: 4px; white-space: nowrap;
  font: 500 13px 'IBM Plex Mono', monospace; padding: 7px 0; mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent); }
.stk-tape-track { display: inline-flex; animation: stk-tape linear infinite; }
.stk-tape:hover .stk-tape-track { animation-play-state: paused; }
@keyframes stk-tape { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.tape-item { padding: 0 22px; border-right: 1px solid rgba(232,227,212,.14); }
.tape-item b { font-weight: 600; letter-spacing: .03em; text-transform: uppercase; font-size: 12px; }
.tape-item em { font-style: normal; }
.tape-item em.up { color: #5CC98A; } .tape-item em.down { color: #F07A6A; } .tape-item em.halt { color: #D9B45A; }

.movers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.mover { font: inherit; color: inherit; text-align: left; cursor: pointer; background: var(--paper); border: 1px solid var(--line);
  border-top: 4px solid var(--line); border-radius: 5px; padding: 10px 12px; display: grid; gap: 2px; min-width: 0; }
.mover span { font: 500 10.5px 'IBM Plex Mono', monospace; letter-spacing: .1em; text-transform: uppercase; opacity: .7; }
.mover b { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mover em { font: 600 17px 'IBM Plex Mono', monospace; font-style: normal; }
.mover.up { border-top-color: var(--gain); } .mover.up em { color: var(--gain); }
.mover.down { border-top-color: var(--loss); } .mover.down em { color: var(--loss); }
.mover.pay { border-top-color: var(--gold); } .mover.pay em { color: var(--gold); }
.mover:hover { border-color: var(--ink); }
.mover:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
@media (max-width: 560px) {
  .movers { gap: 6px; }
  .mover { padding: 8px 8px; }
  .mover span { font-size: 9px; letter-spacing: .06em; }
  .mover b { font-size: 12px; }
  .mover em { font-size: 14px; }
}

.stk-line { grid-template-columns: minmax(0, 1fr) 116px 132px 72px; }
.stk-mine { font-size: 11.5px; color: var(--navy); font-weight: 600; opacity: 1 !important; }
.stk-pill { font: 600 12px 'IBM Plex Mono', monospace; font-style: normal; justify-self: end; padding: 1px 7px; border-radius: 999px; color: #fff; }
.stk-pill.up { background: var(--gain); } .stk-pill.down { background: var(--loss); }
.stk-price { gap: 3px; }
.stk-row.is-halted { background: repeating-linear-gradient(135deg, rgba(217,180,90,.14) 0 10px, transparent 10px 20px); }
.stk-halt { color: #8A6A12; }
@media (max-width: 560px) {
  .stk-line { grid-template-columns: minmax(0, 1fr) 112px; }
  .stk-spark, .stk-yield { display: none; }
}

.live-price { display: inline-block; font-variant-numeric: tabular-nums; border-radius: 3px; padding: 0 3px; margin: 0 -3px; }
.live-price.flash-up { animation: flash-up 1.2s ease-out; }
.live-price.flash-down { animation: flash-down 1.2s ease-out; }
@keyframes flash-up { 0% { background: rgba(47,107,69,.45); color: var(--gain); } 100% { background: transparent; } }
@keyframes flash-down { 0% { background: rgba(176,52,42,.42); color: var(--loss); } 100% { background: transparent; } }

.stk-pro-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(260px, 1fr); gap: 18px; align-items: start; }
@media (max-width: 820px) { .stk-pro-grid { grid-template-columns: minmax(0, 1fr); } }
.stk-pro-chart { max-width: none; }
.stk-chart { width: 100%; height: auto; display: block; color: var(--ink); }
.stk-pulse { transform-box: fill-box; transform-origin: center; animation: stk-pulse 1.8s ease-out infinite; opacity: .35; }
@keyframes stk-pulse { 0% { transform: scale(.45); opacity: .55; } 100% { transform: scale(1.6); opacity: 0; } }
.stk-band { margin-top: 2px; }

.ticket { position: relative; display: grid; gap: 12px; background: var(--paper); border: 1px solid var(--line); border-top: 5px solid var(--gain);
  border-radius: 6px; padding: 14px; overflow: hidden; }
.ticket.is-sell { border-top-color: var(--loss); }
.ticket-side { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--line); border-radius: 5px; overflow: hidden; }
.ticket-side button { font: 600 15px 'IBM Plex Sans', sans-serif; padding: 9px; border: 0; background: transparent; color: inherit; cursor: pointer; }
.ticket-side button.on { color: #fff; }
.ticket.is-buy .ticket-side button.on { background: var(--gain); }
.ticket.is-sell .ticket-side button.on { background: var(--loss); }
.ticket-side button:focus-visible, .ticket-step button:focus-visible, .ticket-chips button:focus-visible, .ticket-go:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.ticket-qty { display: grid; gap: 6px; }
.ticket-qty label { font: 500 10.5px 'IBM Plex Mono', monospace; letter-spacing: .1em; text-transform: uppercase; opacity: .7; }
.ticket-step { display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px; border: 1px solid var(--line); border-radius: 5px; overflow: hidden; }
.ticket-step button { font: 600 20px 'IBM Plex Sans', sans-serif; border: 0; background: var(--paper-dark); color: inherit; cursor: pointer; }
.ticket-step input { font: 600 20px 'IBM Plex Mono', monospace; text-align: center; border: 0; border-left: 1px solid var(--line); border-right: 1px solid var(--line);
  background: transparent; color: inherit; padding: 6px; min-width: 0; -moz-appearance: textfield; }
.ticket-step input::-webkit-outer-spin-button, .ticket-step input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.ticket-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.ticket-chips button { font: 500 12.5px 'IBM Plex Mono', monospace; padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: inherit; cursor: pointer; }
.ticket-chips button:disabled { opacity: .4; cursor: not-allowed; }
.ticket-sum { margin: 0; display: grid; gap: 8px; }
.ticket-sum div { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; border-bottom: 1px dashed var(--line); padding-bottom: 6px; }
.ticket-sum dt { font-size: 12.5px; opacity: .8; }
.ticket-sum dd { margin: 0; text-align: right; font: 600 15px 'IBM Plex Mono', monospace; font-variant-numeric: tabular-nums; }
.ticket-sum dd em { font-style: normal; font-size: 12px; }
.ticket-sum dd.up { color: var(--gain); } .ticket-sum dd.down { color: var(--loss); }
.ticket-sum dd b { display: block; font-size: 19px; }
.ticket-sum dd .sub { display: block; font: 400 11px 'IBM Plex Sans', sans-serif; opacity: .7; }
.ticket-warn { margin: 0; font-size: 12.5px; line-height: 1.45; padding: 8px 10px; border-left: 3px solid #D9B45A; background: rgba(217,180,90,.16); }
.ticket-why { margin: 0; font-size: 12.5px; opacity: .8; }
.ticket-go { font: 700 15.5px 'IBM Plex Sans', sans-serif; padding: 13px 12px; border: 0; border-radius: 5px; color: #fff; cursor: pointer; background: var(--gain); }
.ticket.is-sell .ticket-go { background: var(--loss); }
.ticket-go:disabled { opacity: .45; cursor: not-allowed; }
.ticket-go:not(:disabled):hover { filter: brightness(1.08); }
.ticket-foot { display: flex; justify-content: space-between; align-items: center; font-size: 12.5px; }

/* THE FILL SLIP. Stamped over the ticket when an order goes through, then
   gone after a few seconds. */
.fill-slip { position: absolute; left: 12px; right: 12px; bottom: 12px; display: grid; gap: 3px; padding: 14px 14px 12px;
  background: #FBF6E9; color: #1D2430; border: 1px solid #CDBF9C; border-radius: 5px; box-shadow: 0 10px 26px rgba(0,0,0,.25);
  animation: slip-in .32s cubic-bezier(.2,.8,.25,1) both, slip-out .35s ease-in 3.25s both; }
.fill-slip b { font-family: 'Fraunces', serif; font-size: 17px; }
.fill-slip span { font-size: 12.5px; }
.fill-stamp { justify-self: start; font: 700 12px 'IBM Plex Mono', monospace !important; letter-spacing: .14em; text-transform: uppercase;
  padding: 3px 10px; border: 2px solid currentColor; border-radius: 3px; transform: rotate(-4deg); animation: slip-stamp .45s cubic-bezier(.3,1.5,.5,1) .18s both; }
.fill-slip.is-buy .fill-stamp { color: #2F6B45; } .fill-slip.is-sell .fill-stamp { color: #B0342A; }
@keyframes slip-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes slip-out { to { opacity: 0; transform: translateY(8px); } }
@keyframes slip-stamp { 0% { opacity: 0; transform: scale(1.8) rotate(-12deg); } 100% { opacity: 1; transform: scale(1) rotate(-4deg); } }

.stk-side { font: 600 11px 'IBM Plex Mono', monospace; text-transform: uppercase; letter-spacing: .08em; padding: 2px 7px; border-radius: 3px; color: #fff; }
.stk-side.buy { background: var(--gain); } .stk-side.sell { background: var(--loss); }
.stk-orders li { justify-content: flex-start; }
.stk-orders li .btn { margin-left: auto; }

.stk-port { display: grid; gap: 10px; }
.stk-port-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.stk-port-head h3 { margin: 0; }
.stk-port-head b { font: 600 22px 'IBM Plex Mono', monospace; margin-right: 8px; }
.stk-port-head em, .stk-port-pl em { font-style: normal; font: 600 13px 'IBM Plex Mono', monospace; }
.stk-port-head em.up, .stk-port-pl.up em { color: var(--gain); } .stk-port-head em.down, .stk-port-pl.down em { color: var(--loss); }
.stk-port-rows { display: grid; }
.stk-port-row { font: inherit; color: inherit; background: none; border: 0; border-top: 1px solid var(--line); cursor: pointer; text-align: left;
  display: grid; grid-template-columns: minmax(0, 1fr) 90px 110px; gap: 12px; align-items: center; padding: 8px 2px; }
.stk-port-row > span:first-child { display: grid; min-width: 0; }
.stk-port-row > span:first-child span { font-size: 12px; opacity: .7; }
.stk-port-bar { height: 6px; border-radius: 3px; background: rgba(128,128,128,.18); overflow: hidden; }
.stk-port-bar i { display: block; height: 100%; } .stk-port-bar i.up { background: var(--gain); } .stk-port-bar i.down { background: var(--loss); }
.stk-port-pl { text-align: right; display: grid; font: 600 14px 'IBM Plex Mono', monospace; }
@media (max-width: 480px) { .stk-port-row { grid-template-columns: minmax(0, 1fr) 96px; } .stk-port-bar { display: none; } }

@media (prefers-reduced-motion: reduce) {
  .mkt-board.is-open .mkt-lamp, .stk-pulse, .live-price.flash-up, .live-price.flash-down, .fill-slip, .fill-stamp { animation: none; }
  .stk-tape-track { animation: none; flex-wrap: wrap; white-space: normal; }
  .stk-tape-track .tape-item[aria-hidden="true"] { display: none; }
  .stk-pulse { opacity: 0; }
  .fill-slip { animation: slip-out .01s linear 3.6s both; }
}

/* The street level key: ownership fills as squares, like the buildings. */
.key-mark.sq { transform:none; border-radius:2px; border-color:#10201A; }
.key-mark.key-idle { opacity:.42; }

/* The portfolio card's buttons: a column at the top right, the same width
   whatever is in it. Under it on a phone, where there is no right. */
.pf-acts { flex:0 0 190px; display:flex; flex-direction:column; align-items:stretch; gap:8px; }
.pf-acts > .btn { width:100%; text-align:center; }
.pf-acts .muted-plain { font-size:12px; }
@media (max-width:640px) { .pf-acts { flex:1 1 100%; flex-direction:row; flex-wrap:wrap; } .pf-acts > .btn { width:auto; } }

/* ---- the week on the Exchange, in the Gazette; floats on a profile (1 Oct 2026) ---- */
.gx-cols { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:10px 20px; margin-top:6px; }
.gx-kicker { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.12em; text-transform:uppercase; color:#6E634C; }
.gx-list { list-style:none; margin:4px 0 0; padding:0; display:grid; gap:4px; }
.gx-list li { display:grid; grid-template-columns:1fr auto; gap:0 10px; align-items:baseline; font-size:13px; padding:4px 0; border-bottom:1px dotted #C6B78E; }
.gx-list li b { font-family:'Fraunces', serif; font-weight:600; }
.gx-list .gx-who { grid-column:1; font-size:12px; }
.gx-list em { grid-column:2; grid-row:1 / span 2; font-style:normal; font-weight:700; font-variant-numeric:tabular-nums; }
.gx-list em.up, .pf-floats .up { color:var(--gain); }
.gx-list em.down, .pf-floats .down { color:var(--loss); }
.pf-floats { margin:0 0 14px; }
.pf-floats-h { font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.12em; text-transform:uppercase; color:#6b6455; }
.pf-floats ul { list-style:none; margin:6px 0 0; padding:0; display:grid; gap:4px; }
.pf-floats li { display:flex; flex-wrap:wrap; justify-content:space-between; gap:2px 12px; font-size:13px; }
.pf-floats li span { font-variant-numeric:tabular-nums; font-weight:600; }

/* ---- the guest city (lib/guest.js, 1 Oct 2026) ---- */
.guest-banner { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:6px 14px;
  margin:0 0 10px; padding:9px 14px; border-radius:4px; background:#1B2420; color:#F3EEE1; font-size:13px; line-height:1.4; }
.guest-banner b { color:#E2C468; }
.guest-banner a { color:#F3EEE1; font-weight:600; text-decoration:underline; text-underline-offset:3px; white-space:nowrap; }
.guest-tag { display:inline-block; vertical-align:middle; margin-left:8px; padding:3px 9px; border-radius:4px;
  background:#1B2420; color:#E2C468; font:600 11px/1.4 'IBM Plex Mono', monospace; letter-spacing:.12em; text-transform:uppercase; }

/* ---- THE FIRST MINUTE (lib: public/app.jsx FirstTour, 2 Oct 2026) ----------
   A night stage, one picture and one line a scene. The pictures are drawn on
   a 340 by 330 board scaled to the screen, so every move lands in the same
   place on a phone and a desktop. Every animation fills both ways, so under
   reduced motion (.ft-still) each jumps straight to its last frame. */
.ft { position:fixed; inset:0; z-index:400; display:flex; flex-direction:column; color:#F3EEE1;
  background:radial-gradient(ellipse at 50% 18%, #26346F 0%, #161F55 45%, #0B1030 100%);
  font-family:'IBM Plex Sans', sans-serif; overflow:hidden; --k:1; }
/* !important, because every shorthand below would otherwise reset it to none
   and an element would sit at its last frame before its turn came. */
.ft *, .ft *::before, .ft *::after { animation-fill-mode:both !important; }
.ft-top { display:flex; flex-direction:column; gap:10px; padding:14px 16px 0; max-width:640px; width:100%; margin:0 auto; }
.ft-bars { display:grid; grid-template-columns:repeat(4, 1fr); gap:6px; }
.ft-bars span { height:4px; border-radius:2px; background:rgba(243,238,225,.22); overflow:hidden; }
.ft-bars span.is-done i { width:100%; }
.ft-bars i { display:block; height:100%; width:0; background:#E2C468; }
.ft-bars span.is-now i { animation:ft-bar linear forwards; }
.ft-still .ft-bars span.is-now i { width:100%; animation:none; }
@keyframes ft-bar { from { width:0; } to { width:100%; } }
.ft-links { display:flex; justify-content:space-between; }
.ft-links button { background:none; border:0; color:rgba(243,238,225,.78); font:500 13px 'IBM Plex Sans', sans-serif; padding:6px 2px; cursor:pointer;
  text-decoration:underline; text-underline-offset:3px; }
.ft-links button:focus-visible, .ft button:focus-visible { outline:2px solid #E2C468; outline-offset:3px; }
.ft-body { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px; padding:8px 16px 18px;
  max-width:640px; width:100%; margin:0 auto; cursor:pointer; min-height:0; }
.ft-stage { position:relative; width:calc(340px * var(--k)); height:calc(330px * var(--k)); flex:none; }
.ft-scene { position:absolute; left:0; top:0; width:340px; height:330px; transform:scale(var(--k)); transform-origin:0 0; }
.ft-words { text-align:center; max-width:30rem; animation:ft-rise .5s ease .15s both; }
.ft-words h2 { font:700 clamp(24px, 6.4vw, 34px)/1.1 'Fraunces', serif; margin:0 0 8px; letter-spacing:-.01em; text-wrap:balance; }
.ft-words p { margin:0; font-size:16px; line-height:1.45; color:rgba(243,238,225,.82); text-wrap:pretty; }
@keyframes ft-rise { from { opacity:0; transform:translateY(12px); } to { opacity:1; transform:none; } }
.ft-nav { display:flex; gap:12px; justify-content:center; width:100%; cursor:default; }
.ft-nav button, .ft-cta, .ft-quiet { font:600 15px 'IBM Plex Sans', sans-serif; border-radius:8px; cursor:pointer; padding:11px 22px; }
.ft-next, .ft-cta { background:#E2C468; color:#161F55; border:1px solid #E2C468; }
.ft-back-btn, .ft-quiet { background:transparent; color:#F3EEE1; border:1px solid rgba(243,238,225,.35); }
.ft-back-btn:disabled { opacity:.35; cursor:default; }
.ft-stamp { position:absolute; z-index:5; font:800 22px/1 'IBM Plex Mono', monospace; letter-spacing:.14em; text-transform:uppercase;
  padding:8px 12px; border:3px solid currentColor; border-radius:4px; background:rgba(11,16,48,.25); pointer-events:none; }
.ft-chip { position:absolute; font:600 11px 'IBM Plex Mono', monospace; letter-spacing:.12em; text-transform:uppercase; padding:5px 9px; border-radius:999px; }

/* 1. THE DRAW: three deeds, shuffled, one turned over. */
.ft-back, .ft-flip { position:absolute; left:95px; top:34px; width:150px; height:210px; }
.ft-back, .ft-face-back, .ft-end-card { border-radius:8px; border:3px solid #E2C468;
  background:repeating-linear-gradient(45deg, #1F2B66 0 8px, #1A245A 8px 16px); box-shadow:0 12px 26px rgba(0,0,0,.45);
  display:grid; place-items:center; }
.ft-back i, .ft-face-back i, .ft-end-card i { font:700 54px 'Fraunces', serif; font-style:normal; color:#E2C468;
  width:78px; height:78px; display:grid; place-items:center; border:2px solid rgba(226,196,104,.6); border-radius:50%; }
.ft-b1 { animation:ft-b1 4.4s ease .1s; }
.ft-b3 { animation:ft-b3 4.4s ease .2s; }
@keyframes ft-b1 {
  0% { opacity:0; transform:translate(-110px, 50px) rotate(-6deg); }
  14% { opacity:1; transform:translate(-110px, 0) rotate(-6deg); }
  26% { transform:translate(0, -16px) rotate(0); }
  38% { transform:translate(110px, 0) rotate(6deg); }
  50% { transform:translate(0, 16px) rotate(0); }
  60% { opacity:1; transform:translate(-110px, 0) rotate(-6deg); }
  78%, 100% { opacity:.18; transform:translate(-150px, 14px) rotate(-10deg) scale(.86); }
}
@keyframes ft-b3 {
  0% { opacity:0; transform:translate(110px, 50px) rotate(6deg); }
  14% { opacity:1; transform:translate(110px, 0) rotate(6deg); }
  26% { transform:translate(0, 16px) rotate(0); }
  38% { transform:translate(-110px, 0) rotate(-6deg); }
  50% { transform:translate(0, -16px) rotate(0); }
  60% { opacity:1; transform:translate(110px, 0) rotate(6deg); }
  78%, 100% { opacity:.18; transform:translate(150px, 14px) rotate(10deg) scale(.86); }
}
.ft-flip { animation:ft-lift 4.6s ease 0s; z-index:2; }
@keyframes ft-lift {
  0% { opacity:0; transform:translateY(50px); }
  12% { opacity:1; transform:none; }
  22% { transform:translateY(8px); } 34% { transform:translateY(-8px); } 46% { transform:none; }
  58% { transform:none; }
  70%, 100% { transform:translateY(-6px) scale(1.08); }
}
/* Turned in two halves, the back narrowing to nothing and the front widening
   from it, rather than in 3D: a backface that will not hide is a front seen
   through its own back. */
.ft-face { position:absolute; inset:0; }
.ft-face-back { animation:ft-turn-back .4s ease-in 3.2s; }
.ft-face-front { animation:ft-turn-front .4s ease-out 3.6s, ft-glow 1.8s ease-in-out 4.1s 2; border-radius:8px; background:#FBF8F0;
  border:5px solid #C6BC9F; overflow:hidden; display:flex; flex-direction:column; color:#1B2420; box-shadow:0 14px 30px rgba(0,0,0,.5); }
.ft-face-front.q-uncommon { border-color:#8E979F; }
.ft-face-front.q-rare { border-color:#B08C1E; }
.ft-face-front.q-ultra { border-color:#B4342E; }
@keyframes ft-turn-back { from { transform:scaleX(1); } to { transform:scaleX(0); } }
@keyframes ft-turn-front { from { transform:scaleX(0); } to { transform:scaleX(1); } }
@keyframes ft-glow { 0%, 100% { box-shadow:0 14px 30px rgba(0,0,0,.5); } 50% { box-shadow:0 0 0 4px rgba(226,196,104,.55), 0 0 40px 8px rgba(226,196,104,.45); } }
.ft-deed-art { position:relative; height:112px; overflow:hidden; background:#DCD6C6; }
.ft-deed-art img, .ft-deed-art svg { width:100%; height:100%; object-fit:cover; display:block; }
.ft-deed-art .ribbon { position:absolute; top:6px; right:6px; transform:scale(.85); transform-origin:100% 0; }
.ft-deed-cap { padding:8px 10px; display:grid; gap:3px; }
.ft-deed-cap b { font:700 15px/1.15 'Fraunces', serif; }
.ft-deed-cap span { font:500 10px 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:#6b6455; }
.ft-deed-cap em { font-style:normal; font-size:12.5px; font-weight:600; color:#2F7A4B; font-variant-numeric:tabular-nums; margin-top:3px; }
.ft-stamp-yours { left:-26px; top:58px; color:#E2C468; animation:ft-stamp .45s cubic-bezier(.3,1.6,.5,1) 4.5s; }
@keyframes ft-stamp { from { opacity:0; transform:scale(2.3) rotate(-14deg); } to { opacity:1; transform:scale(1) rotate(-10deg); } }

/* 2. THE CARDS: dealt, one sealed, the evening, and it lands. */
.ft-target { position:absolute; left:72px; top:0; width:196px; border-radius:8px; overflow:hidden; background:#FBF8F0; color:#1B2420;
  border:4px solid #E2761B; box-shadow:0 10px 24px rgba(0,0,0,.45); animation:ft-rise .5s ease .1s, ft-shake .45s ease 5.85s; }
.ft-target-art { height:86px; background:#DCD6C6; }
.ft-target-art img, .ft-target-art svg { width:100%; height:100%; object-fit:cover; display:block; }
.ft-target-cap { position:relative; padding:6px 9px 8px; display:grid; gap:2px; min-height:46px; }
.ft-target-cap span { font:500 10px 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:#6b6455; }
.ft-target-cap b { font-size:14px; font-variant-numeric:tabular-nums; }
.ft-rent-live { color:#2F7A4B; animation:ft-out .25s ease 5.9s; }
.ft-rent-dead { position:absolute; left:9px; bottom:8px; color:#B0342A; animation:ft-in .3s ease 6.0s; }
@keyframes ft-out { from { opacity:1; } to { opacity:0; } }
@keyframes ft-in { from { opacity:0; transform:translateY(4px); } to { opacity:1; transform:none; } }
@keyframes ft-shake { 0%, 100% { transform:none; } 20% { transform:translateX(-7px) rotate(-1.5deg); } 45% { transform:translateX(6px) rotate(1deg); } 70% { transform:translateX(-3px); } }
.ft-stamp-landed { left:50%; top:48px; margin-left:-62px; color:#E5574A; animation:ft-stamp .45s cubic-bezier(.3,1.6,.5,1) 5.95s; }
.ft-clock { position:absolute; left:276px; top:6px; width:60px; height:30px; border-radius:6px; background:#0B1030; border:1px solid rgba(226,196,104,.5);
  font:600 15px/30px 'IBM Plex Mono', monospace; color:#E2C468; text-align:center; overflow:hidden; animation:ft-rise .4s ease .3s; }
.ft-clock span { position:absolute; inset:0; }
.ft-clock-a { animation:ft-flip-out .35s ease 4.7s; }
.ft-clock-b { animation:ft-flip-in .35s ease 4.85s; }
@keyframes ft-flip-out { from { transform:none; opacity:1; } to { transform:translateY(-100%); opacity:0; } }
@keyframes ft-flip-in { from { transform:translateY(100%); opacity:0; } to { transform:none; opacity:1; } }
.ft-hand { position:absolute; left:0; top:168px; width:340px; height:150px; }
.ft-card { position:absolute; top:0; width:84px; }
.ft-card .tcard { --cw:84px; border-width:4px !important; box-shadow:0 8px 16px rgba(0,0,0,.45); }
.ft-card .tcard-plate { display:none; }
.ft-card .tcard-ribbon { font-size:6px; padding:2px 4px; }
.ft-card-0 { left:34px; animation:ft-deal0 3.4s ease .25s; }
.ft-card-1 { left:102px; z-index:3; animation:ft-play 6.1s ease 0s; }
.ft-card-2 { left:170px; animation:ft-deal2 3.4s ease .55s; }
.ft-card-3 { left:238px; animation:ft-deal3 3.4s ease .7s; }
@keyframes ft-deal0 { 0% { opacity:0; transform:translateY(-190px) rotate(0); } 14% { opacity:1; transform:translateY(14px) rotate(-12deg); } 75% { opacity:1; transform:translateY(14px) rotate(-12deg); } 100% { opacity:.4; transform:translateY(22px) rotate(-12deg); } }
@keyframes ft-deal2 { 0% { opacity:0; transform:translateY(-190px) rotate(0); } 14% { opacity:1; transform:translateY(2px) rotate(4deg); } 75% { opacity:1; transform:translateY(2px) rotate(4deg); } 100% { opacity:.4; transform:translateY(10px) rotate(4deg); } }
@keyframes ft-deal3 { 0% { opacity:0; transform:translateY(-190px) rotate(0); } 14% { opacity:1; transform:translateY(14px) rotate(12deg); } 75% { opacity:1; transform:translateY(14px) rotate(12deg); } 100% { opacity:.4; transform:translateY(22px) rotate(12deg); } }
/* The one that is played: dealt, lifted and sealed, then at the evening it
   flies to the rival's building and is gone. */
@keyframes ft-play {
  0% { opacity:0; transform:translateY(-190px) rotate(0); }
  7% { opacity:1; transform:translateY(2px) rotate(-4deg); }
  28% { transform:translateY(2px) rotate(-4deg); filter:none; }
  36% { transform:translateY(-28px) scale(1.12) rotate(0); filter:drop-shadow(0 0 14px rgba(226,196,104,.85)); }
  80% { opacity:1; transform:translateY(-28px) scale(1.12) rotate(0); filter:drop-shadow(0 0 14px rgba(226,196,104,.85)); }
  95% { opacity:1; transform:translate(26px, -146px) scale(.42) rotate(18deg); }
  100% { opacity:0; transform:translate(26px, -146px) scale(.3) rotate(24deg); }
}
/* The card's name, then that it is sealed, in the same place one after the
   other: a name over the rival's building hid its rent. */
.ft-chip-name { left:50%; transform:translateX(-50%); top:302px; color:#F3EEE1; background:#7E1F33; border:1px solid #E8A9B8; white-space:nowrap;
  animation:ft-chip 1.25s ease 1.8s; z-index:4; }
.ft-chip-sealed { left:50%; transform:translateX(-50%); top:302px; color:#161F55; background:#E2C468; white-space:nowrap;
  animation:ft-chip 2.2s ease 3.1s; }
@keyframes ft-chip { 0% { opacity:0; } 12% { opacity:1; } 88% { opacity:1; } 100% { opacity:0; } }

/* 3. THE COUNCIL: your field round the table, three games, skill. */
.ft-table { position:absolute; left:110px; top:4px; width:120px; height:120px; border-radius:50%;
  background:radial-gradient(circle, #2E7D5B 0%, #1F5A41 70%); border:3px solid #7E5A2A; box-shadow:0 10px 24px rgba(0,0,0,.45);
  animation:ft-pop .45s ease .1s; }
.ft-table-mid { position:absolute; inset:0; display:grid; place-items:center; font:600 9px 'IBM Plex Mono', monospace; letter-spacing:.12em;
  text-transform:uppercase; color:rgba(243,238,225,.85); }
.ft-seat { position:absolute; left:50%; top:50%; width:34px; height:34px; margin:-17px 0 0 -17px; border-radius:50%; display:grid; place-items:center;
  background:#F3EEE1; color:#161F55; font:700 13px 'Fraunces', serif; border:2px solid #0B1030; }
.ft-seat.is-you { background:#E2C468; font-size:10px; font-family:'IBM Plex Mono', monospace; }
.ft-seat-0 { --a:90deg; } .ft-seat-1 { --a:150deg; } .ft-seat-2 { --a:210deg; } .ft-seat-3 { --a:270deg; } .ft-seat-4 { --a:330deg; } .ft-seat-5 { --a:30deg; }
.ft-seat { transform:rotate(var(--a)) translate(70px) rotate(calc(var(--a) * -1)); animation:ft-seat .4s ease; }
.ft-seat-0 { animation-delay:.3s; } .ft-seat-1 { animation-delay:.42s; } .ft-seat-2 { animation-delay:.54s; } .ft-seat-3 { animation-delay:.66s; } .ft-seat-4 { animation-delay:.78s; } .ft-seat-5 { animation-delay:.9s; }
@keyframes ft-seat { from { opacity:0; transform:rotate(var(--a)) translate(20px) rotate(calc(var(--a) * -1)) scale(.4); } to { opacity:1; transform:rotate(var(--a)) translate(70px) rotate(calc(var(--a) * -1)); } }
@keyframes ft-pop { from { opacity:0; transform:scale(.6); } to { opacity:1; transform:none; } }
.ft-games { position:absolute; left:14px; right:14px; top:150px; display:grid; gap:9px; }
.ft-game { position:relative; display:grid; grid-template-columns:30px 1fr; gap:10px; align-items:center; padding:9px 12px; border-radius:8px;
  background:#F3EEE1; color:#1B2420; box-shadow:0 8px 18px rgba(0,0,0,.35); }
.ft-game svg { color:#7E1F1B; }
.ft-game b { display:block; font:700 14.5px 'Fraunces', serif; }
.ft-game span { display:block; font-size:12px; color:#4E5A55; }
.ft-game-0 { animation:ft-slide .45s ease 1.2s; } .ft-game-1 { animation:ft-slide .45s ease 1.8s; } .ft-game-2 { animation:ft-slide .45s ease 2.4s; }
@keyframes ft-slide { from { opacity:0; transform:translateX(60px); } to { opacity:1; transform:none; } }
.ft-skill { position:absolute; right:10px; top:50%; margin-top:-12px; font:700 12px/24px 'IBM Plex Mono', monospace; font-style:normal;
  color:#161F55; background:#E2C468; padding:0 9px; border-radius:999px; }
.ft-game-0 .ft-skill { animation:ft-skill 1.1s ease 3.4s; } .ft-game-1 .ft-skill { animation:ft-skill 1.1s ease 4.0s; } .ft-game-2 .ft-skill { animation:ft-skill 1.1s ease 4.6s; }
@keyframes ft-skill { 0% { opacity:0; transform:translateY(10px) scale(.6); } 30% { opacity:1; transform:translateY(-4px) scale(1.12); } 100% { opacity:1; transform:none; } }

/* 4. THE CITY: six things to find, one after another. */
.ft-city { display:grid; grid-template-columns:repeat(3, 104px); grid-auto-rows:150px; gap:12px; padding:8px 4px 0; align-content:start; }
.ft-tile { display:grid; grid-template-rows:1fr auto; gap:6px; padding:8px 8px 10px; border-radius:10px; background:#F3EEE1; color:#1B2420;
  box-shadow:0 8px 18px rgba(0,0,0,.35); text-align:center; animation:ft-pop .4s ease; }
.ft-tile b { font:700 12.5px/1.15 'Fraunces', serif; }
.ft-tile-pic { display:grid; place-items:center; min-height:0; }
.ft-tile-pic svg { width:100%; height:auto; max-height:84px; }
.ft-tile-0 { animation-delay:.2s; } .ft-tile-1 { animation-delay:.55s; } .ft-tile-2 { animation-delay:.9s; }
.ft-tile-3 { animation-delay:1.25s; } .ft-tile-4 { animation-delay:1.6s; } .ft-tile-5 { animation-delay:1.95s; }
.ft-wash { animation:ft-wash 1.2s ease .7s; }
@keyframes ft-wash { from { opacity:0; } to { opacity:.85; } }
.ft-crown { animation:ft-pop .4s ease 1.6s; transform-box:fill-box; transform-origin:center; }
.ft-line { stroke-dasharray:160; animation:ft-draw 1.6s ease 1.0s; }
@keyframes ft-draw { from { stroke-dashoffset:160; } to { stroke-dashoffset:0; } }
.ft-b-base { animation:ft-drop .35s ease 1.3s; } .ft-b-walls { animation:ft-drop .35s ease 1.6s; }
.ft-b-roof { animation:ft-drop .35s ease 1.9s; } .ft-b-door { animation:ft-drop .3s ease 2.2s; }
@keyframes ft-drop { from { opacity:0; transform:translateY(-26px); } to { opacity:1; transform:none; } }
.ft-tick { stroke-dasharray:20; animation:ft-tick .35s ease; }
.ft-tick-0 { animation-delay:1.8s; } .ft-tick-1 { animation-delay:2.1s; } .ft-tick-2 { animation-delay:2.4s; }
@keyframes ft-tick { from { stroke-dashoffset:20; } to { stroke-dashoffset:0; } }
.ft-medal { animation:ft-spin .8s ease 2.0s; }
@keyframes ft-spin { from { opacity:0; transform:rotateY(180deg) scale(.6); } to { opacity:1; transform:none; } }
.ft-gavel { transform-box:view-box; transform-origin:47px 64px; animation:ft-gavel .7s ease-in-out 2.5s 3; }
@keyframes ft-gavel { 0%, 100% { transform:rotate(0); } 45% { transform:rotate(-28deg); } 70% { transform:rotate(4deg); } }

/* THE END: the free draw, waiting. */
.ft-end { cursor:default; gap:14px; }
.ft-end-card { width:120px; height:168px; animation:ft-pop .5s ease, ft-glow 2s ease-in-out .5s infinite; }
.ft-cta { font-size:17px; padding:14px 30px; box-shadow:0 0 0 4px rgba(226,196,104,.25); }
.ft-quiet { font-size:14px; padding:9px 18px; }
.ft-end .ft-quiet + .ft-quiet { border:0; text-decoration:underline; text-underline-offset:3px; padding-top:0; }

/* Reduced motion: every animation at its last frame, nothing moving. */
.ft-still *, .ft-still *::before, .ft-still *::after { animation-delay:-120s !important; animation-iteration-count:1 !important; }
.ft-still .ft-end-card { animation:none; }
@media (max-height:640px) { .ft-words p { font-size:14px; } .ft-body { gap:10px; } }

/* ---- first steps (FirstSteps in public/app.jsx, 2 Oct 2026) ----
   A slim card along the bottom of the real game, never over the middle of
   it. The thing to press next glows on its own tab. */
.fs { position:fixed; left:0; right:0; bottom:0; z-index:300; padding:0 10px max(10px, env(safe-area-inset-bottom)); pointer-events:none; }
.fs-in { pointer-events:auto; max-width:620px; margin:0 auto; background:#161F55; color:#F3EEE1; border:1px solid rgba(226,196,104,.55);
  border-radius:12px; box-shadow:0 14px 34px rgba(11,16,48,.45); padding:10px 14px 12px; display:grid; gap:8px;
  animation:fs-up .35s ease both; }
@keyframes fs-up { from { opacity:0; transform:translateY(20px); } to { opacity:1; transform:none; } }
.fs-top { display:flex; justify-content:space-between; align-items:center; gap:10px; }
.fs-dots { display:flex; gap:6px; }
.fs-dots i { width:22px; height:22px; border-radius:50%; display:grid; place-items:center; font:700 11px 'IBM Plex Mono', monospace; font-style:normal;
  border:1px solid rgba(243,238,225,.35); color:rgba(243,238,225,.7); }
.fs-dots i.is-now { background:#E2C468; border-color:#E2C468; color:#161F55; }
.fs-dots i.is-done { background:#2F7A4B; border-color:#2F7A4B; color:#fff; }
.fs-links { display:flex; gap:14px; }
.fs-links button { background:none; border:0; color:rgba(243,238,225,.75); font:500 12.5px 'IBM Plex Sans', sans-serif; cursor:pointer;
  text-decoration:underline; text-underline-offset:3px; padding:2px 0; }
.fs-body { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.fs-words { flex:1 1 260px; display:grid; gap:2px; }
.fs-words b { font:700 17px/1.2 'Fraunces', serif; }
.fs-words span { font-size:13.5px; line-height:1.4; color:rgba(243,238,225,.85); }
.fs-go { flex:none; background:#E2C468; color:#161F55; border:0; border-radius:8px; font:600 14.5px 'IBM Plex Sans', sans-serif; padding:10px 18px; cursor:pointer; }
.fs-go:focus-visible, .fs-links button:focus-visible, .fs-explore button:focus-visible { outline:2px solid #E2C468; outline-offset:2px; }
.fs-end { display:grid; gap:10px; }
.fs-explore { display:flex; flex-wrap:wrap; gap:6px; }
.fs-explore button { background:transparent; color:#F3EEE1; border:1px solid rgba(243,238,225,.4); border-radius:999px; font:500 13px 'IBM Plex Sans', sans-serif;
  padding:6px 12px; cursor:pointer; }
.fs-explore button:hover { border-color:#E2C468; color:#E2C468; }
/* The next thing to press: a pulse in the guide card's own navy, so it reads
   as "this one" and never as a rarity (gold is the rare ring). */
.fs-glow { position:relative; z-index:2; border-radius:8px; animation:fs-glow 1.6s ease-in-out infinite; }
@keyframes fs-glow { 0%, 100% { box-shadow:0 0 0 0 rgba(22,31,85,0); } 50% { box-shadow:0 0 0 4px rgba(22,31,85,.85), 0 0 24px 6px rgba(38,52,111,.45); } }
@media (prefers-reduced-motion: reduce) { .fs-in { animation:none; } .fs-glow { animation:none; box-shadow:0 0 0 3px rgba(22,31,85,.9); } }
/* Room at the foot of the page for the card. */
body:has(.fs) .ukpx-root { padding-bottom:150px; }
/* First steps steps aside while a window or the draw is open, so it never
   covers the button it is pointing at (on a phone it sat over "Take your
   free draw"). */
body:has(.modal-backdrop) .fs, body:has(.draw-overlay) .fs { display:none; }
/* The first pull, cut to one line and one button. */
.lotto-quick { display:flex; flex-direction:column; align-items:flex-start; gap:12px; padding-top:2px; }
.lotto-quick .lotto-lede { margin:0; font-size:15px; }
.lotto-quick .btn.lotto-go { order:0; flex:none; font-size:17px; padding:14px 26px; }
@media (max-width: 600px) { .lotto-quick .btn.lotto-go { align-self:stretch; } }
.lotto-more { background:none; border:0; padding:2px 0; color:#4b463a; font:500 13.5px 'IBM Plex Sans', sans-serif; text-decoration:underline; text-underline-offset:3px; cursor:pointer; }

/* ---- the masthead (Masthead in public/app.jsx) ------------------------
   The Portfolio's banner as one piece, a colour per page. Labels in mono,
   the figure in Fraunces, a line under it; the feature tile carries the
   page's accent as a rule along its top. */
.mast { --m-bg:#364F45; --m-bg2:#2F463D; --m-edge:#223028; --m-label:#A8BCAF; --m-accent:#E4BA8E;
  display:grid; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
  background:linear-gradient(180deg, var(--m-bg), var(--m-bg2)); border:1px solid var(--m-edge);
  box-shadow:0 10px 26px rgba(28,30,34,.18); }
.mast-council { --m-bg:#4C5A30; --m-bg2:#3F4B27; --m-edge:#283018; --m-label:#C9D2AE; --m-accent:#F2C08F; }
.mast-floor   { --m-bg:#5A3E2B; --m-bg2:#4B3322; --m-edge:#2E1F14; --m-label:#D9C3A9; --m-accent:#F0C38E; }
.mast-bank    { --m-bg:#1F5560; --m-bg2:#194750; --m-edge:#0F2E34; --m-label:#A9CDD3; --m-accent:#F2C994; }
.mast-board   { --m-bg:#2C3340; --m-bg2:#232934; --m-edge:#151920; --m-label:#B4BDCB; --m-accent:#E9B98A; }
.mast-tile { display:grid; align-content:start; gap:7px; padding:17px 20px 19px; min-width:0;
  border-left:1px solid rgba(255,255,255,.12); }
.mast-tile:first-child { border-left:0; }
.mast-tile.is-wide { grid-column:span 2; }
.mast-label { font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.18em; text-transform:uppercase; color:var(--m-label); }
.mast-value { font-family:'Fraunces', serif; font-weight:700; font-size:22px; line-height:1.15; color:#F4EFE3;
  letter-spacing:-.01em; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
.mast-value em { font-style:normal; font-weight:500; font-size:14px; color:var(--m-label); }
.mast-value span { font:inherit; color:inherit; letter-spacing:inherit; }
.mast-foot { font-size:11.5px; line-height:1.35; color:rgba(244,239,227,.64); }
.mast-foot span { font:inherit; color:inherit; }
.mast-tile.is-feature { box-shadow:inset 0 3px 0 var(--m-accent); background:rgba(255,255,255,.04); }
.mast-tile.is-feature .mast-value { color:var(--m-accent); }
@media (max-width: 760px) {
  .mast { grid-template-columns:1fr 1fr; }
  .mast-tile { border-left:0; border-top:1px solid rgba(255,255,255,.12); padding:13px 16px 15px; }
  .mast-tile:nth-child(-n+2) { border-top:0; }
  .mast-tile.is-wide { grid-column:auto; }
  .mast-tile:nth-child(even) { border-left:1px solid rgba(255,255,255,.12); }
  .mast-value { font-size:19px; }
}

/* ---- the trading floor, dressed (2 Oct 2026) --------------------------
   The Portfolio's particulars carried across: white cards on the paper, a
   walnut edge, the figure in Fraunces. The switch is in the floor's walnut;
   an offer waiting for an answer is marked in the masthead's tan, never
   gold (gold is a rarity). */
.floor { display:flex; flex-direction:column; gap:16px; }
.floor .floor-switch { margin:0; border:1px solid #CBC1A9; background:#FCFAF4; padding:4px; gap:4px; }
.floor .floor-tab { min-height:40px; border:0 !important; font-size:14px; color:#5B4A3A; }
.floor .floor-tab:hover:not(.on) { background:rgba(90,62,43,.07); }
.floor .floor-tab.on { background:#5A3E2B; color:#F4EFE3; }
.floor .floor-tab em.due { background:#F0C38E; color:#2E1F14; }
.floor .floor-tab:focus-visible { outline:2px solid #5A3E2B; outline-offset:2px; }
.floor > div > .intro, .floor .intro { margin:0 0 14px; }
.floor .card { background:#FCFAF4; border:1px solid #CBC1A9; border-left:3px solid #5A3E2B; padding:18px 20px;
  box-shadow:0 2px 0 rgba(203,193,169,.5); }
.floor .card h3 { font-family:'Fraunces', serif; font-weight:700; color:#3A2A1C; }
.floor .one-away { border-left-color:#B5763B; }
.floor .mutual-matches { border-left-color:var(--brick); }
.floor .wanted-from-me { border-left-color:var(--forest); }
.floor .gap-holder { background:#F4EFE3; border-color:#D8CDB4; }
.floor .gap-holder:hover { border-color:#5A3E2B; background:#fff; }
.floor .check-list { background:#fff; border-color:#D8CDB4; }
.floor .field-row input, .floor .search-input, .floor select { background:#fff; }
/* An auction lot: the building first, the bid in its own box. */
.floor .auc-card .card-row { display:grid; grid-template-columns:120px 1fr auto; gap:16px; align-items:center; }
.floor .auc-shot { width:120px; aspect-ratio:4 / 3; overflow:hidden; background:#E9E2D0; border:1px solid #D8CDB4; line-height:0; }
.floor .auc-shot img, .floor .auc-shot svg { width:100%; height:100%; object-fit:cover; display:block; }
.floor .auc-main { min-width:0; }
.floor .auc-main h3 { font-size:20px; margin:0 0 6px; }
.floor .auc-bid { text-align:right; padding:10px 14px; background:#F4EFE3; border:1px solid #E1D7C1; min-width:150px; }
.floor .auc-bid .price { font:700 22px 'Fraunces', serif; color:#3A2A1C; font-variant-numeric:tabular-nums; }
.floor .auc-card.is-leading { border-left-color:var(--gain); }
.floor .auc-card.is-leading .auc-bid { background:rgba(47,107,69,.09); border-color:rgba(47,107,69,.3); }
.floor .auc-card.is-leading .auc-bid .price { color:var(--gain); }
.floor .auc-card .auction-clock { margin:14px 0 12px; }
.floor .auc-card .field-row { margin-top:0; }
.floor .auc-card .field-row .btn { background:#5A3E2B; border-color:#5A3E2B; }
@media (max-width: 620px) {
  .floor .auc-card .card-row { grid-template-columns:96px 1fr; }
  .floor .auc-shot { width:96px; }
  .floor .auc-bid { grid-column:1 / -1; text-align:left; display:flex; justify-content:space-between; align-items:baseline; flex-wrap:wrap; gap:4px 10px; min-width:0; }
  .floor .auc-bid .muted { flex-basis:100%; }
}

/* ---- the bank, dressed (2 Oct 2026) -----------------------------------
   Petrol, the colour of a banknote's ink: the masthead, the edge of every
   account and the ladder of tiers. The stocks pane is left as it was. */
.bankp { display:flex; flex-direction:column; gap:16px; }
.bankp > .intro { margin:0; }
.bankp .card { margin:0; background:#FCFAF4; border:1px solid #C9CFC6; border-left:3px solid #1F5560; padding:18px 20px;
  box-shadow:0 2px 0 rgba(190,198,190,.5); }
.bankp .card h3 { font-family:'Fraunces', serif; font-weight:700; color:#173E45; margin:0 0 4px; }
.bankp .card.is-locked { background:transparent; border-style:dashed; border-left-style:solid; border-left-color:#8FAEB3; box-shadow:none; }
.bankp .card.is-locked h3 { color:#5F7A7E; }
.bankp .btn:not(.secondary) { background:#1F5560; border-color:#1F5560; }
.bankp .field-row input { background:#fff; }
/* The stat rows inside an account: four small figures on a tinted band. */
.bankp .portfolio-total { display:grid; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr)); gap:1px;
  background:#D6E0DF; border:1px solid #D6E0DF; margin:10px 0 14px !important; }
.bankp .portfolio-total .block { background:#F1F5F3; border:0; padding:10px 14px; }
.bankp .portfolio-total .label { font-family:'IBM Plex Mono', monospace; font-size:9.5px; letter-spacing:.14em; color:#4F6C70; }
.bankp .portfolio-total .value { font-family:'Fraunces', serif; font-size:19px; font-weight:700; color:#173E45; }
/* The ladder of tiers. */
.bank-ladder { list-style:none; margin:0 0 16px; padding:0; display:grid; grid-template-columns:repeat(4, 1fr); gap:6px; counter-reset:none; }
.bank-ladder li { position:relative; display:grid; gap:3px; padding:10px 12px 11px; background:#EEF2EF; border:1px solid #D6E0DF; min-width:0; }
.bank-ladder .bl-step { width:22px; height:22px; border-radius:50%; display:grid; place-items:center; font:700 11px 'IBM Plex Mono', monospace;
  border:1.5px solid #8FAEB3; color:#4F6C70; background:#fff; }
.bank-ladder .bl-name { font:600 13.5px 'Fraunces', serif; color:#173E45; line-height:1.2; }
.bank-ladder .bl-cost { font:500 11px 'IBM Plex Mono', monospace; color:#5F7A7E; font-variant-numeric:tabular-nums; }
.bank-ladder li.is-held { background:#1F5560; border-color:#1F5560; }
.bank-ladder li.is-held .bl-step { background:#F2C994; border-color:#F2C994; color:#173E45; }
.bank-ladder li.is-held .bl-name { color:#F4EFE3; }
.bank-ladder li.is-held .bl-cost { color:#A9CDD3; }
.bank-ladder li.is-next { border:1.5px solid #1F5560; background:#fff; }
.bank-ladder li.is-next .bl-step { border-color:#1F5560; color:#1F5560; }
.bank-small-print { background:#EEF2EF !important; box-shadow:none !important; }
.bank-small-print h3 { font-size:15px; }
@media (max-width: 620px) {
  .bank-ladder { grid-template-columns:1fr 1fr; }
}

/* ---- the leaderboard, dressed (2 Oct 2026) ----------------------------
   Slate, a scoreboard's colour, for the masthead and the podium. The podium
   is told apart by height and the first place's tan rule, never by gold or
   silver, which are rarities in this game. The table sits on white with a
   thin bar under each figure, its length against the leader's. Your own row
   stays unshaded (Aaron, 27 Sep 2026): your name is in bold. */
.lboard { display:flex; flex-direction:column; gap:16px; }
.lboard > .intro, .lboard > .filter-bar { margin:0; }
.lb-podium { list-style:none; margin:0; padding:0; display:grid; grid-template-columns:1fr 1.15fr 1fr; gap:10px; align-items:end; }
.lbp { display:grid; gap:5px; justify-items:center; text-align:center; padding:16px 12px 14px; color:#F4EFE3;
  background:linear-gradient(180deg, #353D4C, #2A313D); border:1px solid #151920; min-width:0; }
.lbp-1 { order:2; padding-top:24px; padding-bottom:22px; box-shadow:inset 0 3px 0 #E9B98A, 0 10px 24px rgba(21,25,32,.22); }
.lbp-2 { order:1; }
.lbp-3 { order:3; }
.lbp-rank { font:700 30px 'Fraunces', serif; line-height:1; color:#B4BDCB; }
.lbp-1 .lbp-rank { font-size:40px; color:#E9B98A; }
.lbp-name { font:600 15px 'IBM Plex Sans', sans-serif; max-width:100%; overflow-wrap:anywhere; }
.lbp-name .trader-link:not(.is-leader):not(.is-magnate) { color:#F4EFE3; }
/* A leader's or magnate's colour is a key on this page, and too dark to
   read on slate: the name sits on a cream chip so the colour still shows. */
.lbp-name .trader-link.is-leader, .lbp-name .trader-link.is-magnate { background:#F4EFE3; padding:1px 7px; }
.lbp-net { font:700 20px 'Fraunces', serif; font-variant-numeric:tabular-nums; }
.lbp-1 .lbp-net { font-size:24px; }
.lbp-foot { font-size:11.5px; color:rgba(244,239,227,.64); }
.lbp.is-me .lbp-name { font-weight:800; }
.lboard .lb-wrap { background:#FCFAF4; border:1px solid #CBC1A9; box-shadow:0 2px 0 rgba(203,193,169,.5); }
.lboard .lb th { background:#F1ECE0; }
.lboard .lb td.rank { font:700 16px 'Fraunces', serif; color:#2C3340; }
.lboard .lb td.price { position:relative; }
.lb-bar { display:block; height:3px; margin-top:5px; background:rgba(44,51,64,.08); max-width:150px; }
.lb-bar i { display:block; height:100%; background:#56627A; }
.lboard .card { background:#FCFAF4; border:1px solid #CBC1A9; border-left:3px solid #2C3340; box-shadow:0 2px 0 rgba(203,193,169,.5); }
.lboard .card h3 { font-family:'Fraunces', serif; font-weight:700; }
#district-leaders tr.is-open td { color:#8A8373; }
#district-leaders tr.is-claimed .fh-name { font-weight:600; }
.fh-held { display:inline-grid; gap:4px; font-variant-numeric:tabular-nums; min-width:70px; }
.fh-held i { display:block; height:4px; background:rgba(44,51,64,.1); }
.fh-held b { display:block; height:100%; background:#2C3340; }
@media (max-width: 620px) {
  .lb-podium { grid-template-columns:1fr; }
  .lbp, .lbp-1, .lbp-2, .lbp-3 { order:0; padding:12px 14px; grid-template-columns:auto 1fr auto; justify-items:start; text-align:left; align-items:center; column-gap:12px; }
  .lbp-rank, .lbp-1 .lbp-rank { font-size:26px; grid-row:span 2; }
  .lbp-net, .lbp-1 .lbp-net { font-size:18px; justify-self:end; }
  .lbp-foot { grid-column:2 / -1; }
}
