[data-focusable] {
  transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
  outline: none;
  cursor: pointer;
}

[data-focusable].focused {
  border-color: var(--focus-ring) !important;
  box-shadow: 0 0 0 3px var(--accent-glow), 0 0 20px var(--accent-glow);
  z-index: 10;
}

/* A TV drawing the app at 4K (data-density, theme-service) repaints a fade
   of a background, border or glow every frame, ~18 a second there: those
   change at once, and only transform and opacity still glide. */
html[data-density="2x"] [data-focusable] {
  transition-property: transform, opacity;
}

.btn.focused {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: white;
}

.btn-danger.focused,
.confirmation-btn.danger.focused {
  color: #fff;
  background: var(--danger);
  border-color: var(--danger) !important;
  box-shadow:
    0 0 0 3px rgba(var(--danger-rgb-legacy), 0.24),
    0 0 20px rgba(var(--danger-rgb-legacy), 0.35);
}

.settings-input.focused {
  border-color: var(--accent) !important;
  background: var(--bg-primary);
}

.epg-programme.focused {
  background: var(--accent-dim) !important;
  border-color: var(--accent) !important;
  z-index: 10;
}

/* Pointer platforms (the desktop app, the browser demo; `html.pointer`
   from app.ts, never on the TVs): what the mouse rests on shows it, as a
   lighter cousin of each focus style, and Back is a button at the top
   left, since the keyboard's Escape is not where a mouse-only viewer
   looks. The D-pad's own focus stays what it was. */
html.pointer .gh-card:not(.focused):hover .gh-card-art { transform: scale(1.04); }
html.pointer .gh-card:not(.focused):hover::before { opacity: 0.55; transform: scale(1.04); }
html.pointer .gh-card:not(.focused):hover .gh-card-name { color: var(--text-primary); }
html.pointer .channel-item:not(.focused):hover::before,
html.pointer .group-item:not(.focused):hover::before { opacity: 0.5; }
html.pointer .detail-version:not(.focused):hover,
html.pointer .detail-btn:not(.focused):hover { border-color: rgba(var(--accent-rgb-legacy), 0.55); }
html.pointer .tab-bar-item:not(.focused):not(.active):hover { color: var(--text-primary); }

.pointer-back {
  position: fixed;
  top: 26px;
  left: 14px;
  /* Above the views and the player (60), under the welcome (900), the
     first-run questions (1000) and the toasts and dialogs (9999+). */
  z-index: 800;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--glass-edge);
  border-radius: 50%;
  background: var(--glass-tint-solid);
  color: var(--text-primary);
  cursor: pointer;
  opacity: 0.75;
  transition: opacity var(--transition);
}
.pointer-back:hover { opacity: 1; }
.pointer-back svg {
  display: block;
  width: 24px;
  height: 24px;
  margin: 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* A small box's X, top right (close-box.ts closeButton, pointer platforms):
   the box's Back, as a click beside the box is. Each box gives it room. */
.box-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--glass-edge);
  border-radius: 50%;
  background: var(--glass-tint-solid);
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
}
.box-close:hover { color: var(--text-primary); border-color: rgba(var(--accent-rgb-legacy), 0.55); }
.box-close svg {
  display: block;
  width: 18px;
  height: 18px;
  margin: 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
}
/* The boxes that hold it: a corner to sit in, and their heading kept
   clear of it. */
html.pointer .gh-picker-panel,
html.pointer .channel-version-dialog,
html.pointer .confirmation-dialog,
html.pointer .reminder-dialog,
html.pointer .catchup-resume-dialog,
html.pointer .subs-offset-card,
html.pointer .player-sidebar .sidebar-channel-panel { position: relative; }
html.pointer .gh-picker-title,
html.pointer .channel-version-title,
html.pointer .player-menu .menu-header,
html.pointer .subs-overlay-header,
html.pointer .epg-mapping-heading,
html.pointer .group-picker-title { padding-right: 44px; }
html.pointer .confirmation-title,
html.pointer .reminder-message,
html.pointer .catchup-resume-message,
html.pointer .subs-offset-title { padding: 0 36px; }
html.pointer .episode-panel-header { padding-right: 64px; }
html.pointer .player-sidebar .sidebar-channel-title { padding-right: 60px; }
html.pointer .player-sidebar .sidebar-channel-panel > .box-close { top: 16px; }
/* The side panels': level with their heading, inside their padding. */
.player-menu > .box-close { top: 26px; right: 24px; }
.episode-panel > .box-close { top: 41px; right: 16px; }
/* A list that scrolls keeps it in sight. */
.group-picker > .box-close {
  position: sticky;
  top: 0;
  float: right;
  margin: -6px -6px 0 8px;
}
/* Dropdowns: above their first row. The settings dropdown's sits beside
   its scrolling list, shown with it. */
