/* Pulse card frame — founder-approved Kaira film shell, 8 Sep 2026.
   Shared by the React app and sandboxed game documents. No overlay/pseudo-element
   is used: native video controls, sheet grabbers and game input stay reachable. */
:root {
  --pulse-frame-ground: #02060d;
  --pulse-frame-rim: linear-gradient(140deg, rgba(125,207,255,.65), rgba(86,127,184,.12) 34%, rgba(146,95,213,.22) 64%, rgba(0,237,255,.58));
  --pulse-frame-inner: rgba(255,255,255,.14);
  --pulse-frame-shadow: 0 12px 36px rgba(0,0,0,.45), 0 0 26px rgba(8,123,199,.10), inset 0 0 0 1px var(--pulse-frame-inner);
  --pulse-frame-radius: 20px;
  --pulse-frame-highlight: 0 12px 36px rgba(0,0,0,.45), 0 0 24px rgba(255,255,255,.22), 0 0 0 1px rgba(255,255,255,.38), inset 0 0 0 1px rgba(255,255,255,.48);
}

/* Explicit outer surfaces only. Selection chips, price bars and table rows keep
   their semantic states. Existing sizes, padding, positions and motion remain. */
:is(.pulse-card-frame, .neon-card, .hh2-feature,
    .pkg-surface, .pkg-run-card, .pkg-exp-card, .races-m-card, .race-card,
    .social-call-card, .social-play-card, .social-suggestion,
    .sf-item, .sp-post, .sp-pred, .lb-mobile__podium-player, .lb-mobile__mine),
.pw-world :is(.pw-single, .pw-game-card, .pw-package, .pw-story, .pw-film),
html[data-live-game] :is(.glass.setup-sheet, .glass.live-sheet, .glass.landed-sheet,
    .glass.next-sheet, .glass.call-sheet, .sheet.setup-sheet, .sheet.live-sheet,
    .sheet.result-sheet, .glass-sheet, .pulse-result, .setup-card, .drawer-card,
    .race-drawer-sheet, .ride-asset-sheet, .ride-control-sheet, .call-history-sheet) {
  transition: box-shadow 160ms ease;
  box-sizing: border-box;
  border: 2px solid transparent !important;
  border-radius: var(--pulse-frame-radius) !important;
  background: linear-gradient(var(--pulse-frame-ground), var(--pulse-frame-ground)) padding-box,
              var(--pulse-frame-rim) border-box !important;
  box-shadow: var(--pulse-frame-shadow) !important;
}

/* The discovery deck carries the heavier film rim from the reference photo.
   Border-box preserves equal card bounds and the single-screen mobile layout. */
