/* THE PHONE — the designer's line to her client, and the client's to her.
 *
 * It loads on three pages that do not agree about anything: the studio (dark, and carrying the
 * full token set from app.css and silk.css), the approval page (light, standalone, no tokens at
 * all), and the 3D link (dark, also standalone). So this file names ONE set of its own variables
 * on the host element and nothing else, each falling back to a literal when the page it landed on
 * has no design system to inherit from.
 *
 * NO SIX-DIGIT HEX ANYWHERE IN HERE. scripts/palette-check.py covers this file for the same
 * reason it covers market.css and scheme.css — one palette, and a literal is how a second one
 * starts. rgba() is deliberately outside that rule and is what the fallbacks use.
 *
 * Everything is namespaced under #ginphone / #ginphone-fab and the .gp- prefix, so the whole
 * feature can be removed by deleting one <link>. Nothing here touches an existing selector.
 */

#ginphone-fab,
#ginphone {
  --gp-ink:      var(--text,    rgba(236, 238, 245, 1));
  --gp-ink-2:    var(--text-2,  rgba(166, 172, 188, 1));
  --gp-ink-3:    var(--text-3,  rgba(126, 133, 150, 1));
  --gp-panel:    var(--panel,   rgba(22, 24, 32, 1));
  --gp-panel-2:  var(--panel-2, rgba(30, 33, 43, 1));
  --gp-line:     var(--line,    rgba(255, 255, 255, .10));
  --gp-accent:   var(--accent,  rgba(122, 138, 255, 1));
  --gp-on-accent: rgba(255, 255, 255, .97);
  --gp-good:     var(--good,    rgba(86, 196, 134, 1));
  --gp-warn:     var(--warn,    rgba(232, 168, 74, 1));
  --gp-shadow:   0 24px 64px rgba(0, 0, 0, .46), 0 2px 8px rgba(0, 0, 0, .3);
  --gp-r:        18px;
  font-family: var(--sans, system-ui, -apple-system, "Segoe UI", sans-serif);
}

/* A LIGHT PAGE IS NOT A DARK PAGE WITH DIFFERENT NUMBERS. The approval page has no tokens, so
 * the fallbacks above resolve dark — correct in the studio, wrong on paper. A page says which
 * it is and the phone believes it. */
.gp-light #ginphone-fab,
.gp-light #ginphone {
  --gp-ink:      rgba(26, 28, 34, 1);
  --gp-ink-2:    rgba(94, 100, 112, 1);
  --gp-ink-3:    rgba(136, 142, 154, 1);
  --gp-panel:    rgba(255, 255, 255, 1);
  --gp-panel-2:  rgba(244, 245, 248, 1);
  --gp-line:     rgba(16, 18, 24, .12);
  --gp-accent:   rgba(58, 78, 220, 1);
  --gp-shadow:   0 24px 64px rgba(16, 18, 30, .20), 0 2px 8px rgba(16, 18, 30, .10);
}

/* ── the button ──────────────────────────────────────────────────────────────
 *
 * Bottom-right, because that is where this product already puts a floating button, and far
 * enough up to clear the one that is there. Under #toasts (5100) on purpose: a toast is the
 * thing that must never be covered. */
#ginphone-fab {
  position: fixed;
  right: 24px;
  bottom: 96px;
  z-index: 620;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 1px solid var(--gp-line);
  background: var(--gp-panel);
  color: var(--gp-ink);
  box-shadow: var(--gp-shadow);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
  transition: transform .16s ease, background .16s ease;
}
#ginphone-fab:hover { transform: translateY(-2px); background: var(--gp-panel-2); }
#ginphone-fab:focus-visible { outline: 2px solid var(--gp-accent); outline-offset: 3px; }
#ginphone-fab svg { width: 23px; height: 23px; display: block; }

/* The count, and the ring. Same shape as the studio guide's badge, which is the one existing
 * precedent in this product for "something is waiting for you". */
#ginphone-fab.has-new::after {
  content: attr(data-unread);
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 10px;
  background: var(--gp-accent);
  color: var(--gp-on-accent);
  font: 600 11px/20px var(--sans, system-ui, sans-serif);
  text-align: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .35);
}
.gp-ring {
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 2px solid var(--gp-accent);
  opacity: 0;
  pointer-events: none;
}
#ginphone-fab.has-new .gp-ring { animation: gp-ring 2.3s ease-out infinite; }
@keyframes gp-ring {
  0%   { opacity: .75; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(1.65); }
  100% { opacity: 0;   transform: scale(1.65); }
}
@media (prefers-reduced-motion: reduce) {
  #ginphone-fab.has-new .gp-ring { animation: none; opacity: .5; }
}

