/* tools/web/site.css — the landing page and the player pages (tools/web.ts). */

:root {
  color-scheme: dark;
  --bg: #0d0f14;
  --panel: #151922;
  --line: #262c38;
  --text: #dfe4ec;
  --muted: #8d97a8;
  --accent: #f4c35a;
  --accent-ink: #1b1505;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.5;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: #ffd98a; }

h1, h2 { line-height: 1.2; }

kbd {
  display: inline-block;
  min-width: 1.9em;
  padding: 2px 6px;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: #1c212b;
  color: var(--text);
  font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  text-align: center;
  white-space: nowrap;
}

/* Pixel art: nearest-neighbour scaling for the previews and the game. */
.shot img,
.stage canvas {
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}

table.controls { border-collapse: collapse; }
table.controls th {
  padding: 3px 14px 3px 0;
  font-weight: normal;
  text-align: left;
  vertical-align: top;
  white-space: nowrap;
}
table.controls td { padding: 4px 0; color: var(--muted); }
.pointer-key { font-size: 13px; color: var(--text); }

.site-footer {
  max-width: 1040px;
  margin: 32px auto 0;
  padding: 16px 16px 32px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 13px;
}

/* ---- landing ------------------------------------------------------------ */

.landing .site-header,
.landing .games {
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 16px;
}

.landing .site-header { padding-top: 40px; padding-bottom: 12px; }
.landing h1 { margin: 0 0 8px; font-size: 28px; letter-spacing: 0.01em; }
.landing .intro { max-width: 640px; margin: 0; color: var(--muted); }
.landing .links { margin: 8px 0 0; }
.landing .elsewhere { color: var(--muted); font-size: 13px; margin-left: 6px; }


.game-card {
  display: grid;
  grid-template-columns: 480px 1fr;
  gap: 24px;
  align-items: start;
  padding: 24px 0;
  border-top: 1px solid var(--line);
}
.game-card:first-child { margin-top: 16px; }

.shot { text-decoration: none; }

.shot img {
  display: block;
  width: 480px;
  height: auto;
  background: #000;
  border-radius: 3px;
  box-shadow: 0 0 0 1px var(--line);
}

/* A game without a preview image yet. */
.no-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 480px;
  max-width: 100%;
  aspect-ratio: 480 / 272;
  padding: 16px;
  border-radius: 3px;
  background: repeating-linear-gradient(45deg, #11141b 0 8px, #151922 8px 16px);
  box-shadow: 0 0 0 1px var(--line);
  color: var(--muted);
  font-size: 18px;
  text-align: center;
}

.card-body h2 { margin: 0 0 6px; font-size: 20px; }
.card-body h2 a { color: var(--text); text-decoration: none; }
.card-body h2 a:hover { color: var(--accent); }
.card-body .description { margin: 0 0 12px; }
.card-body table.controls { font-size: 13px; }

.play {
  display: inline-block;
  margin-top: 4px;
  padding: 7px 14px;
  border-radius: 4px;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: none;
}
.play:hover { background: #ffd98a; color: var(--accent-ink); }

/* Landing page chapter lists: a compact disclosure, collapsed by default,
   whose chips wrap instead of a long vertical link list (tools/web.ts). */
.chapters {
  margin: 12px 0 0;
  font-size: 13px;
}
.chapters > summary {
  cursor: pointer;
  color: var(--muted);
  user-select: none;
  -webkit-user-select: none;
}
.chapters > summary:hover { color: var(--accent); }
.chapter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}
.chapter-chips a {
  display: inline-block;
  max-width: 100%;
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--text);
  font-size: 12px;
  line-height: 1.4;
  text-decoration: none;
  overflow-wrap: anywhere;
}
.chapter-chips a:hover { border-color: var(--accent); color: var(--accent); }

/* Nothing on the page should force a horizontal scrollbar on a phone:
   media stays inside its column, and long unbreakable tokens wrap. */
img, video, canvas { max-width: 100%; }
.card-body .description,
.controls td,
.info .description {
  overflow-wrap: anywhere;
}

@media (max-width: 860px) {
  .game-card { grid-template-columns: 1fr; gap: 14px; }
  .shot img { width: 100%; max-width: 480px; }
}
/* Below 1x a nearest-neighbour preview drops whole rows; smooth it instead. */
@media (max-width: 511px) {
  .shot img { image-rendering: auto; }
}

/* ---- player ------------------------------------------------------------- */

.bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 18px;
  padding: 12px 16px;
}
.bar h1 { margin: 0; font-size: 18px; }
.back { font-size: 14px; }

