/*
 * UndertoneLab for the web.
 *
 * The brief was that this should look like the phone app, so the sizes below are iOS's own text
 * styles in points (body 17, subheadline 15, footnote 13, caption 12, caption2 11) and the list
 * is a hand-built `.insetGrouped` — 16pt side margins, 10pt corners, separators inset past the
 * leading icon. On a Mac or an iPhone `-apple-system` resolves to SF Pro and the match is close
 * to exact; elsewhere the fallback stack keeps the metrics but not the letterforms.
 *
 * Colours are Morning Hush, from `Core/Model/Palette.swift`. Dark only, and not because of
 * `prefers-color-scheme`: a session is usually run in a dim room, so the app has no light theme
 * on any platform.
 */

:root {
    /* Baltic Blue, Lavender Grey, Cool Steel, Ash Grey, Cream. */
    --ramp-deep: #586994;
    --ramp-mid: #7d869c;
    --ramp-muted: #a2abab;
    --ramp-soft: #b4c4ae;
    --ramp-bright: #e5e8b6;

    --app-background: #0e1118;
    --surface: #1a1f2b;
    --tint: var(--ramp-bright);
    --highlight: var(--ramp-soft);

    --text-primary: #f2f3f5;
    --text-secondary: rgba(162, 171, 171, 0.75);
    --text-tertiary: rgba(162, 171, 171, 0.45);
    --separator: rgba(162, 171, 171, 0.18);

    --radius-row: 10px;
    --inset: 16px;

    --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro", "Segoe UI",
        system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-rounded: ui-rounded, -apple-system, "SF Pro Rounded", system-ui, sans-serif;

    /* Overwritten from JS on the play screen so the gradient can follow the beat rate. */
    --play-gradient: linear-gradient(160deg, rgba(88, 105, 148, 0.85) 0%, #1b2233 55%, #0b0e15 100%);

    color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    background: var(--app-background);
    color: var(--text-primary);
    font-family: var(--font);
    font-size: 17px;
    line-height: 1.35;
    -webkit-font-smoothing: antialiased;
    -webkit-text-size-adjust: 100%;
    overscroll-behavior-y: none;
}

/* An author `display` beats the UA's `[hidden] { display: none }`, and both the play screen and
   the now-playing bar set one. Without this, `hidden` silently does nothing to them. */
[hidden] { display: none !important; }

button {
    font: inherit;
    -webkit-user-select: none;
    user-select: none;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

a { color: var(--tint); }

.icon {
    width: 1.25em;
    height: 1.25em;
    flex: none;
    display: block;
}

:focus-visible {
    outline: 2px solid var(--tint);
    outline-offset: 2px;
    border-radius: 6px;
}

/* Phone-shaped at phone widths, and a real page above that. The wide layout is not a stretched
   list — the presets become a grid of cards at 760px, which is the point at which a single column
   of full-width rows starts to look like a mistake. */
.app {
    max-width: 1120px;
    margin: 0 auto;
    min-height: 100%;
    position: relative;
}

/* ---------------------------------------------------------------- navigation bar */

.navbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px var(--inset) 8px;
    background: rgba(14, 17, 24, 0.82);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    min-height: 44px;
}

.navbar.plain { background: none; backdrop-filter: none; -webkit-backdrop-filter: none; }

.navbar__title {
    flex: 1;
    text-align: center;
    font-size: 17px;
    font-weight: 600;
    margin: 0;
}

.navbar__button {
    color: var(--tint);
    font-size: 17px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 34px;
    min-width: 34px;
    justify-content: center;
}

.navbar__button--wide { justify-content: flex-start; }
/* Matches the Done button's slot so the title stays optically centred either way. */
.navbar__leading { display: flex; min-width: 34px; }
.navbar__button:active { opacity: 0.5; }
.navbar__spacer { min-width: 34px; }

/* A labelled pill rather than a bare glyph: an ellipsis in a circle is a convention you have to
   already know, and a word is not. */
.pill-button {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 13px;
    border-radius: 999px;
    font-size: 15px;
    color: var(--text-primary);
    background: rgba(162, 171, 171, 0.16);
    white-space: nowrap;
}
.pill-button:active { background: rgba(162, 171, 171, 0.28); }

/* iOS shows a large title until you scroll; this is the resting state of it. */
.large-title {
    font-size: 34px;
    font-weight: 700;
    letter-spacing: -0.4px;
    margin: 4px 0 14px;
    padding: 0 var(--inset);
}

/*
 * "Get more features from the apps".
 *
 * A banner between the title and the list rather than a button in the navigation bar: the label
 * is a sentence now, and a sentence does not fit in a bar that also carries a title on a
 * 375-point screen.
 *
 * Outlined rather than filled: the only solid tinted control in the app is the primary button at
 * the end of onboarding, and a call to action loud enough to compete with the preset list would
 * be selling harder than this app sells anything.
 */
.cta {
    display: flex;
    align-items: center;
    gap: 10px;
    width: calc(100% - var(--inset) * 2);
    margin: 0 var(--inset) 22px;
    padding: 13px 14px;
    border-radius: 12px;
    font-size: 15px;
    font-weight: 500;
    text-align: left;
    color: var(--tint);
    background: color-mix(in srgb, var(--tint) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--tint) 28%, transparent);
}