/* ── the handset ───────────────────────────────────────────────────────────
 *
 * A DEVICE, NOT A PANEL. A rounded box with a list in it is a chat widget, and people have been
 * trained to ignore those in the corner of a website. The client of an interior designer is not
 * filing a support ticket; they are texting the person doing their house. So: a bezel with a
 * screen inside it, an island, a status bar and a home bar — the shape says what it is before a
 * word is read.
 *
 * Every piece of the furniture is aria-hidden in the markup. A screen reader should hear a
 * conversation, not a description of a telephone.
 */

#ginphone {
  position: fixed;
  right: 24px;
  bottom: 162px;              /* clear of its own button, which is 54px tall at 96px */
  z-index: 621;
  width: min(372px, calc(100vw - 32px));
  height: min(660px, calc(100vh - 194px));

  /* THE BODY. Two rings: a hard edge, then the metal, then the screen sits inside the padding. */
  padding: 11px 10px;
  border-radius: 46px;
  background:
    linear-gradient(160deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, 0) 38%),
    linear-gradient(200deg, rgba(92, 100, 124, 1), rgba(38, 42, 56, 1) 52%, rgba(24, 26, 36, 1));
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, .13),
    inset 0 0 0 1.5px rgba(0, 0, 0, .55),
    0 40px 90px rgba(0, 0, 0, .55),
    0 8px 24px rgba(0, 0, 0, .38);

  /* IT COMES UP OUT OF ITS OWN BUTTON. The origin is the corner the button sits in, so it grows
   * from there rather than appearing in the middle of nowhere. */
  transform-origin: calc(100% - 20px) calc(100% + 60px);
  transform: perspective(1200px) rotateX(12deg) rotateY(-8deg) scale(.82) translateY(26px);
  opacity: 0;
  transition: transform .42s cubic-bezier(.17, .84, .27, 1), opacity .2s ease;
  will-change: transform, opacity;
}
#ginphone.gp-open { transform: none; opacity: 1; }
#ginphone[hidden] { display: none; }

/* The screen. Everything that is a conversation lives in here. */
.gp-screen {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 36px;
  background: var(--gp-panel);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .5);
}

/* IT WAKES UP. A screen that is simply there was never off; one that lights as it opens reads as
 * a device being picked up. 420ms, once, and never again until it is closed. */
#ginphone.gp-open .gp-screen { animation: gp-wake .52s ease-out; }
@keyframes gp-wake {
  0%   { filter: brightness(2.4) saturate(.2); opacity: .25; }
  35%  { filter: brightness(1.25) saturate(.8); opacity: 1; }
  100% { filter: none; }
}

/* The camera cutout, floating over the status bar. */
.gp-island {
  position: absolute;
  top: 17px;
  left: 50%;
  transform: translateX(-50%);
  width: 86px;
  height: 25px;
  border-radius: 13px;
  background: rgba(0, 0, 0, .92);
  z-index: 4;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.gp-cam {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-left: 52px;
  background: radial-gradient(circle at 35% 35%, rgba(70, 92, 140, .9), rgba(8, 10, 16, 1) 70%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .07);
}

/* The status bar, which is what makes the island look like it belongs to something. */
.gp-status {
  flex: 0 0 auto;
  height: 40px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 24px 0;
  background: var(--gp-panel-2);
  pointer-events: none;
}
.gp-clock {
  font: 600 12px/1 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink);
  margin-inline-end: auto;
  font-variant-numeric: tabular-nums;
}
.gp-sig, .gp-wifi, .gp-batt { opacity: .62; }
.gp-sig {
  width: 15px; height: 10px;
  background:
    linear-gradient(to top, var(--gp-ink) 40%, transparent 40%) 0 100% / 3px 4px no-repeat,
    linear-gradient(to top, var(--gp-ink) 60%, transparent 60%) 4px 100% / 3px 6px no-repeat,
    linear-gradient(to top, var(--gp-ink) 80%, transparent 80%) 8px 100% / 3px 8px no-repeat,
    linear-gradient(to top, var(--gp-ink) 100%, transparent 100%) 12px 100% / 3px 10px no-repeat;
}
.gp-wifi {
  width: 13px; height: 10px;
  border: 2px solid var(--gp-ink);
  border-bottom: 0;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
}
.gp-batt {
  width: 22px; height: 11px;
  border: 1.3px solid var(--gp-ink);
  border-radius: 3.5px;
  position: relative;
}
.gp-batt::before {
  content: ''; position: absolute; inset: 1.6px; right: 7px;
  border-radius: 1.5px; background: var(--gp-ink);
}
.gp-batt::after {
  content: ''; position: absolute; top: 3.4px; right: -3.2px;
  width: 1.8px; height: 4px; border-radius: 0 1.5px 1.5px 0; background: var(--gp-ink);
  opacity: .7;
}