.pw-world :is(.pw-single, .pw-game-card, .pw-package, .pw-story) {
  border-width: 5px !important;
  --pulse-frame-radius: 24px;
}
.pw-world .pw-film {
  border-width: 3px !important;
  --pulse-frame-radius: 20px;
}
.pw-film video { border-radius: 16px; background: #000; }

@media (max-width: 860px) and (max-height: 740px) {
  .pw-world :is(.pw-single, .pw-game-card, .pw-package, .pw-story) {
    border-width: 3px !important;
    --pulse-frame-radius: 20px;
  }
}
@media (forced-colors: active) {
  :is(.pulse-card-frame, .neon-card),
  .pw-world :is(.pw-single, .pw-game-card, .pw-package, .pw-story, .pw-film) {
    border-color: CanvasText !important;
  }
}

/* White response light: hover on a mouse; press or keyboard focus on any device.
   No overlay and no scaling, so video controls and carousel swipes stay intact.
   8 Oct 2026 PT: a Home Featured card (.hh2-feature) presses on `data-pressed`,
   not `:active` (rule below). iOS Safari holds :active for the whole of a touch
   that turns into a swipe, so every swipe of the Featured rail lit a 36px +
   24px glow around a moving 3D card and dropped it on landing (Justin: "the
   cards are still glitchy"). The rail's 130 ms press delay
   (src/utils/useRailPressDelay.js, the iOS COVERFLOW_PRESS_DELAY_MS) sets
   data-pressed only on a touch that stays a press. */
:is(.pulse-card-frame, .neon-card,
  .pkg-surface, .pkg-run-card, .pkg-exp-card, .races-m-card, .race-card,
  .social-call-card, .social-play-card, .social-suggestion, .sf-item, .sp-post,
  .sp-pred, .lb-mobile__podium-player, .lb-mobile__mine,
  .pw-world .pw-single, .pw-world .pw-game-card, .pw-world .pw-package,
  .pw-world .pw-story, .pw-world .pw-film,
  html[data-live-game] .glass.setup-sheet, html[data-live-game] .glass.live-sheet,
  html[data-live-game] .glass.landed-sheet, html[data-live-game] .glass.next-sheet,
  html[data-live-game] .glass.call-sheet, html[data-live-game] .sheet.setup-sheet,
  html[data-live-game] .sheet.live-sheet, html[data-live-game] .sheet.result-sheet,
  html[data-live-game] .glass-sheet, html[data-live-game] .pulse-result,
  html[data-live-game] .setup-card, html[data-live-game] .drawer-card,
  html[data-live-game] .race-drawer-sheet, html[data-live-game] .ride-asset-sheet,
  html[data-live-game] .ride-control-sheet, html[data-live-game] .call-history-sheet):is(:active, :focus-visible, :has(:focus-visible)) {
  box-shadow: var(--pulse-frame-highlight) !important;
}
.hh2-feature:is([data-pressed], :focus-visible, :has(:focus-visible)) {
  box-shadow: var(--pulse-frame-highlight) !important;
}
@media (hover: hover) {
  :is(.pulse-card-frame, .neon-card, .hh2-feature,
  .pkg-surface, .pkg-run-card, .pkg-exp-card, .races-m-card, .race-card,
  .social-call-card, .social-play-card, .social-suggestion, .sf-item, .sp-post,
  .sp-pred, .lb-mobile__podium-player, .lb-mobile__mine,
  .pw-world .pw-single, .pw-world .pw-game-card, .pw-world .pw-package,
  .pw-world .pw-story, .pw-world .pw-film,
  html[data-live-game] .glass.setup-sheet, html[data-live-game] .glass.live-sheet,
  html[data-live-game] .glass.landed-sheet, html[data-live-game] .glass.next-sheet,
  html[data-live-game] .glass.call-sheet, html[data-live-game] .sheet.setup-sheet,
  html[data-live-game] .sheet.live-sheet, html[data-live-game] .sheet.result-sheet,
  html[data-live-game] .glass-sheet, html[data-live-game] .pulse-result,
  html[data-live-game] .setup-card, html[data-live-game] .drawer-card,
  html[data-live-game] .race-drawer-sheet, html[data-live-game] .ride-asset-sheet,
  html[data-live-game] .ride-control-sheet, html[data-live-game] .call-history-sheet):hover {
    box-shadow: var(--pulse-frame-highlight) !important;
  }
}
@media (prefers-reduced-motion: reduce) {
  :is(.pulse-card-frame, .neon-card, .hh2-feature,
  .pkg-surface, .pkg-run-card, .pkg-exp-card, .races-m-card, .race-card,
  .social-call-card, .social-play-card, .social-suggestion, .sf-item, .sp-post,
  .sp-pred, .lb-mobile__podium-player, .lb-mobile__mine,
  .pw-world .pw-single, .pw-world .pw-game-card, .pw-world .pw-package,
  .pw-world .pw-story, .pw-world .pw-film,
  html[data-live-game] .glass.setup-sheet, html[data-live-game] .glass.live-sheet,
  html[data-live-game] .glass.landed-sheet, html[data-live-game] .glass.next-sheet,
  html[data-live-game] .glass.call-sheet, html[data-live-game] .sheet.setup-sheet,
  html[data-live-game] .sheet.live-sheet, html[data-live-game] .sheet.result-sheet,
  html[data-live-game] .glass-sheet, html[data-live-game] .pulse-result,
  html[data-live-game] .setup-card, html[data-live-game] .drawer-card,
  html[data-live-game] .race-drawer-sheet, html[data-live-game] .ride-asset-sheet,
  html[data-live-game] .ride-control-sheet, html[data-live-game] .call-history-sheet) { transition: none; }
}

/* ── THE OBSIDIAN FACE ON THE DESKTOP SHELL (desktop revamp phase 4, 26 Sep 2026) ──
   The phone defines these under html[data-pulse-obsidian-preview="true"] at
   767px and below (src/styles/obsidian-mobile-preview.css). The desktop system
   makes the same face the platform's card face (DESKTOP-SYSTEM.md §4), so the
   shell carries the identical values; a desktop stylesheet reads var(--ob-*)
   exactly as the phone's does. Same numbers, one source per width. */
body.pulse-shell-on {
  --ob-ground: #030405;
  --ob-ink: #f5f7fa;
  --ob-muted: #a6adb5;
  --ob-line: #ffffff20;
  --ob-edge: #ffffff45;
  --ob-face: radial-gradient(ellipse at 38% -55%, #ffffff45, transparent 60%), linear-gradient(165deg, #252a2f 0%, #101317 15%, #050608 60%, #11151a 100%);
  --ob-selected: radial-gradient(ellipse at 38% -55%, #ffffffa3, transparent 60%), linear-gradient(155deg, #3b4248 0%, #171b20 32%, #060709 100%);
  --ob-shadow: inset 0 1px 0 #ffffffa3, inset 1px 0 0 #ffffff24, inset 0 -1px 0 #ffffff1f, 0 10px 26px #00000066;
  --ob-selected-shadow: inset 0 1px 0 #ffffffcc, inset 0 0 0 1px #ffffff52, 0 0 0 1px #ffffff70, 0 8px 24px #00000070, 0 0 18px #d6efff2b;
  --ob-press: var(--pulse-frame-highlight);
}


/* Liquid chrome controls — 9 Oct 2026, decisions ledger §186.
   Material only: authored dimensions, action logic, charts and directional
   green/red remain owned by their existing components. Shared with iframes. */
:root {
  --pulse-metal-face: linear-gradient(178deg, #fcfdff 0%, #a8adb5 3%, #505761 10%, #737a83 17%, #bdc2c9 28%, #e2e5e9 43%, #d3d7dd 62%, #b8bec6 75%, #626a75 90%, #343b46 96%, #cbd0d8 100%);
  --pulse-metal-ink: #101318;
  --pulse-metal-rim: #bfc5ce;
  --pulse-metal-shadow: inset 0 1px 0 #ffffff, inset 1px 0 0 #ffffff66, inset -1px 0 0 #ffffff30, inset 0 -2px 1px #151a23cc, 0 3px 6px #00000080, 0 0 12px #ffffff16;
  --pulse-glass-face: linear-gradient(165deg, #333a43 0%, #13171d 14%, #050608 45%, #0c1015 86%, #252c35 100%);
  --pulse-glass-ink: #f5f7fa;
  --pulse-glass-rim: #9099a6;
  --pulse-glass-shadow: inset 0 1px 0 #edf1f5b3, inset 1px 0 0 #ffffff24, inset 0 -1px 0 #ffffff38, 0 3px 8px #00000070;
  --pulse-control-hover-shadow: inset 0 1px 0 #ffffff, inset 0 -2px 1px #151a23cc, 0 3px 6px #00000080, 0 0 15px #ffffff35;
  --pulse-control-press-shadow: inset 0 2px 3px #11151a80, inset 0 -1px 0 #ffffff80, 0 1px 2px #00000080;
  --pulse-control-focus: #f0f3f7;
  --pulse-control-disabled-face: linear-gradient(180deg, #323941, #1b2027);
  --pulse-control-disabled-ink: #b7bfc9;
}

/* Explicit primary roles. The long-form profile selector is intentional: its
   mobile override used to replace the primary face without its dark label. */
:root :is(.pulse-chrome-primary, .pw-primary, .neon-button-cyan,
    html[data-pulse-obsidian-preview="true"] .sp-page .sp-actions .neon-button.neon-button-cyan,
    html[data-pulse-obsidian-preview="true"] .hh2 .hh2-deposit-cta,
    .hh2-deposit-cta, .pulse-recovery__primary,
    html[data-live-game] .primary:not(.pulse-slide), html[data-live-game] .primary-action:not(.is-quiet),
    html[data-live-game] .share-primary, html[data-live-game] .control-done) {
  --pulse-role-face: var(--pulse-metal-face);
  --pulse-role-ink: var(--pulse-metal-ink);
  --pulse-role-rim: var(--pulse-metal-rim);
  --pulse-role-shadow: var(--pulse-metal-shadow);
  background: var(--pulse-control-face, var(--pulse-role-face)) !important;
  color: var(--pulse-control-ink, var(--pulse-role-ink)) !important;
  border-color: var(--pulse-control-rim, var(--pulse-role-rim)) !important;
  box-shadow: var(--pulse-control-shadow, var(--pulse-role-shadow)) !important;
  text-shadow: none !important; transform: none !important;
  transition: var(--pulse-control-transition, box-shadow 180ms ease, border-color 180ms ease) !important;
}

/* Secondary actions and selected navigation use the same black-glass family.
   Never match all aria-pressed controls: Higher/Lower has semantic colours. */
:root :is(.pulse-chrome-secondary, .pw-secondary, .pw-panel-action,
    .game-setup-card .setup-duration-option[aria-pressed="true"],
    .game-setup-card :is(.setup-quick-fill,.setup-asset-category,.setup-asset-option).is-selected,
    html[data-pulse-obsidian-preview="true"] .hh2 .hh2-chip[aria-pressed="true"],
    html[data-pulse-obsidian-preview="true"] :is(.hh2-tabs,.pshell-rail,.sp-tabs) > button:is([aria-selected="true"],[aria-pressed="true"]),
    .dg-tabs button[aria-selected="true"],
    html[data-live-game] .secondary-action,
    html[data-live-game] :is(.entry-presets,.settings-presets,.quick) button[aria-pressed="true"],
    html[data-live-game] .choice.is-active:not(:is(.is-up,.is-down,[data-direction],[data-draft-direction])),
    html[data-live-game] .drawer-option.selected,
    html[data-live-game] .auto-cashout button.selected,
    html[data-live-game] .amount-quick button.selected) {
  --pulse-role-face: var(--pulse-glass-face);
  --pulse-role-ink: var(--pulse-glass-ink);
  --pulse-role-rim: var(--pulse-glass-rim);
  --pulse-role-shadow: var(--pulse-glass-shadow);
  background: var(--pulse-control-face, var(--pulse-role-face)) !important;
  color: var(--pulse-control-ink, var(--pulse-role-ink)) !important;
  border-color: var(--pulse-control-rim, var(--pulse-role-rim)) !important;
  box-shadow: var(--pulse-control-shadow, var(--pulse-role-shadow)) !important;
  text-shadow: none !important; transform: none !important;
  transition: var(--pulse-control-transition, box-shadow 180ms ease, border-color 180ms ease) !important;
}
.pw-world .pw-tabs button[aria-selected="true"]::before {
  background: var(--pulse-glass-face);
  box-shadow: var(--pulse-glass-shadow), inset 0 0 0 1px var(--pulse-glass-rim);
}

/* Shared action state selectors are deliberately explicit as well. Lower
   bevel on press, no size change, no repeating shimmer or ambient animation. */
:is(.pulse-chrome-primary,.pulse-chrome-secondary,.pw-primary,.pw-secondary,.pw-panel-action,.neon-button-cyan,.hh2-deposit-cta,.pulse-recovery__primary,
    html[data-live-game] .primary:not(.pulse-slide),html[data-live-game] .primary-action:not(.is-quiet),html[data-live-game] .share-primary,html[data-live-game] .control-done,html[data-live-game] .secondary-action):focus-visible {
  outline: 2px solid var(--pulse-control-focus) !important; outline-offset: 3px;
}
:is(.pulse-chrome-primary,.pulse-chrome-secondary,.pw-primary,.pw-secondary,.pw-panel-action,.neon-button-cyan,.hh2-deposit-cta,.pulse-recovery__primary,
    html[data-live-game] .primary:not(.pulse-slide),html[data-live-game] .primary-action:not(.is-quiet),html[data-live-game] .share-primary,html[data-live-game] .control-done,html[data-live-game] .secondary-action):active:not(:disabled):not([aria-disabled="true"]) {
  --pulse-control-shadow: var(--pulse-control-press-shadow); transform: none !important;
}
@media (hover: hover) {
  :is(.pulse-chrome-primary,.pulse-chrome-secondary,.pw-primary,.pw-secondary,.pw-panel-action,.neon-button-cyan,.hh2-deposit-cta,.pulse-recovery__primary,
      html[data-live-game] .primary:not(.pulse-slide),html[data-live-game] .primary-action:not(.is-quiet),html[data-live-game] .share-primary,html[data-live-game] .control-done,html[data-live-game] .secondary-action):hover:not(:active):not(:disabled):not([aria-disabled="true"]) {
    --pulse-control-shadow: var(--pulse-control-hover-shadow); transform: none !important;
  }
}
:is(.pulse-chrome-primary,.pulse-chrome-secondary,.pw-primary,.pw-secondary,.pw-panel-action,.neon-button-cyan,.hh2-deposit-cta,.pulse-recovery__primary,
    html[data-live-game] .primary:not(.pulse-slide),html[data-live-game] .primary-action:not(.is-quiet),html[data-live-game] .share-primary,html[data-live-game] .control-done,html[data-live-game] .secondary-action):is(:disabled,[aria-disabled="true"]) {
  --pulse-control-face: var(--pulse-control-disabled-face);
  --pulse-control-ink: var(--pulse-control-disabled-ink);
  --pulse-control-rim: var(--pulse-control-disabled-ink);
  --pulse-control-shadow: none; opacity: 1 !important; cursor: default; transform: none;
}
@media (prefers-reduced-motion: reduce) {
  :is(.pulse-chrome-primary,.pulse-chrome-secondary,.pw-primary,.pw-secondary,.pw-panel-action,.neon-button-cyan,.hh2-deposit-cta,.pulse-recovery__primary,
      html[data-live-game] .primary:not(.pulse-slide),html[data-live-game] .primary-action:not(.is-quiet),html[data-live-game] .share-primary,html[data-live-game] .control-done,html[data-live-game] .secondary-action) {
    transition: none !important; transform: none;
  }
}
@media (forced-colors: active) {
  :is(.pulse-chrome-primary,.pulse-chrome-secondary,.pw-primary,.pw-secondary,.pw-panel-action,.neon-button-cyan,.hh2-deposit-cta,.pulse-recovery__primary,
      html[data-live-game] .primary:not(.pulse-slide),html[data-live-game] .primary-action:not(.is-quiet),html[data-live-game] .share-primary,html[data-live-game] .control-done,html[data-live-game] .secondary-action) {
    --pulse-control-face: ButtonFace; --pulse-control-ink: ButtonText;
    --pulse-control-rim: ButtonText; --pulse-control-shadow: none;
    border: 1px solid ButtonText !important;
  }
}

/* Shared slide-to-confirm remains a dark track with a metal movable thumb.
   Its progress fill, completed green state and drag geometry are preserved. */
html[data-live-game] .pulse-slide:not(.is-complete):not(.locking):not(.done):not(:disabled):not([aria-disabled="true"]):not(.is-disabled) {
  background: var(--pulse-glass-face) !important;
  border-color: var(--pulse-glass-rim) !important;
  box-shadow: var(--pulse-glass-shadow) !important;
}
html[data-live-game] .pulse-slide::before {
  background: linear-gradient(90deg, #ffffff10, #ffffff30) !important;
}
html[data-live-game] .pulse-slide:not(.is-complete):not(.locking):not(.done) .pulse-slide-thumb {
  background: var(--pulse-metal-face) !important;
  color: var(--pulse-metal-ink) !important;
  border-color: var(--pulse-metal-rim) !important;
  box-shadow: var(--pulse-metal-shadow) !important;
}
html[data-live-game] .pulse-slide:is(:disabled,[aria-disabled="true"],.is-disabled) {
  opacity: 1 !important; box-shadow: none !important;
  background: var(--pulse-control-disabled-face) !important;
  border-color: var(--pulse-control-disabled-ink) !important;
}
html[data-live-game] .pulse-slide:is(:disabled,[aria-disabled="true"],.is-disabled) > strong {
  color: var(--pulse-control-disabled-ink) !important;
}
html[data-live-game] .pulse-range { --pulse-slider-accent: var(--pulse-metal-rim); }
html[data-live-game] .pulse-range-thumb { background: var(--pulse-metal-face) !important; box-shadow: var(--pulse-metal-shadow) !important; }

/* Remove the legacy one-second focus ripple from neutral metal actions. */
.neon-button:is(.neon-button-cyan,.pulse-chrome-primary)::after { display: none !important; animation: none !important; }
.pw-world button:focus-visible,.pw-entry button:focus-visible {
  outline-color: var(--pulse-control-focus);
}

/* The role selectors outrank older phone themes; put the reduced-motion
   value in their shared token so selector specificity cannot restore motion. */
@media (prefers-reduced-motion: reduce) {
  :root { --pulse-control-transition: none; }
}