.cta__label { flex: 1; min-width: 0; }
.cta .icon { width: 18px; height: 18px; }
.cta__chevron { width: 14px !important; height: 14px !important; stroke-width: 2.4; opacity: 0.7; }
.cta:active { background: color-mix(in srgb, var(--tint) 18%, transparent); }

@media (min-width: 700px) {
    /* Capped rather than full-bleed: a 1120px bar carrying one short sentence reads as an empty
       strip. At this width it is a button again, sitting under the title. */
    .cta { font-size: 16px; padding: 15px 18px; margin-bottom: 26px; width: auto; max-width: 440px; }
}

/* ---------------------------------------------------------------- inset grouped list */

.list {
    padding-bottom: 28px;
}

.section {
    margin: 0 0 26px;
}

.section__header {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 0 calc(var(--inset) + 4px) 7px;
    font-size: 15px;
    color: var(--text-primary);
    text-align: left;
}

.section__header--static { color: var(--text-secondary); font-size: 13px; }

.section__count { color: var(--text-tertiary); }
.section__header .icon { width: 0.85em; height: 0.85em; color: var(--text-secondary); transition: transform 0.22s ease; }
.section__header[aria-expanded="false"] .icon { transform: rotate(-90deg); }

.section__body {
    background: var(--surface);
    border-radius: var(--radius-row);
    margin: 0 var(--inset);
    overflow: hidden;
}

.section__footer {
    padding: 7px calc(var(--inset) + 4px) 0;
    font-size: 13px;
    color: var(--text-secondary);
}

.row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 11px 14px;
    text-align: left;
    position: relative;
    min-height: 44px;
    color: inherit;
}

.row + .row::before {
    content: "";
    position: absolute;
    top: 0;
    left: 14px;
    right: 0;
    height: 1px;
    background: var(--separator);
}

/* When a row leads with an icon, the separator starts after it — as it does on iOS. */
.row--icon + .row--icon::before { left: 50px; }

.row:active { background: rgba(255, 255, 255, 0.06); }
.row--static:active { background: none; cursor: default; }

.row__icon { width: 24px; flex: none; display: flex; justify-content: center; color: var(--tint); }
.row__icon .icon { width: 20px; height: 20px; }

.row__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.row__title { font-size: 17px; font-weight: 500; }
.row__subtitle { font-size: 12px; color: var(--text-secondary); }
.row__value { font-size: 17px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.row__chevron { color: var(--text-tertiary); }
.row__chevron .icon { width: 14px; height: 14px; stroke-width: 2.4; }

.row__more {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 34px;
    margin: -4px -6px -4px 0;
    color: var(--text-secondary);
    border-radius: 8px;
}
.row__more:active { background: rgba(255, 255, 255, 0.1); }

.prose {
    padding: 11px 14px;
    font-size: 15px;
    color: var(--text-primary);
}
.prose + .prose::before {
    content: "";
    display: block;
    height: 1px;
    background: var(--separator);
    margin: -11px -14px 11px;
}
.prose--secondary { color: var(--text-secondary); font-size: 13px; }

.footer-note {
    padding: 6px calc(var(--inset) + 4px) 0;
    font-size: 13px;
    color: var(--text-secondary);
    text-align: center;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.footer-note .version { font-size: 11px; color: var(--text-tertiary); }

/* ---------------------------------------------------------------- evidence badge */

.badge {
    display: inline-block;
    align-self: flex-start;
    font-size: 11px;
    font-weight: 500;
    padding: 3px 7px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--badge-colour) 18%, transparent);
    color: var(--badge-colour);
}