/* The sheen. One soft diagonal, low enough not to fight the text under it. */
.gp-glass {
  position: absolute;
  inset: 11px 10px;
  border-radius: 36px;
  pointer-events: none;
  background: linear-gradient(142deg,
    rgba(255, 255, 255, .055) 0%,
    rgba(255, 255, 255, .02) 26%,
    rgba(255, 255, 255, 0) 46%);
  z-index: 3;
}

.gp-home {
  position: absolute;
  bottom: 15px;
  left: 50%;
  transform: translateX(-50%);
  width: 108px;
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .30);
  z-index: 4;
  pointer-events: none;
}
.gp-light .gp-home { background: rgba(0, 0, 0, .28); }

/* THE BUTTONS DOWN THE SIDES. Nothing presses them. They are there because the eye reads an
 * unbroken slab as a card and a slab with buttons as a thing somebody holds. */
#ginphone::before,
#ginphone::after {
  content: '';
  position: absolute;
  inset-inline-end: -2px;
  width: 2.5px;
  border-radius: 2px;
  background: linear-gradient(180deg, rgba(150, 158, 182, .85), rgba(60, 66, 84, .85));
  pointer-events: none;
}
#ginphone::before { top: 148px; height: 62px; }     /* side button */
#ginphone::after  { top: 96px;  height: 34px; }     /* and above it */

@media (prefers-reduced-motion: reduce) {
  #ginphone { transition: opacity .15s ease; transform: none; }
  #ginphone.gp-open .gp-screen { animation: none; }
}

.gp-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 14px 12px;
  border-bottom: 1px solid var(--gp-line);
  background: var(--gp-panel-2);
  flex: 0 0 auto;
}
.gp-head h3 {
  margin: 0;
  font: 600 14px/1.25 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink);
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gp-head p {
  margin: 1px 0 0;
  font: 400 11.5px/1.3 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gp-head-txt { flex: 1 1 auto; min-width: 0; }
.gp-icon {
  border: 1px solid transparent;
  background: none;
  color: var(--gp-ink-2);
  cursor: pointer;
  border-radius: 9px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  font: 400 17px/1 var(--sans, system-ui, sans-serif);
  flex: 0 0 auto;
  padding: 0;
}
.gp-icon:hover { color: var(--gp-ink); background: var(--gp-line); }
.gp-icon:focus-visible { outline: 2px solid var(--gp-accent); outline-offset: 1px; }

.gp-body { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; }

/* ── the list of conversations ───────────────────────────────────────────── */

.gp-row {
  display: block;
  width: 100%;
  text-align: start;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--gp-line);
  padding: 12px 14px;
  cursor: pointer;
  color: inherit;
}
.gp-row:hover { background: var(--gp-panel-2); }
.gp-row:focus-visible { outline: 2px solid var(--gp-accent); outline-offset: -2px; }
.gp-row-top { display: flex; align-items: baseline; gap: 8px; }
.gp-who {
  font: 600 13px/1.3 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink);
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gp-when { font: 400 11px/1.3 var(--sans, system-ui, sans-serif); color: var(--gp-ink-3); flex: 0 0 auto; }
.gp-where { font: 400 11.5px/1.35 var(--sans, system-ui, sans-serif); color: var(--gp-ink-3); margin: 1px 0 0; }
.gp-last {
  font: 400 12.5px/1.4 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink-2);
  margin: 4px 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.gp-last b { color: var(--gp-ink-3); font-weight: 500; }
.gp-n {
  flex: 0 0 auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--gp-accent);
  color: var(--gp-on-accent);
  font: 600 10.5px/18px var(--sans, system-ui, sans-serif);
  text-align: center;
}

.gp-empty {
  padding: 34px 24px;
  text-align: center;
  color: var(--gp-ink-3);
  font: 400 13px/1.6 var(--sans, system-ui, sans-serif);
}
.gp-empty b { display: block; color: var(--gp-ink-2); font-weight: 600; margin-bottom: 6px; }

/* ── the thread ──────────────────────────────────────────────────────────── */

.gp-msgs { padding: 14px; display: flex; flex-direction: column; gap: 10px; }

/* A MESSAGE ARRIVES, IT DOES NOT APPEAR. The difference between the two is most of what makes a
 * thread feel like a conversation rather than a table that refreshed. It runs on every bubble,
 * so opening a thread deals the history out in order and a message landing mid-conversation
 * does the same thing the rest of them did. 220ms: long enough to read as motion, short enough
 * that nobody is waiting for it. */