.bar-button {
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.bar-button:hover { border-color: var(--accent); color: var(--accent); }
.bar-button[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

/* Character-name box beside the sign-in controls (games that declare auth).
   Hidden until the game opens its character-creation screen. */
.auth-name {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}
.auth-name[hidden] { display: none; }
.auth-name input {
  width: 14em;
  max-width: 60vw;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
}
.auth-name input:focus { outline: none; border-color: var(--accent); }
.auth-name input::placeholder { color: var(--muted); }
.auth-name-error { color: var(--accent); }
.auth-name-error[hidden] { display: none; }

/* Invite-link box beside the sign-in controls (multiplayer games). Hidden
   until the game mints a realm invite; the input holds the shareable URL. */
.auth-invite {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}
.auth-invite[hidden] { display: none; }
.auth-invite input {
  width: 24em;
  max-width: 60vw;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
}
.auth-invite input:focus { outline: none; border-color: var(--accent); }
.auth-invite-hint { flex-basis: 100%; color: var(--muted); }
.auth-invite-hint[hidden] { display: none; }

.audio-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  color: var(--muted);
  font-size: 13px;
}
.audio-controls button {
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.audio-controls button[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
}
.audio-controls input { width: 112px; accent-color: var(--accent); }
.audio-controls output { min-width: 3.2em; color: var(--text); text-align: right; }

.screen-area {
  display: flex;
  justify-content: center;
  padding: 0 16px;
}

/* The screen and its touch controls stay together in normal flow (screen,
   then the pad right below it on touch devices) and become the fixed
   fullscreen surface in immersive mode (body.immersive, player.js). */
.play-surface {
  display: flex;
  flex-direction: column;
}

/* tools/web/player.js sets the exact size: a whole number of device pixels
   per game pixel. Until then, 2x. */
.stage {
  position: relative;
  width: 960px;
  max-width: 100%;
  background: #000;
  outline: none;
  box-shadow: 0 0 0 1px var(--line);
}
.stage[data-focused="true"] { box-shadow: 0 0 0 1px var(--accent); }

.stage canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
  background: rgba(8, 9, 12, 0.78);
  text-align: center;
}
.overlay[hidden] { display: none; }
.overlay p { margin: 0; max-width: 36em; }
.stage[data-state="error"] .overlay p { color: #ffb4a8; }
.overlay button {
  padding: 6px 14px;
  border: 0;
  border-radius: 4px;
  background: var(--accent);
  color: var(--accent-ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.focus-hint {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  padding: 5px 12px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: rgba(13, 15, 20, 0.88);
  font-size: 13px;
  white-space: nowrap;
  pointer-events: none;
}
.focus-hint[hidden] { display: none; }

/* ?embed (tools/web/player.js): only the game screen, centred in the
   window, for a page that frames the player. */
body.embedded { background: #000; overflow: hidden; }
body.embedded .bar,
body.embedded .caption,
body.embedded .pad,
body.embedded .info,
body.embedded .demo-controls,
body.embedded .site-footer { display: none; }
body.embedded main { display: flex; align-items: center; justify-content: center; height: 100vh; }
body.embedded .play-surface { display: contents; }
body.embedded .screen-area { width: 100%; padding: 0; }
body.embedded .stage { box-shadow: none; }

.caption {
  margin: 10px auto 0;
  padding: 0 16px;
  max-width: 720px;
  color: var(--muted);
  font-size: 13px;
  text-align: center;
}

.editor-tools {
  max-width: 960px;
  margin: 0 auto 14px;
  padding: 0 16px;
  text-align: center;
}
.editor-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.editor-actions button {
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.editor-actions button:hover { border-color: var(--accent); color: var(--accent); }
.editor-actions #editor-download { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
.editor-actions button:disabled {
  border-color: var(--line);
  color: var(--muted);
  cursor: wait;
  opacity: .6;
}
.editor-status,
.editor-privacy {
  margin: 7px 0 0;
  font-size: 13px;
  overflow-wrap: anywhere;
}
.editor-status { color: var(--muted); }
.editor-status.error { color: #ffb4a8; }
.editor-privacy { color: var(--accent); }

.demo-controls {
  max-width: 720px;
  margin: 16px auto 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
}
.demo-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}
.demo-head h2 { margin: 0; font-size: 16px; }
.demo-toggle {
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: #1c212b;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.demo-toggle:hover { border-color: var(--accent); color: #ffd98a; }
.demo-toggle[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent);
}
.demo-body[hidden] { display: none; }
.demo-control-row {
  display: grid;
  grid-template-columns: 76px 1fr;
  gap: 10px;
  align-items: start;
}
.demo-control-row + .demo-control-row { margin-top: 9px; }
.demo-control-row > span { padding-top: 5px; color: var(--muted); font-size: 13px; }
.demo-buttons { display: flex; flex-wrap: wrap; gap: 6px; }
.demo-chapter-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
}
.demo-button {
  display: inline-block;
  padding: 4px 9px;
  border: 1px solid #3a4352;
  border-radius: 4px;
  background: #1c212b;
  color: var(--text);
  font-size: 13px;
  text-decoration: none;
  white-space: normal;
  overflow-wrap: anywhere;
}
.demo-button:hover { border-color: var(--accent); color: #ffd98a; }
.demo-button.active {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--accent-ink);
}
.demo-chapter-card {
  display: flex;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  flex-direction: column;
  text-align: left;
}
.demo-chapter-preview {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #090b10;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}
.demo-chapter-copy {
  display: flex;
  padding: 8px 10px 9px;
  flex: 1;
  flex-direction: column;
  gap: 3px;
}
.demo-chapter-title { font-weight: 650; overflow-wrap: anywhere; }
.demo-chapter-description {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.demo-chapter-card.active .demo-chapter-description { color: #463a21; }
.demo-speed { min-width: 42px; text-align: center; }
.demo-help { margin: 9px 0 0; color: var(--muted); font-size: 12px; }

@media (max-width: 520px) {
  .demo-control-row { grid-template-columns: 1fr; gap: 4px; }
  .demo-control-row > span { padding-top: 0; }
  .demo-chapter-cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}

.editor-tools {
  max-width: 960px;
  margin: 0 auto 14px;
  padding: 0 16px;
  text-align: center;
}
.editor-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.editor-actions button {
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.editor-actions button:hover { border-color: var(--accent); color: var(--accent); }
.editor-actions #editor-download { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
.editor-actions button:disabled {
  border-color: var(--line);
  color: var(--muted);
  cursor: wait;
  opacity: .6;
}
.editor-status,
.editor-privacy { margin: 7px 0 0; font-size: 13px; }
.editor-status { color: var(--muted); }
.editor-status.error { color: #ffb4a8; }
.editor-privacy { color: var(--accent); }

.info {
  max-width: 720px;
  margin: 20px auto 0;
  padding: 0 16px;
}
.info .description { margin: 0 0 16px; }
.info h2 { margin: 0 0 8px; font-size: 16px; }
.info .features {
  margin: 0 0 16px;
  padding: 0;
  list-style: none;
  color: var(--muted);
}
.info .features li + li { margin-top: 4px; }

.noscript { text-align: center; color: #ffb4a8; }

/* On-screen buttons, only where there is no hovering mouse. */
.pad {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  max-width: 520px;
  margin: 14px auto 0;
  padding: 0 16px;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
@media (hover: hover) and (pointer: fine) {
  .pad { display: none; }
}
@media (hover: none) and (pointer: coarse) {
  .caption { display: none; }
}
.pad button {
  min-width: 48px;
  height: 48px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  color: var(--text);
  font: 600 16px/1 system-ui, sans-serif;
  touch-action: none;
}
.pad button.held { background: var(--accent); color: var(--accent-ink); }
.dpad {
  display: grid;
  grid-template-columns: repeat(3, 48px);
  grid-template-rows: repeat(3, 48px);
  gap: 4px;
}
.dpad .up { grid-area: 1 / 2; }
.dpad .left { grid-area: 2 / 1; }
.dpad .right { grid-area: 2 / 3; }
.dpad .down { grid-area: 3 / 2; }
.pad .actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  max-width: 220px;
}
.pad .actions button { border-radius: 24px; padding: 0 12px; }
.pad .pad-select, .pad .pad-start { font-size: 12px; height: 44px; }

/* ---- immersive (fullscreen play) ----------------------------------------
   body.immersive is added by tools/web/player.js when the Fullscreen button
   is pressed. On browsers with the Fullscreen API the play surface itself is
   the fullscreen element; everywhere else (iPhone Safari) the same class
   drives this CSS fallback: a fixed surface over 100dvh/100dvw that respects
   the safe-area insets on every side, with the page chrome hidden. */
body.immersive {
  overflow: hidden;
  overscroll-behavior: none;
}
body.immersive .bar,
body.immersive .caption,
body.immersive .info,
body.immersive .demo-controls,
body.immersive .site-footer,
body.immersive .editor-tools,
body.immersive noscript { display: none; }

body.immersive .play-surface {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  width: 100dvw;
  height: 100dvh;
  z-index: 10;
  background: var(--bg);
  padding:
    env(safe-area-inset-top)
    env(safe-area-inset-right)
    env(safe-area-inset-bottom)
    env(safe-area-inset-left);
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
body.immersive .screen-area {
  width: 100%;
  height: 100%;
  padding: 0;
  /* The stage is sized by fit.ts to the largest whole-pixel scale; centre
     it both ways so the handheld layout keeps it off the pad corners. */
  align-items: center;
}
body.immersive .pad {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-width: none;
  margin: 0;
  padding:
    0
    max(12px, env(safe-area-inset-right))
    max(10px, env(safe-area-inset-bottom))
    max(12px, env(safe-area-inset-left));
  align-items: flex-end;
}

/* Landscape immersive: the pad floats OVER the maximised screen. The
   container receives no touch (only the buttons do), so taps on the game
   picture between the buttons reach the game. The two clusters are centred
   vertically at the screen edges, clear of both the top status plate and the
   bottom HUD strips. Buttons rest at a light translucent opacity and turn
   solid while held. Portrait immersive is untouched. */
@media (orientation: landscape) {
  body.immersive .pad { align-items: center; pointer-events: none; }
  /* Three 48px columns keep the action cluster against the right edge;
     four columns would intrude into the middle of an 844px phone screen. */
  body.immersive .pad .actions { max-width: 164px; }
  body.immersive .pad button {
    pointer-events: auto;
    opacity: 0.38;
    border-color: rgba(223, 228, 236, 0.55);
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  }
  body.immersive .pad button.held {
    opacity: 1;
    border-color: var(--accent);
    background: var(--accent);
    color: var(--accent-ink);
    text-shadow: none;
  }
  body.immersive .pad-toggle { display: block; }
  /* Hidden: the pad is gone and the toggle shrinks to a small translucent
     "show" button in the corner. */
  body.immersive.pad-hidden .pad { display: none; }
  body.immersive.pad-hidden .pad-toggle {
    padding: 3px 9px;
    font-size: 11px;
    opacity: 0.45;
  }
}

/* The corner tools of immersive play: "exit fullscreen" and (landscape
   only) the "hide buttons" toggle. Only the buttons receive touch; the
   container itself lets taps fall through to the game. */
.immersive-tools {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top));
  right: calc(8px + env(safe-area-inset-right));
  z-index: 2;
  display: flex;
  gap: 8px;
  pointer-events: none;
}
.immersive-tools > button {
  pointer-events: auto;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.immersive-tools > button:hover { border-color: var(--accent); color: var(--accent); }
.immersive-tools > button[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

/* The pad toggle stays hidden until landscape immersive play; portrait
   immersive keeps its unchanged bottom-row pad. */
.pad-toggle { display: none; }

/* Shown only while the device is portrait in immersive mode; the layout
   still plays portrait, this is a dismissible suggestion. */
.rotate-hint {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top));
  left: 50%;
  z-index: 2;
  display: none;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 24px);
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(13, 15, 20, 0.92);
  font-size: 13px;
  transform: translateX(-50%);
  white-space: normal;
}
.rotate-hint p { margin: 0; }
.rotate-hint button {
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: #1c212b;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
@media (orientation: portrait) {
  body.immersive .rotate-hint:not([hidden]) { display: flex; }
}

/* Touch targets in the page chrome follow the 44 CSS-pixel mobile floor.
   This covers auth/name/invite controls and the always-visible immersive
   escape hatch; the game pad already uses 48px controls. */
@media (hover: none) and (pointer: coarse) {
  .bar { align-items: center; gap: 8px 12px; }
  .bar-button,
  .auth-name input,
  .auth-invite input,
  .audio-controls button,
  .lang-switch .lang-button,
  .overlay button,
  .immersive-tools > button,
  .rotate-hint button {
    min-height: 44px;
  }
  .auth-name,
  .auth-invite { align-items: center; }
}

/* ---- player page language switch ----------------------------------------
   A game that declares languages in web.json gets a switcher in the bar.
   The inline script (tools/web/i18n.ts) resolves the language and swaps the
   page chrome; <html data-page-lang="pending"> keeps the body hidden until
   it ran, so an English page never flashes before a Chinese one. */
html[data-page-lang="pending"] body { visibility: hidden; }

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.lang-switch .lang-button {
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  white-space: normal;
  overflow-wrap: anywhere;
}
.lang-switch .lang-button:hover { border-color: var(--accent); color: var(--accent); }
.lang-switch .lang-button.active,
.lang-switch .lang-button[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

/* Chapters/autoplay unavailable in the active language (tapes recorded in
   another): the inline switcher fills this notice and disables the cards. */
.demo-chapters-notice {
  margin: 9px 0 0;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: #1c212b;
  color: var(--muted);
  font-size: 12px;
  overflow-wrap: anywhere;
}
.demo-chapters-notice[hidden] { display: none; }
.demo-button.is-disabled {
  opacity: .5;
  pointer-events: none;
}
