/* listen.css */
/* One "Listen" (static/listen.js) and the collapsed guide picker: shared by the program page, the
   journey page and the journey cards. */
[data-listen][aria-busy] { cursor: progress; opacity: .85; }
[data-listen].listen-ready { animation: listen-pulse 1.6s ease-in-out infinite; }
@keyframes listen-pulse { 50% { box-shadow: 0 0 0 6px rgba(127, 127, 127, .25); box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 25%, transparent); } }
@media (prefers-reduced-motion: reduce) { [data-listen].listen-ready { animation: none; outline: 3px solid var(--accent); outline-offset: 2px; } }
.listen-top .listen-actions, .jtop-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.listen-top .btn-big { min-width: min(12rem, 100%); }
.guide-panel > summary { cursor: pointer; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; list-style: none; }
.guide-panel > summary::-webkit-details-marker { display: none; }
.guide-panel > summary::after { content: ""; width: .5em; height: .5em; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); margin-left: auto; margin-right: .25em; }
.guide-panel[open] > summary::after { transform: rotate(225deg); }
.guide-summary { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.guide-summary img { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex: none; }
.course-note { margin: 0; }
.btn-small { padding: 6px 14px; font-size: .9rem; min-height: 44px; }   /* iOS tap target (mobile e2e 2026-10-13) */
/* Card actions sit after the card's link (never inside it). */
.jcard:has(> .jcard-actions) { display: flex; flex-direction: column; }
html.no-has .jcard.x-actions { display: flex; flex-direction: column; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.jcard:has(> .jcard-actions) > .jcard-link { height: auto; flex: 1 1 auto; }
html.no-has .jcard.x-actions > .jcard-link { height: auto; flex: 1 1 auto; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.jcard-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 0 20px 20px; }
/* Same card, same row: the body fills the card so meta + progress + actions line up at the bottom, and the
   play and Settings buttons share one line (a secondary link button shrinks with an ellipsis; the play label never does). */
.jcard:has(> .jcard-actions) .jcard-body { flex: 1 1 auto; }
html.no-has .jcard.x-actions .jcard-body { flex: 1 1 auto; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.jcard:has(> .jcard-actions) .jcard-meta { margin-top: auto; }
html.no-has .jcard.x-actions .jcard-meta { margin-top: auto; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
/* The play button never shrinks (its label is the main action); a secondary link button gives way first. */
.jcard-actions > .play-btn { flex: none; }
.jcard-actions > .play-btn .play-label { white-space: nowrap; }
.jcard-actions > a.btn { flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jcard-actions { flex-wrap: nowrap; }
/* Phones (320 px, long German or Hindi labels; round 3 item 24): the second button drops to its own row and wraps instead of being cut to "S…". */
@media (max-width: 420px) { .jcard-actions { flex-wrap: wrap; } .jcard-actions > a.btn { white-space: normal; text-align: center; text-overflow: clip; overflow-wrap: anywhere; } }
.jcard-actions > :not(.play-btn):not(a.btn):not(.jcard-status) { flex: none; }
.jcard-actions:has(> .jcard-status:not(:empty)) { flex-wrap: wrap; }
html.no-has .jcard-actions.x-status { flex-wrap: wrap; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.jcard-status { flex-basis: 100%; margin: 0; }
/* While a session is being prepared the play label is long ("Preparing your session… about 1–2 min", longer in hu/de):
   the row wraps so Settings moves to its own line whole instead of being clipped (Gergo, hu screenshot 22 Oct). */
.jcard-actions:has(> .play-btn[aria-busy]) { flex-wrap: wrap; }
html.no-has .jcard-actions.x-busy { flex-wrap: wrap; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.jcard-actions:has(> .play-btn[aria-busy]) > a.btn { flex: none; }
html.no-has .jcard-actions.x-busy > a.btn { flex: none; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.jcard-actions > .play-btn[aria-busy] { max-width: 100%; }
.jcard-actions > .play-btn[aria-busy] .play-label { white-space: normal; }
.jcard-status:empty { display: none; }
.guide-panel > summary h2 { margin: 0; }
/* A script line's ▶ while its excerpt is made on demand: a small spinner in place of the icon. */
button.play[aria-busy] span[aria-hidden] { visibility: hidden; }
button.play[aria-busy] { position: relative; }
button.play[aria-busy]::after { content: ""; position: absolute; inset: 0; margin: auto; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; animation: line-spin .8s linear infinite; }
@keyframes line-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { button.play[aria-busy]::after { animation-duration: 2.4s; } }

/* The one Play button (_play.html). Sizes lg / md / sm; the icon is drawn here: ▶, ❚❚ while playing, a
   spinner while preparing (aria-busy). One look everywhere (Gergo, 2026-10-13). */
.play-btn { display: inline-flex; align-items: center; justify-content: center; gap: .5em; border-radius: 999px; white-space: normal; text-align: center; }   /* nowrap before 2026-10-28: a long label at large text pushed the page sideways */
.play-btn .play-ico { display: inline-grid; place-items: center; width: 1.1em; height: 1.1em; flex: none; }
/* W87: the icons are drawn, not glyphs (the ❚ came from a fallback font, was taller than the text and the two bars overlapped into one). */
.play-btn .play-ico::before, .sample-ico::before { content: ""; display: block; width: .8em; height: .8em; background: currentColor; clip-path: polygon(12% 0, 100% 50%, 12% 100%); }
.play-btn.is-playing .play-ico::before, .sample-btn.is-playing .sample-ico::before { clip-path: none;
  background: linear-gradient(90deg, currentColor 0 34%, transparent 34% 66%, currentColor 66% 100%); }
.play-btn[aria-busy] .play-ico::before { content: ""; width: .9em; height: .9em; border-radius: 50%; border: 2px solid currentColor;
  border-right-color: transparent; background: none; clip-path: none; animation: line-spin .8s linear infinite; }
.play-btn[aria-busy] { cursor: progress; opacity: .9; }
.play-lg { min-height: 52px; padding: 12px 28px; font-size: 1.1rem; min-width: min(12rem, 100%); }
.play-md { min-height: 44px; padding: 9px 20px; font-size: 1rem; }
.play-sm { min-height: 44px; padding: 6px 16px; font-size: .92rem; }
/* The program page: the Play buttons drive the player; the bar's own ▶ would be a second control. */
.listen-player .pp { display: none; }
/* Tap targets >= 44 px on phones (site review m26): text buttons, ghost buttons, the footer's cookie link. */
@media (pointer: coarse) {
  button.ghost, .btn-text, button.link { min-height: 44px; }
  .footer-cookies a, .site-footer nav a, footer nav a { display: inline-flex; align-items: center; min-height: 44px; }
}
/* W403: 44 px touch targets for download links, selects, search/partner inputs and <summary> (phones, touch). */
@media (pointer: coarse), (max-width: 640px) {
  a[download] { display: inline-flex; align-items: center; min-height: 44px; }
  select, .partner-code input[type="text"], input[type="search"] { min-height: 44px; box-sizing: border-box; }
  details > summary { min-height: 44px; box-sizing: border-box; padding-block: 10px; }
}

/* The 60 s sample before sign-up (samples.py, _sample.html) */
.sample { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 12px 0 4px; }
.sample-btn { gap: 8px; min-height: 44px; }
.sample-ico { display: inline-grid; place-items: center; width: 1.1em; flex: none; }

/* "Press Play" after sign-in (web_accounts.welcome): the cue above the Play button, which is focused */
.welcome-cue { margin: 10px 0 12px; padding: 12px 14px; border-radius: 10px; border: 1.5px solid var(--accent);
  background: var(--accent-soft, rgba(127, 127, 127, .12)); background: color-mix(in srgb, var(--accent) 10%, transparent); font-weight: 600; }
.welcome-cue p { margin: 0; }
.welcome-cue .small { font-weight: 400; margin-top: 4px; }
.welcome-first { margin: 0 0 16px; }
.welcome-first h2 { margin: 0 0 6px; font-size: 1.15rem; }
.welcome-first .play-btn { margin-top: 8px; }
.play-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* Sign-in page: the deal line, and the "check your email" alternatives (web_templates/signin.html, check_email.html) */
.signin .signin-deal { margin: 0 0 8px; }
.signin .btn-big { width: 100%; }
.signin-alt { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 16px; }
.signin-alt .btn, .signin-alt .btn-text { min-height: 44px; }
/* The 6-digit sign-in code typed on the check-email page (check_email.html): large, spaced digits, one thumb-sized button. */
.signin-code { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line, rgba(127,127,127,.3)); }
.code-input { font-size: 28px; letter-spacing: .3em; text-align: center; min-height: 56px; width: 100%; max-width: 280px; font-variant-numeric: tabular-nums; }
/* The inline stereo note (listen.js) */
.stereo-note { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; margin: 6px 0 0; }
.stereo-note .btn-text { min-height: 44px; padding: 0 6px; }
/* The shared progress button: a second-colour fill from the left at --progress, or a shimmer when no percent is
   known (listen.js TwhProgress). Used by Play while preparing / updating and by every other "making" state. */
.btn-progress { position: relative; overflow: hidden; isolation: isolate; }
.btn-progress::after { content: ""; position: absolute; inset: 0; z-index: -1; width: var(--progress, 0%);
  background: rgba(255, 255, 255, .28); background: color-mix(in srgb, var(--on-accent, #fff) 28%, transparent); transition: width .6s ease; }
.btn-outline.btn-progress::after { background: var(--accent-soft, rgba(127, 127, 127, .2)); background: color-mix(in srgb, var(--accent) 22%, transparent); }
.btn-progress.is-indeterminate::after { width: 40%; animation: btn-shimmer 1.4s ease-in-out infinite; }
@keyframes btn-shimmer { from { transform: translateX(-100%); } to { transform: translateX(260%); } }
@media (prefers-reduced-motion: reduce) { .btn-progress.is-indeterminate::after { animation: none; width: 100%; opacity: .35; } }
.btn-progress[aria-busy] { opacity: 1; }

/* The first-visit line (samples.first_visit): calm, inline, one button; no pop-up */
.fv-line { margin: 12px 0 8px; max-width: 60ch; }
.fv-text { margin: 0 0 10px; font-size: 1.05rem; line-height: 1.45; }
.fv-line .sample { margin-top: 0; }
.fv-line .sample-btn { width: 100%; max-width: 22rem; }
.fv-after { margin-top: 12px; padding: 12px 14px; border-radius: 10px; border: 1.5px solid var(--accent); }
.fv-after p { margin: 0 0 8px; }
.fv-after p:last-child { margin-bottom: 0; }
@media (pointer: coarse) { .footer-journeys a { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; padding: 0 2px; } }
/* The card's whole-card link (.jcard-link::after, brand.css) must never cover the card's own controls: the
   actions row, the library's ⋯ menu and notices sit above it (Safari/Chromium hit-testing, 14 Oct). */
.jcard > *:not(.jcard-link) { position: relative; z-index: 1; }
/* "🎙 Live with your guide" in the player: one tap target, never two half-lines (14 Oct). */
.live-hint [data-live-go] { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; padding: 0 6px; white-space: nowrap; }
/* Voice / tones balance: left = louder tones, right = louder voice (was an inline style, blocked by the CSP). */
.tone-range input[data-balance] { direction: rtl; }
/* Editor, "Make it yours" (editor.html): one visible box, the rest one tap away */
.prompt-label { display: block; font-size: 1.1rem; margin: 8px 0 2px; }
.prompt-count-line { text-align: right; margin: 2px 0 6px; }
.your-name > summary, .ideas > summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; font-weight: 600; }
.ideas { margin: 4px 0 8px; }
/* "Preparing your session… about 1-2 min" (Gergo mail 18 Oct, screenshot): the nowrap label grew wider than the
   pill on a phone and clipped at both ends; a busy button may wrap to two lines instead. */
.play-btn { max-width: 100%; }
.play-btn[aria-busy], .play-btn[aria-busy] .play-label { white-space: normal; }

/* "Hear it your way": language (and English accent) choice above the sample button, the pitch line under it (sample.js, _sample.html) */
.sample-opts { margin: 12px 0 0; max-width: 26rem; }
.sample-opts-h { margin: 0 0 6px; font-weight: 600; font-size: .95rem; }
.sample-opts-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.sample-opts select.sample-lang { width: auto; min-width: 9rem; flex: 1 1 9rem; min-height: 44px; }
.sample-accent { display: inline-flex; gap: 6px; }
.sample-accent[hidden] { display: none; }
.sample-acc { min-width: 0; padding: 6px 12px; }
.sample-acc[aria-pressed="true"] { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--on-accent); }
.sample-pitch { margin: 6px 0 0; max-width: 36rem; }

/* The guide beside Play (course page and player sheet): avatar, name, "Change". Phone-first, one calm line. */
.jtop-guide, .player-guide { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 8px 0 0; }
.jtop-guide [data-jtop-guide-img], .player-guide [data-guide-img] { display: inline-flex; line-height: 0; }
.guide-chip-img, .jtop-guide img { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; }
.jtop-guide a, .player-guide a { min-height: 44px; display: inline-flex; align-items: center; padding: 0 6px; }
.player-guide[hidden] { display: none; }
/* The play setup panel (listen.js, listen_setup.py): a bottom sheet on a phone, a centred card on a wide screen. Big targets,
   calm colours from the theme tokens (dark mode follows them), no motion. */
.setup-wrap { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: flex-end; justify-content: center; background: rgba(0, 0, 0, .55); }
.setup-sheet { box-sizing: border-box; width: 100%; max-width: 32rem; max-height: 92vh; max-height: 92dvh; overflow-y: auto; padding: 16px 16px 20px;
  background: var(--surface); color: var(--text, inherit); border: 1px solid var(--line); border-radius: 16px 16px 0 0; }
@media (min-width: 640px) { .setup-wrap { align-items: center; } .setup-sheet { border-radius: 16px; } }
.setup-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.setup-head h2 { margin: 0; font-size: 1.15rem; }
.setup-x { min-width: 44px; min-height: 44px; font-size: 1.6rem; line-height: 1; background: none; border: 0; color: inherit; cursor: pointer; border-radius: 8px; }
.setup-lead { margin: 4px 0 8px; }
.setup-group { margin: 0 0 12px; padding: 0; border: 0; min-width: 0; }
.setup-group legend { padding: 0; margin: 0 0 4px; font-weight: 600; }
.setup-opt { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 6px 12px; margin: 0 0 6px; border: 1px solid var(--line); border-radius: 12px; cursor: pointer; }
.setup-opt input { width: 22px; height: 22px; flex: none; accent-color: var(--accent-fill, currentColor); }
.setup-opt:has(input:checked) { border-color: var(--accent-fill, currentColor); }
html.no-has .setup-opt.x-checked { border-color: var(--accent-fill, currentColor); }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.setup-opt:has(input:focus-visible) { outline: 2px solid var(--accent-fill, currentColor); outline-offset: 2px; }
html.no-has .setup-opt.x-focus { outline: 2px solid var(--accent-fill, currentColor); outline-offset: 2px; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
.setup-go { width: 100%; min-height: 52px; position: sticky; bottom: 0; }
.setup-x:focus-visible, .setup-chip:focus-visible { outline: 2px solid var(--accent-fill, currentColor); outline-offset: 2px; }
html.setup-open { overflow: hidden; }
/* The chip row above Play: "Voice: Emma · Rain · Noise on · Binaural on". */
.setup-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 10px; }
.setup-chip { min-height: 44px; padding: 6px 14px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: inherit; font: inherit; font-size: .9rem; cursor: pointer; }
.setup-gear { color: var(--muted, inherit); }

/* A2 (29 Oct 2026): the sample is the one primary action in the hero. "Starting" is the instant answer to the tap (before sound):
   a pulsing icon, no layout shift (the label is the same width class). The free-account line under it is a quiet text link. */
.sample-btn.is-starting .sample-ico::before { content: "●"; display: inline-block; width: auto; height: auto; background: none; clip-path: none; transform: scale(.7); animation: twh-sample-pulse 1s ease-in-out infinite; }
@keyframes twh-sample-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .sample-btn.is-starting .sample-ico::before { animation: none; } }
.sample-wrap { margin: 0; }
.sample-wrap > .sample { margin-top: 12px; }
.sample-wrap .sample-btn { width: 100%; max-width: 26rem; min-height: 56px; }
.free-signup-hero { margin: 4px 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; color: var(--muted); }
/* W-01: on a course page the line sits on the dark hero image (desktop and tablet); the phone layout puts it below the image on the page colour. */
@media (min-width: 561px) {
  .jhero.has-art .free-signup-hero, .jhero.has-art .free-signup-hero span { color: #f6f3ec; }
  .jhero.has-art .sample-note { color: #f6f3ec; }
  .jhero.has-art .free-signup-hero .btn-text { color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, .6); }
}
.free-signup-hero .btn-text { min-height: 44px; display: inline-flex; align-items: center; padding: 0 4px; font-weight: 600; text-decoration: underline; }
.sample-wrap .sample-opts { margin-top: 8px; }
.sample-wrap .fv-after { margin-top: 12px; }

/* The opt-in "a new, more natural voice is available" card (static/flow-upgrade.js, voice_flow_upgrade.py). */
.vfu{margin:.6rem 0 0;padding:.65rem .8rem;border:1px solid var(--line,#d9d4c7);border-radius:10px;background:var(--panel,#fffdf7);font-size:.92rem;line-height:1.4}
.vfu strong{display:block;font-weight:600}
.vfu p{margin:.25rem 0 .5rem;color:var(--muted,#5b5a55)}
.vfu-go{min-height:44px;padding:.5rem 1rem;border:0;border-radius:8px;background:var(--accent,#2f6f5e);color:#fff;font:inherit;font-weight:600;cursor:pointer}
.vfu-go[disabled]{opacity:.6;cursor:default}

/* pwa.css */
/* 2hives as a phone app (static/pwa.js, web_templates/_pwa.html). */

/* Install prompt: a small card above the bottom edge, dismissible. */
.pwa-prompt { position: fixed; z-index: 55; left: 50%; transform: translateX(-50%);
  bottom: calc(16px + env(safe-area-inset-bottom, 0px)); width: min(520px, calc(100vw - 32px));
  display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 8px 12px; align-items: center;
  padding: 12px 14px; margin: 0; box-shadow: var(--shadow-3); }
.pwa-prompt[hidden] { display: none; }
.pwa-prompt img { border-radius: 11px; }
.pwa-prompt-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pwa-prompt-actions { grid-column: 1 / -1; display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
.pwa-prompt-actions .btn { min-height: 44px; }

/* iPhone "Add to Home Screen" sheet */
.pwa-ios { max-width: min(440px, calc(100vw - 32px)); border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--surface); color: var(--text); padding: 20px; }
.pwa-ios::backdrop { background: rgb(15 20 32 / 0.55); }
.pwa-ios h2 { margin-top: 0; font-size: var(--text-lg); }
.pwa-ios-steps { list-style: none; padding: 0; margin: 0 0 16px; display: grid; gap: 12px; }
.pwa-ios-steps li { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 12px; align-items: center; }
.pwa-ios-ill { width: 48px; height: 48px; color: var(--accent-ink); border-radius: 11px; }
.pwa-ios form { display: flex; justify-content: flex-end; }
.pwa-ios .btn { min-height: 44px; }

/* Library: Save for offline */
.pwa-offline { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 8px 0; }
.pwa-offline[hidden], .pwa-offline [hidden] { display: none; }
.pwa-offline .btn { min-height: 44px; }
.pwa-offline progress { width: 140px; }
.pwa-offline-wifi { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; }
.pwa-offline-wifi input { width: 24px; height: 24px; margin: 0; flex: none; }
.pwa-install-link { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.pwa-install-link[hidden] { display: none; }
.pwa-install-link .btn { min-height: 44px; }

/* Offline page */
.pwa-offline-list { list-style: none; padding: 0; display: grid; gap: 8px; }
.pwa-offline-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line); }
.pwa-offline-list li > span { flex: 1 1 12rem; min-width: 0; overflow-wrap: break-word; }
.pwa-offline-list .btn { min-height: 44px; }

/* Standalone (installed) window: the status bar is translucent (apple-mobile-web-app-status-bar-style),
   so the sticky header carries the top inset itself, and the bottom clears the home indicator. */
@media (display-mode: standalone) {
  .site-header { top: 0; padding-top: env(safe-area-inset-top, 0px); }
  main { padding-bottom: env(safe-area-inset-bottom, 0px); }
}
html.pwa-standalone .site-header { top: 0; padding-top: env(safe-area-inset-top, 0px); }

/* Inside the store apps (html.native-app, set by native.js; the CSP style-src 'self' blocks a style element injected from script, so the rules live here).
   Apple 4.2 / 3.1.1 (mobile/PLAN.md 3): no install prompts, no web-only blocks, no price page link, no comparison page link (its page links to
   competitors' App Store entries), no press kit, no llms.txt, no social-channel row, and never an App Store / Google Play link. Terms, Privacy,
   Safety, About, Questions, Support and the support address stay in the footer (the Support link must never be hidden here: store review). */
html.native-app [data-pwa-install-link], html.native-app [data-pwa-prompt], html.native-app [data-pwa-ios], html.native-app .web-only,
html.native-app .footer-links a[href$="/pricing"], html.native-app .footer-links a[href$="/compare"], html.native-app .footer-links a[href$="/press"],
html.native-app .footer-links a[href$="/llms.txt"], html.native-app .footer-social,
html.native-app a[href*="apps.apple.com"], html.native-app a[href*="itunes.apple.com"], html.native-app a[href*="play.google.com"] { display: none !important; }

/* ---- App shell, banners, touch and contrast basics (28 Oct 2026, UX spec issues 1, 8, 9, 13, 15) ---- */
/* The page paints its own background on the root, not only on body: the area outside the body (overscroll, the frame before first paint, a short page)
   is then the theme's colour and never white or the other theme's. */
html { background-color: var(--bg); }
/* Inside the app: no rubber-band / pull-to-refresh bounce revealing a different colour, no grey tap flash, no double-tap-zoom delay on controls. */
html.native-app { overscroll-behavior: none; -webkit-tap-highlight-color: transparent; }
html.native-app :is(a, button, summary, label, input, select, textarea, [role=button]) { touch-action: manipulation; }
/* Banners never stack: while the terms notice is up, the other inline banners wait; the install card waits for the cookie banner (same bottom edge). */
[data-terms-notice]:not([hidden]) ~ :is([data-ch-banner], .lang-banner, .ending-line) { display: none; }
body:has(.consent-banner:not([hidden])) .pwa-prompt { display: none; }
/* W2 F3 (cookie first): the terms notice waits until the cookie card has been answered (the card gets [hidden]), so a first visit shows one thing at a time. */
body:has(.consent-banner:not([hidden])) [data-terms-notice] { display: none; }
html.no-has body.x-consent [data-terms-notice] { display: none; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
html.no-has body.x-consent .pwa-prompt { display: none; }   /* fallback: no :has() before iOS 15.4 (static/has-fallback.js) */
html.native-app .pwa-prompt, html.native-app .pwa-ios, html.native-app [data-pwa-install-link] { display: none !important; }
/* Touch targets: a link that stands alone on its line (reference lists on /research, notes) gets a 44 px hit area without moving the text. */
@media (pointer: coarse) {
  .prose li > a, .prose p > a:only-child { padding-block: 12px; }
}
/* More contrast (iOS "Increase Contrast", Android high-contrast text, Windows): the hairlines become the strong line colour. */
@media (prefers-contrast: more) {
  :root { --line: var(--line-strong); }
  .card, .jcard, .notice, .free-banner { border-color: var(--line-strong); }
  .muted, .small { color: var(--text); }
}
/* Forced colours (Windows High Contrast): shadows vanish, so every control keeps a real border and focus is an outline. */
@media (forced-colors: active) {
  .btn, .btn-text, button, .button, input, select, textarea, summary, .card, .jcard, .pwa-prompt, .consent-banner, .free-banner, .site-header,
  .player, .mixer, [data-mixer] { border: 1px solid CanvasText; }
  .btn-primary { border: 2px solid ButtonText; }
  :focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
  a { text-decoration: underline; }
  progress, input[type=range] { forced-color-adjust: auto; }
}

/* W28 F6: the iPhone "Open in Safari" hint (static/ios-web.js) is the install card without the icon column. */
.safari-hint { grid-template-columns: minmax(0, 1fr); }
.safari-hint[hidden] { display: none; }

/* W28 F2: in a Home Screen app the email link opens Safari, so the sign-in screens lead with the 6-digit code (static/ios-web.js marks
   html.pwa-standalone). The note is for the installed app only; the code form moves to the top of "Check your email". */
.standalone-only { display: none; }
html.pwa-standalone .standalone-only { display: block; }
html.pwa-standalone .signin-sent { display: flex; flex-direction: column; }
html.pwa-standalone .signin-sent > * { order: 5; }
html.pwa-standalone .signin-sent > h1 { order: 0; }
html.pwa-standalone .signin-sent > .standalone-only { order: 1; }
html.pwa-standalone .signin-sent > [data-code-form] { order: 2; }
html.pwa-standalone .signin-sent > [role="status"], html.pwa-standalone .signin-sent > .signin-context { order: 6; }
html.pwa-standalone .signin-sent > [data-resend] { order: 7; }
html.pwa-standalone .signin-sent > .signin-alt { order: 8; }
html.pwa-standalone .signin-sent .signin-code .code-input { font-size: 1.5rem; letter-spacing: .2em; text-align: center; }

/* W67 (A11Y-AUDIT L3, WCAG 2.3.3): motion stops for people who ask the system for less of it. */
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }

/* W168 iPhone bridge (ios_bridge.py, static/ios-bridge.js): the Home Screen card shown after a finished session; the steps reuse .pwa-ios-steps. */
.ios-bridge { grid-template-columns: minmax(0, 1fr); max-height: calc(100vh - 32px); overflow-y: auto; }
.ios-bridge[hidden] { display: none; }
.ios-bridge .pwa-ios-steps { margin: 0; }
.ios-bridge-page .pwa-ios-steps { margin: 16px 0; }
.ios-bridge-safari { display: flex; flex-direction: column; gap: 2px; margin: 0 0 8px; }
html.pwa-standalone .ios-bridge, html.native-app .ios-bridge { display: none !important; }
/* W190: rows that exist only inside the store apps (Account > Offline listening) */
.app-only { display: none; }
html.native-app .app-only { display: revert; }

/* netstatus.css */
/* Connection banner (static/netstatus.js). A sticky strip in the page flow: it pushes content down
   and never overlaps the player controls. Empty (zero height) until the script shows a message. */
.net-live { position: sticky; top: 0; z-index: 70; }
.net-banner { display: flex; align-items: center; gap: 8px; justify-content: center; padding: 8px 12px;
  padding-top: max(8px, env(safe-area-inset-top, 0px)); font-size: .9rem; line-height: 1.35;
  background: var(--warn-bg); color: var(--warn); border-bottom: 1px solid var(--line); text-align: center; }
.net-banner[hidden] { display: none; }
.net-banner.net-ok { background: var(--success-bg, var(--surface-2)); color: var(--success, var(--text)); }
.net-msg { min-width: 0; overflow-wrap: anywhere; }
.net-x { flex: none; min-width: 44px; min-height: 44px; margin: -8px -8px -8px 0; padding: 0; border: 0;
  background: transparent; color: inherit; font: inherit; font-size: 1.4rem; line-height: 1; cursor: pointer; }
.net-x:focus-visible { outline: 2px solid currentColor; outline-offset: -4px; border-radius: 8px; }
@media (prefers-reduced-motion: no-preference) {
  .net-banner:not([hidden]) { animation: net-in .18s ease-out; }
  @keyframes net-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
}