.gp-msg { max-width: 84%; animation: gp-land .22s cubic-bezier(.22, .9, .3, 1) both; }
@keyframes gp-land {
  from { opacity: 0; transform: translateY(9px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
/* Hers come from her side, his from his — the direction carries the same information the
 * alignment does, one moment earlier. */
.gp-me  { animation-name: gp-land-right; }
.gp-them { animation-name: gp-land-left; }
@keyframes gp-land-right {
  from { opacity: 0; transform: translate(10px, 7px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@keyframes gp-land-left {
  from { opacity: 0; transform: translate(-10px, 7px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .gp-msg, .gp-me, .gp-them { animation: none; }
}

.gp-msg-b {
  padding: 9px 12px;
  border-radius: 14px;
  font: 400 13px/1.5 var(--sans, system-ui, sans-serif);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.gp-them { align-self: flex-start; }
.gp-them .gp-msg-b {
  background: var(--gp-panel-2);
  color: var(--gp-ink);
  border-bottom-left-radius: 5px;
  border: 1px solid var(--gp-line);
}
.gp-me { align-self: flex-end; }
.gp-me .gp-msg-b {
  background: var(--gp-accent);
  color: var(--gp-on-accent);
  border-bottom-right-radius: 5px;
}
.gp-meta {
  font: 400 10.5px/1.4 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink-3);
  margin: 3px 2px 0;
}
.gp-me .gp-meta { text-align: end; }

/* A consultation opened to the client reads as neither of them talking — because it is not. */
.gp-consult { align-self: stretch; max-width: 100%; }
.gp-consult .gp-msg-b {
  background: none;
  border: 1px dashed var(--gp-line);
  color: var(--gp-ink-2);
  font-style: italic;
}

/* A decision is not a message and must not look like one. */
.gp-verdict { align-self: center; max-width: 100%; }
.gp-verdict .gp-msg-b {
  background: none;
  border: 0;
  padding: 2px 8px;
  font: 500 11.5px/1.5 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink-3);
  text-align: center;
}
.gp-verdict.is-yes .gp-msg-b { color: var(--gp-good); }
.gp-verdict.is-no .gp-msg-b { color: var(--gp-warn); }

/* ── the card that carries one out ───────────────────────────────────────── */

.gp-do {
  margin: 6px 0 2px;
  border: 1px solid var(--gp-line);
  border-radius: 12px;
  background: var(--gp-panel-2);
  padding: 10px 11px;
}
.gp-do p { margin: 0 0 8px; font: 400 11.5px/1.45 var(--sans, system-ui, sans-serif); color: var(--gp-ink-3); }
.gp-do-acts { display: flex; gap: 7px; flex-wrap: wrap; }
.gp-btn {
  border: 1px solid var(--gp-line);
  background: none;
  color: var(--gp-ink-2);
  border-radius: 9px;
  padding: 5px 10px;
  font: 500 11.5px/1.3 var(--sans, system-ui, sans-serif);
  cursor: pointer;
}
.gp-btn:hover { color: var(--gp-ink); background: var(--gp-line); }
.gp-btn:focus-visible { outline: 2px solid var(--gp-accent); outline-offset: 1px; }
.gp-btn[disabled] { opacity: .5; cursor: default; }
.gp-btn-go { background: var(--gp-accent); border-color: transparent; color: var(--gp-on-accent); }
.gp-btn-go:hover { background: var(--gp-accent); filter: brightness(1.08); color: var(--gp-on-accent); }

/* ── the composer ────────────────────────────────────────────────────────── */

.gp-foot[hidden] { display: none; }
.gp-foot {
  flex: 0 0 auto;
  border-top: 1px solid var(--gp-line);
  background: var(--gp-panel-2);
  /* The bottom padding is the home bar's room. Without it the send button sits under the line
   * and the whole thing stops reading as a screen. */
  padding: 10px 10px 26px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.gp-foot-row { display: flex; gap: 8px; align-items: flex-end; }

/* WHAT THIS MESSAGE IS ABOUT. It replaced a whole second floating box, so it has to carry the
 * same meaning in one line: you pointed at a thing, and the next thing you say is about it. */
.gp-subject[hidden] { display: none; }
.gp-subject {
  display: flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  max-width: 100%;
  padding: 5px 5px 5px 10px;
  border-radius: 999px;
  background: var(--gp-line);
  border: 1px solid transparent;
  animation: gp-land .2s cubic-bezier(.22, .9, .3, 1) both;
}
.gp-subject-t {
  font: 500 11.5px/1.3 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gp-subject-x {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  border: 0; border-radius: 50%;
  background: none;
  color: var(--gp-ink-3);
  cursor: pointer;
  font: 400 14px/1 var(--sans, system-ui, sans-serif);
  display: grid; place-items: center;
  padding: 0;
}
.gp-subject-x:hover { background: var(--gp-panel); color: var(--gp-ink); }
.gp-subject-x:focus-visible { outline: 2px solid var(--gp-accent); outline-offset: 1px; }
.gp-foot textarea {
  flex: 1 1 auto;
  resize: none;
  min-height: 38px;
  max-height: 120px;
  border-radius: 11px;
  border: 1px solid var(--gp-line);
  background: var(--gp-panel);
  color: var(--gp-ink);
  padding: 9px 11px;
  font: 400 13px/1.45 var(--sans, system-ui, sans-serif);
}
.gp-foot textarea:focus-visible { outline: 2px solid var(--gp-accent); outline-offset: -1px; }
.gp-send {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 11px;
  border: 0;
  background: var(--gp-accent);
  color: var(--gp-on-accent);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
}
.gp-send[disabled] { opacity: .45; cursor: default; }
.gp-send:not([disabled]):active { transform: scale(.92); }
.gp-send { transition: transform .12s ease, opacity .12s ease; }
.gp-send svg { width: 17px; height: 17px; }

/* The sentence that says what kind of room this is. It is not decoration: the link used to hide
 * every name from everyone holding it, and now it does not. */
.gp-room[hidden] { display: none; }
.gp-room {
  padding: 8px 14px;
  border-bottom: 1px solid var(--gp-line);
  font: 400 11px/1.45 var(--sans, system-ui, sans-serif);
  color: var(--gp-ink-3);
  background: var(--gp-panel-2);
}

/* ── ON AN ACTUAL PHONE, DO NOT DRAW ONE ───────────────────────────────────
 *
 * A telephone rendered inside a telephone is a joke at the owner's expense, and it costs the
 * only thing that is scarce on that screen, which is room. So the body, the island, the status
 * bar and the home bar all come off, and what is left is the conversation, full-bleed. The
 * device was always a way of saying "this is a message, not a form" — on a phone that is
 * already obvious. */
@media (max-width: 560px) {
  #ginphone {
    right: 8px;
    left: 8px;
    bottom: 8px;
    width: auto;
    height: min(82vh, calc(100vh - 16px));
    padding: 0;
    border-radius: 22px;
    background: var(--gp-panel);
    box-shadow: var(--gp-shadow);
    transform-origin: 85% 110%;
  }
  #ginphone::before, #ginphone::after { display: none; }
  .gp-island, .gp-status, .gp-home, .gp-glass { display: none; }
  .gp-screen { border-radius: 22px; box-shadow: none; }
  .gp-foot { padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px)); }
  #ginphone-fab { right: 16px; bottom: 84px; }
}

/* ── the two controls that live OUTSIDE the handset ──────────────────────────
 *
 * .gp-fwd sits in the studio conversation, not in the phone, so it cannot read the --gp-*
 * variables above — those are declared on #ginphone and #ginphone-fab. It only ever appears in
 * the studio, which has its own tokens, so it uses those directly. */

.gp-fwd {
  position: absolute;
  top: 2px;
  right: 26px;                     /* beside Copy, which owns the corner */
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  opacity: 0;
  font: 500 14px/1 var(--sans, system-ui, sans-serif);
  display: grid;
  place-items: center;
  transition: opacity .14s ease;
  padding: 0;
}
.dz-turn.bot:hover .gp-fwd,
.gp-fwd:focus-visible { opacity: .65; }
.gp-fwd:hover { opacity: 1; color: var(--text); background: rgba(124, 156, 255, .22); }
.gp-fwd[disabled] { opacity: .9; }
/* THE CLASS ARRIVES AFTER THE TURN DOES. The handle is built the moment a turn appears and
 * `dz-failed` is added later, so the check in JS at build time cannot see it. CSS can, whenever
 * it lands. The click refuses as well — this is the half that stops it being offered. */
.dz-turn.dz-failed .gp-fwd { display: none; }

/* The consultation switch. Lit means the door is open, which is a thing she should be able to
 * see at a glance without reading a tooltip. */
.gp-watch.is-on {
  color: var(--gp-on-accent);
  background: var(--gp-accent);
}
.gp-watch.is-on:hover { color: var(--gp-on-accent); background: var(--gp-accent); filter: brightness(1.08); }