.badge[data-evidence="moderate"] { --badge-colour: #59d18b; }
.badge[data-evidence="emerging"] { --badge-colour: #57c6c4; }
.badge[data-evidence="preliminary"] { --badge-colour: #e2c65c; }
.badge[data-evidence="mixed"] { --badge-colour: #e8a15b; }
.badge[data-evidence="anecdotal"] { --badge-colour: var(--ramp-muted); }

/* ---------------------------------------------------------------- now playing bar */

.now-playing {
    position: sticky;
    bottom: 0;
    z-index: 15;
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px var(--inset);
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
    /* A step above the list rows rather than the same colour as them, so it reads as sitting on
       top of the page instead of being the last row of it. */
    background: #262d3d;
    border-top: 1px solid rgba(229, 232, 182, 0.3);
    box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.55);
    text-align: left;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}

.now-playing:active { background: #2e3648; }

.now-playing__art { width: 34px; height: 34px; border-radius: 8px; flex: none; }
.now-playing__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.now-playing__name { font-size: 15px; font-weight: 600; }
.now-playing__hz { font-size: 12px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.now-playing__toggle { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; }
.now-playing__toggle .icon { width: 26px; height: 26px; }

/* ---------------------------------------------------------------- the play screen */

/*
 * The play surface, presented as a panel over the dimmed list rather than as a screen of its own.
 *
 * The gradient still fills it, so it still reads as somewhere else — but it is now visibly a
 * thing you are inside and can step out of, which a full-bleed screen with a small chevron at the
 * bottom did not communicate.
 */
.session-scrim {
    position: fixed;
    inset: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: max(16px, env(safe-area-inset-top)) 16px
             max(16px, env(safe-area-inset-bottom));
    background: rgba(0, 0, 0, 0.55);
    animation: fade-in 0.22s ease;
}

.session__panel {
    position: relative;
    width: 100%;
    max-width: 460px;
    max-height: 100%;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    border-radius: 20px;
    padding: 44px 16px 26px;
    color: #fff;
    /* The gradient's top stop is translucent and would otherwise composite over the scrim. */
    background-color: #0b0e15;
    background-image: var(--play-gradient);
    /* Follows the beat rate, so it drifts rather than steps. */
    transition: background-image 1.6s linear;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    animation: panel-in 0.3s cubic-bezier(0.32, 0.72, 0, 1);
}

.session__close {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
}
.session__close .icon { width: 17px; height: 17px; stroke-width: 2.2; }
.session__close:active { background: rgba(255, 255, 255, 0.3); }

@keyframes panel-in {
    from { transform: scale(0.96); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
}

.session__inner {
    width: 100%;
    max-width: 420px;
    margin: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 26px;
}

.session__header { display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; }
.session__name { font-size: 22px; font-weight: 600; margin: 0; }
.session__purpose { font-size: 15px; color: rgba(255, 255, 255, 0.65); }

.pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    color: rgba(255, 255, 255, 0.7);
    padding: 5px 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
}
.pill .icon { width: 14px; height: 14px; }

.dial { position: relative; width: 218px; height: 218px; flex: none; }
.dial svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.dial__track { fill: none; stroke: rgba(255, 255, 255, 0.15); stroke-width: 8; }
.dial__progress {
    fill: none;
    stroke: rgba(255, 255, 255, 0.85);
    stroke-width: 8;
    stroke-linecap: round;
    transition: stroke-dashoffset 0.25s linear;
}
.dial__centre {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
}
.dial__value {
    font-family: var(--font-rounded);
    font-size: 50px;
    font-weight: 300;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.dial__caption { font-size: 12px; color: rgba(255, 255, 255, 0.6); }

.stats { display: flex; gap: 26px; }
.stat { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.stat__value { font-size: 15px; font-weight: 500; font-variant-numeric: tabular-nums; color: rgba(255, 255, 255, 0.9); }
.stat__label { font-size: 11px; color: rgba(255, 255, 255, 0.5); }

.times { display: flex; align-items: center; gap: 18px; }
.times__block { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.times__value { font-size: 20px; font-variant-numeric: tabular-nums; }
.times__label { font-size: 11px; color: rgba(255, 255, 255, 0.5); }

.circle-button {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
}
.circle-button:active { background: rgba(255, 255, 255, 0.28); }
.circle-button--small { width: 34px; height: 34px; }
.circle-button--small .icon { width: 16px; height: 16px; stroke-width: 2.4; }
.circle-button--large { width: 56px; height: 56px; }
.circle-button--large .icon { width: 24px; height: 24px; }

.session__warning {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    font-size: 13px;
    color: #f0b878;
    text-align: left;
    padding: 0 4px;
}
.session__warning .icon { width: 16px; height: 16px; margin-top: 1px; }

.session__hint { font-size: 11px; color: rgba(255, 255, 255, 0.45); }

.volume { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 300px; color: rgba(255, 255, 255, 0.7); }
.volume .icon { width: 17px; height: 17px; }

input[type="range"] {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.25);
    outline-offset: 6px;
}
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 999px;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border: 0;
    border-radius: 999px;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    cursor: pointer;
}

.controls { display: flex; align-items: center; gap: 18px; }

.stop-button {
    width: 126px;
    height: 56px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.9);
    color: #000;
    font-size: 17px;
    font-weight: 600;
}
.stop-button:active { background: #fff; }

.completed { display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; margin: auto 0; }
.completed .icon { width: 52px; height: 52px; stroke-width: 1.3; }
.completed__title { font-size: 22px; font-weight: 600; margin: 8px 0 0; }
.completed__name { font-size: 15px; color: rgba(255, 255, 255, 0.7); }
.completed__actions { display: flex; gap: 14px; margin-top: 22px; }
.completed__actions button { height: 52px; border-radius: 999px; font-size: 17px; font-weight: 600; }
.completed__again { width: 140px; background: rgba(255, 255, 255, 0.15); color: #fff; }
.completed__done { width: 120px; background: rgba(255, 255, 255, 0.9); color: #000; }

/* ---------------------------------------------------------------- sheets */

.scrim {
    position: fixed;
    inset: 0;
    z-index: 50;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    animation: fade-in 0.22s ease;
}

.sheet {
    width: 100%;
    max-width: 560px;
    max-height: 92vh;
    background: var(--app-background);
    border-radius: 14px 14px 0 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: slide-up 0.3s cubic-bezier(0.32, 0.72, 0, 1);
    padding-bottom: env(safe-area-inset-bottom);
}

.sheet__grabber {
    width: 36px;
    height: 5px;
    border-radius: 999px;
    background: var(--text-tertiary);
    margin: 6px auto 0;
    flex: none;
}

.sheet__body { overflow-y: auto; -webkit-overflow-scrolling: touch; padding-top: 4px; }

/* A sheet whose name is a sentence puts it here rather than in the bar, where it would wrap into
   the Done button on a narrow screen. */
.sheet__heading {
    font-size: 22px;
    font-weight: 600;
    margin: 2px var(--inset) 18px;
    line-height: 1.25;
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes slide-up { from { transform: translateY(100%); } to { transform: translateY(0); } }

@media (prefers-reduced-motion: reduce) {
    .scrim, .sheet, .session-scrim, .session__panel { animation: none; }
    .session__panel { transition: none; }
    .dial__progress { transition: none; }
}

/* ---------------------------------------------------------------- onboarding */

.onboarding { display: flex; flex-direction: column; height: min(560px, 88vh); }
.onboarding__pages { flex: 1; display: flex; overflow: hidden; }
.onboarding__page {
    flex: none;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    padding: 0 8px;
    transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
}
.onboarding__page .icon { width: 46px; height: 46px; color: var(--tint); stroke-width: 1.4; }
.onboarding__title { font-size: 22px; font-weight: 600; text-align: center; margin: 0; }
.onboarding__lines { display: flex; flex-direction: column; gap: 14px; padding: 0 32px; font-size: 15px; }
.onboarding__dots { display: flex; gap: 7px; justify-content: center; padding: 12px 0; }
.onboarding__dot { width: 7px; height: 7px; border-radius: 999px; background: var(--text-tertiary); }
.onboarding__dot[data-active="true"] { background: var(--tint); }

.primary-button {
    margin: 0 28px 24px;
    min-height: 50px;
    border-radius: 12px;
    background: var(--tint);
    color: #12151c;
    font-size: 17px;
    font-weight: 600;
}
.primary-button:active { opacity: 0.8; }

/* ---------------------------------------------------------------- odds and ends */

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.no-scroll { overflow: hidden; }

/* ---------------------------------------------------------------- wide layouts */

/*
 * Everything above this point is the phone app: a 16pt-inset grouped list in a single column.
 * Below, the same components are given room. The palette, the type scale and the card treatment
 * do not change — only how much of the page they are allowed to use.
 */

@media (min-width: 700px) {
    :root { --inset: clamp(20px, 4vw, 44px); }

    .large-title { font-size: 40px; margin: 10px 0 20px; }
    .navbar { padding-top: 16px; }

    .section__header { font-size: 17px; padding-bottom: 10px; }
    .section__footer, .footer-note { font-size: 14px; }
    .footer-note { padding-top: 12px; }
}

@media (min-width: 760px) {
    /* The presets stop being a list and become a board. Each row keeps its own layout and simply
       gains a card of its own, so nothing about the row markup changes. */
    .section--grid .section__body {
        background: none;
        border-radius: 0;
        overflow: visible;
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
        gap: 12px;
    }

    .section--grid .row {
        background: var(--surface);
        border-radius: 14px;
        padding: 18px 18px 16px;
        align-items: flex-start;
        gap: 14px;
        min-height: 92px;
    }

    .section--grid .row::before { display: none; }
    .section--grid .row:hover { background: #212736; }

    .section--grid .row__icon { width: 34px; }
    .section--grid .row__icon .icon { width: 26px; height: 26px; }
    .section--grid .row__text { gap: 4px; padding-top: 1px; }
    .section--grid .row__subtitle { font-size: 13px; }
    .section--grid .row__more { margin: -4px -4px 0 0; }

    /* Only the wide board has room for the grade on the face of the card. In the narrow list it
       stays where the phone puts it — one tap away, in the details. */
    .section--grid .row__badge { display: block; margin-top: 2px; }
}

.row__badge { display: none; }

@media (min-width: 700px) {
    /*
     * A panel is a contained thing, so it grows rather than rearranging. The two-column layout
     * that used to live here belonged to a full-bleed screen; inside a panel it read as a dialog
     * pretending to be a page.
     */
    .session__panel { max-width: 520px; padding: 48px 24px 30px; }
    .session__inner { max-width: 460px; gap: 30px; }
    .dial { width: 260px; height: 260px; }
    .dial__value { font-size: 58px; }
    .session__name { font-size: 26px; }
    .stats { gap: 36px; }
    .times__value { font-size: 22px; }
    .volume { max-width: 340px; }
}

@media (min-width: 700px) {
    /* A sheet sliding off the bottom edge of a desktop window reads as a phone affordance out of
       place. Above the breakpoint it becomes a centred dialog instead. */
    .scrim { align-items: center; padding: 24px; }
    .sheet {
        max-width: 620px;
        max-height: min(760px, 88vh);
        border-radius: 16px;
        animation: fade-in 0.22s ease;
        padding-bottom: 0;
    }
    .sheet__grabber { display: none; }
    .sheet .navbar { padding-top: 14px; }
    .onboarding { height: min(520px, 76vh); }
}

/* Pointer devices get hover feedback; touch devices must not, or the state sticks after a tap. */
@media (hover: hover) and (pointer: fine) {
    .row:hover:not(.row--static) { background: rgba(255, 255, 255, 0.05); }
    .row__more:hover { background: rgba(255, 255, 255, 0.09); }
    .navbar__button:hover { opacity: 0.7; }
    .now-playing:hover { background: #2e3648; }
    .cta:hover { background: color-mix(in srgb, var(--tint) 20%, transparent); }
    .circle-button:hover { background: rgba(255, 255, 255, 0.24); }
    .stop-button:hover { background: #fff; }
    .primary-button:hover { opacity: 0.9; }
}

/* The now-playing bar tracks the page rather than the list, so it spans the full width. Once it
   is out of the flow it stops pushing the page down, so the page has to make room for it. */
@media (min-width: 700px) {
    body.is-playing .app { padding-bottom: 96px; }

    .now-playing {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        max-width: none;
        justify-content: flex-start;
        padding-left: max(var(--inset), calc(50vw - 560px + var(--inset)));
        padding-right: max(var(--inset), calc(50vw - 560px + var(--inset)));
        z-index: 30;
    }
}

/* ---------------------------------------------------------------- the post-session question */

.feedback {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 24px;
    min-height: 360px;
    padding: 24px 0 24px;
    position: relative;
    overflow: hidden;
}

.feedback__question {
    font-size: 20px;
    font-weight: 600;
    text-align: center;
    margin: 0;
    padding: 0 28px;
    line-height: 1.3;
}

.feedback__scale { padding: 0 28px; display: flex; flex-direction: column; gap: 10px; }

/* The slider is white-on-translucent on the play screen; here it sits on the app background. */
.feedback__scale input[type="range"] { background: rgba(162, 171, 171, 0.28); }
.feedback__scale input[type="range"]::-webkit-slider-thumb { background: var(--tint); }
.feedback__scale input[type="range"]::-moz-range-thumb { background: var(--tint); }

.feedback__ends {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: var(--text-secondary);
}

.feedback__actions { display: flex; flex-direction: column; gap: 10px; }
.feedback__actions .primary-button { margin: 0 28px; }

.feedback__skip {
    font-size: 15px;
    color: var(--text-secondary);
    min-height: 32px;
}
.feedback__skip:active { opacity: 0.6; }

.feedback--thanks { justify-content: center; align-items: center; }
.feedback__thanks { display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
.feedback__tick { width: 46px; height: 46px; color: var(--tint); stroke-width: 1.5; }
.feedback__note { font-size: 15px; color: var(--text-secondary); margin: 0; padding: 0 28px; }

/*
 * A couple of dozen pieces falling and spinning once. Deterministic rather than random — spread
 * by the golden ratio, which still reads as irregular — so it is the same burst the phone draws.
 */
.confetti { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }

.confetti__piece {
    position: absolute;
    top: -30px;
    border-radius: 1.5px;
    animation: confetti-fall 1.6s ease-in forwards;
}

@keyframes confetti-fall {
    from { transform: translateY(0) rotate(0deg); opacity: 1; }
    to   { transform: translateY(420px) rotate(var(--spin, 360deg)); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .confetti { display: none; }
}

/* ---------------------------------------------------------------- what the apps add */

.feature {
    display: flex;
    gap: 12px;
    padding: 13px 14px;
    align-items: flex-start;
}

.feature { position: relative; }

/* On the second row and after, drawn at that row's own top edge — inset past the icon, as the
   list rows are. */
.feature + .feature::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50px;
    right: 0;
    height: 1px;
    background: var(--separator);
}
.feature__icon { width: 24px; flex: none; display: flex; justify-content: center; color: var(--tint); padding-top: 1px; }
.feature__icon .icon { width: 20px; height: 20px; }
.feature__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.feature__title { font-size: 16px; font-weight: 500; }
.feature__blurb { font-size: 13px; color: var(--text-secondary); line-height: 1.35; }

/*
 * The four platforms on one line. Four equal columns hold "Apple TV" and "Mac App Store" at
 * 375pt with the store name on two lines, which is the narrowest case that has to work.
 */
.platforms {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
}

.platform {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 15px 4px 13px;
    text-align: center;
    text-decoration: none;
    color: inherit;
    border-radius: 10px;
}

.platform + .platform { box-shadow: inset 1px 0 0 var(--separator); }
.platform .icon { width: 26px; height: 26px; color: var(--tint); }
.platform__name { font-size: 13px; font-weight: 500; }
.platform__store { font-size: 11px; color: var(--text-tertiary); line-height: 1.25; }
.platform:active { background: rgba(255, 255, 255, 0.06); }

@media (hover: hover) and (pointer: fine) {
    .platform:hover { background: rgba(255, 255, 255, 0.05); }
    .cta:hover { background: color-mix(in srgb, var(--tint) 16%, transparent); }
}