html.pointer .account-menu,
html.pointer .dropdown-menu { padding-top: 52px; }
html.pointer .resume-choice-panel { padding-top: 48px; }
.account-menu > .box-close,
.epg-group-menu > .box-close { top: 8px; right: 8px; }
.resume-choice-panel > .box-close { top: 6px; right: 6px; }
html.pointer .epg-group-menu-title { min-height: 36px; padding-right: 52px; }
.dropdown > .box-close { display: none; top: calc(100% + 14px); right: 14px; z-index: 21; }
.dropdown.open > .box-close { display: block; }

/* Room for the button before the wordmark. */
html.pointer .tab-bar-inner { padding-left: 46px; }

/* While the mouse is in use (no remote key since it last moved), the
   pointer is the one mark on the home: the D-pad's focus ring, the
   card's growth and the peek stay out of sight, so a hovered card and the
   D-pad's card are never lit at once (the owner, on the Windows app,
   2026-10-11). A key press brings the focus back (html.keys-active). */
html.pointer:not(.keys-active) .gh-card.focused::before { opacity: 0; transform: none; }
html.pointer:not(.keys-active) .gh-card.focused .gh-card-art { transform: none; }
html.pointer:not(.keys-active) .gh-card.focused .gh-card-name { color: inherit; }
html.pointer:not(.keys-active) .gh-peek { display: none; }
/* The hero's buttons likewise: the D-pad's white Play rests while the
   mouse is in use, and lights under the pointer instead. */
html.pointer:not(.keys-active) .genre-home .gh-btn.focused:not(:hover) { outline: none; border-color: transparent; }
html.pointer:not(.keys-active) .genre-home .gh-btn-primary.focused:not(:hover) { background: var(--glass-accent); color: #fff; }
html.pointer .genre-home .gh-btn:hover { outline: 3px solid var(--catalog-focus); outline-offset: 2px; }
html.pointer .genre-home .gh-btn-primary:hover { background: #fff; color: #111; outline-color: rgba(255, 255, 255, 0.45); }

/* No colour keys on a computer (the column's buttons lose theirs in
   genre-home.ts): the 4K and watchlist-mode chips drop the remote's yellow
   and green with them. */
html.pointer .gh-status-fourk,
html.pointer .gh-status-watchlist { background: var(--accent); color: var(--bg-primary); }

/* Settings' arrow-key help under its categories is the remote's. */
html.pointer .settings-nav-help { display: none; }

/* A drag selects no text (a field keeps its own), and everything that
   takes a click shows the hand. */
html.pointer body { user-select: none; }
html.pointer input,
html.pointer textarea { user-select: text; }
html.pointer [data-focusable] { cursor: pointer; }
html.pointer input[data-focusable] { cursor: text; }
/* The guide's grid: the cell under the mouse, as the list's rows have. */
html.pointer .epg-tl-cell:not(.focused):hover { opacity: 1; box-shadow: 0 0 0 2px rgba(var(--accent-rgb-legacy), 0.55); }
/* The cursor rests over the player: out of sight until it moves
   (app.ts notePointerActivity). */
html.pointer.pointer-idle,
html.pointer.pointer-idle * { cursor: none; }

/* A row's page arrows (genre-home.ts rowArrows, pointer platforms): over
   the cards at each end of the track, shown while the pointer is on the
   row, as streaming sites do. */
.gh-row-arrow {
  position: absolute;
  top: 12px;
  z-index: 3;
  width: 64px;
  height: 280px;
  padding: 0;
  border: none;
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transition: opacity 150ms ease;
}
.gh-row-arrow-back { left: 0; background: linear-gradient(90deg, rgb(0 0 0 / 0.85), rgb(0 0 0 / 0)); }
.gh-row-arrow-on { right: 0; background: linear-gradient(270deg, rgb(0 0 0 / 0.85), rgb(0 0 0 / 0)); }
.gh-row-arrow svg {
  width: 40px;
  height: 40px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 6px rgb(0 0 0 / 0.7));
}
.gh-row-arrow-on svg { transform: scaleX(-1); }
.gh-row:hover .gh-row-arrow { opacity: 0.85; }
.gh-row .gh-row-arrow:hover { opacity: 1; }
