/* ---------------------------------------------------------------------------
   settings.css — AREA: SETTINGS  (owns js/ui/settings.js, js/ui/onboarding.js,
                                   js/ui/celebrate.js, css/settings.css)

   Settings and its sub-pages, the first-run flow, and the celebration
   takeover. Declares NO custom property: every value here is read from
   tokens.css, so the brutal face and the dark ground arrive for free and this
   file never has to branch on either — except where the two themes genuinely
   disagree, which is exactly twice: the theme preview (whose whole job is to
   show the disagreement) and the trophy's shine (a gradient sweep, which is
   the one thing the flat face does not do).

   Naming: .set-* settings, .onb-* onboarding, .cel-* the celebration.

   Motion rules, the same three effects.css keeps: transform and opacity only,
   every animation has a reduced-motion answer at the bottom of this file, and
   nothing decorative may take a pointer event.
--------------------------------------------------------------------------- */

/* =========================================================================
   PAGE SCAFFOLD
   ========================================================================= */

.set-page {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

.set-group { display: flex; flex-direction: column; gap: var(--sp-2); }
.set-group__title { padding-inline: var(--sp-1); }

/* The card is .c-card--flush, so the rows draw their own dividers. */
.set-group__body > * + * { border-top: var(--bw) solid var(--c-line); }

.set-version,
.set-footnote {
  text-align: center;
  padding-inline: var(--sp-4);
  text-wrap: balance;
}

/* =========================================================================
   ROWS
   A row is a <button> when it does something and a <div> when it does not;
   the class does not care, which is what keeps both accessible.
   ========================================================================= */

.set-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 56px;
  padding: var(--sp-3) var(--sp-4);
  text-align: start;
  color: var(--c-ink);
  background: transparent;
  transition: background var(--d-2) var(--e-out);
}
button.set-row:hover:not(:disabled) { background: var(--c-surface-2); }
button.set-row:active:not(:disabled) { background: var(--c-surface-sunken); }
.set-row:disabled { opacity: 0.55; }

.set-row__lead {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
}
.set-row__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.set-row__label { font-size: var(--fs-md); font-weight: var(--fw-semibold); }
/* Hints wrap. No row in twelve languages may assume a short string. */
.set-row__sub { white-space: normal; text-wrap: pretty; }

.set-row__value {
  flex: 0 1 auto;
  max-width: 46%;
  font-size: var(--fs-sm);
  color: var(--c-ink-3);
  text-align: end;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.set-row__chevron { flex: none; color: var(--c-ink-3); display: flex; }

/* The tick on a chosen radio row. Reserved even when empty, so choosing one
   never shifts the label sideways. */
.set-row__check {
  flex: none;
  display: flex;
  color: var(--c-accent);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity var(--d-2) var(--e-out), transform var(--d-2) var(--e-spring);
}
.set-row[aria-checked="true"] .set-row__check { opacity: 1; transform: none; }
.set-row--radio[aria-checked="true"] { background: var(--c-accent-softer); }
.set-row--radio[aria-checked="true"] .set-row__label { color: var(--c-accent-deep); }

/* A switch row: the control is the row, so the target is 56px tall and the
   .c-switch inside is decoration driven by the row's own state. */
.set-row--switch .c-switch { pointer-events: none; }
.set-row--switch[aria-checked="true"] .c-switch {
  background: var(--c-accent);
  border-color: var(--c-accent-line);
}
.set-row--switch[aria-checked="true"] .c-switch::after { transform: translateX(20px); }
[dir="rtl"] .set-row--switch[aria-checked="true"] .c-switch::after { transform: translateX(-20px); }
.set-row:disabled .c-switch { opacity: 0.45; }
.set-row--bare { padding-inline: 0; }
.set-row--static { cursor: default; }

/* The alarm list: a radio row plus its own preview button, side by side —
   never a button inside a button. */
.set-row-group { display: flex; align-items: center; transition: background var(--d-2) var(--e-out); }
.set-row-group > .set-row { flex: 1 1 auto; }
.set-row-group.is-checked { background: var(--c-accent-softer); }
.set-row-group.is-checked > .set-row--radio { background: transparent; }
.set-row__preview { flex: none; margin-inline-end: var(--sp-2); }

/* =========================================================================
   THE PROFILE SUMMARY
   ========================================================================= */

.set-hero {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  padding: var(--sp-4);
  text-align: start;
  background: var(--c-surface);
  border: var(--card-border);
  border-radius: var(--r-card);
  box-shadow: var(--sh-card);
  transition: transform var(--d-1) var(--e-out), box-shadow var(--d-2) var(--e-out);
}
.set-hero:hover { background: var(--c-surface-2); }
.set-hero:active { transform: translate(var(--btn-translate), var(--btn-translate)); box-shadow: var(--sh-press); }
.set-hero__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.set-hero__name {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.set-hero__meta { white-space: normal; }
.set-hero__trail { flex: none; color: var(--c-ink-3); display: flex; }
.set-hero__avatar { font-size: var(--fs-2xl); }

/* =========================================================================
   BLOCKS — a card that holds one control and its label
   ========================================================================= */

.set-block { display: flex; flex-direction: column; gap: var(--sp-3); }
.set-block__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.set-block__head--spaced { margin-top: var(--sp-3); }
.set-block__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--c-ink-2);
  text-transform: var(--caps-transform);
  letter-spacing: var(--ls-normal);
}
.set-block__label--spaced { margin-top: var(--sp-2); }

.set-num {
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  line-height: 1;
  color: var(--c-ink);
}
.set-num__unit { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--c-ink-3); }

/* =========================================================================
   DURATIONS
   The break lengths run in the break colour, so "red means focus" survives
   the settings screen too.
   ========================================================================= */

.set-duration__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.set-presets { gap: var(--sp-2); }
.set-preset { min-width: 3rem; justify-content: center; font-variant-numeric: tabular-nums; }

/* The chosen preset wears the same colour as the track it sets. */
.set-duration[data-kind="short"] .set-preset[aria-pressed="true"] {
  background: var(--c-break);
  border-color: var(--c-break);
  color: var(--c-accent-ink);
}
.set-duration[data-kind="long"] .set-preset[aria-pressed="true"] {
  background: var(--c-long);
  border-color: var(--c-long);
  color: var(--c-accent-ink);
}

.set-duration[data-kind="short"] .c-slider::-webkit-slider-runnable-track {
  background: linear-gradient(to right, var(--c-break) var(--fill, 50%), var(--c-track) var(--fill, 50%));
}
.set-duration[data-kind="short"] .c-slider::-moz-range-progress { background: var(--c-break); }
.set-duration[data-kind="short"] .c-slider::-webkit-slider-thumb { border-color: var(--c-break); }
.set-duration[data-kind="short"] .c-slider::-moz-range-thumb { border-color: var(--c-break); }

.set-duration[data-kind="long"] .c-slider::-webkit-slider-runnable-track {
  background: linear-gradient(to right, var(--c-long) var(--fill, 50%), var(--c-track) var(--fill, 50%));
}
.set-duration[data-kind="long"] .c-slider::-moz-range-progress { background: var(--c-long); }
.set-duration[data-kind="long"] .c-slider::-webkit-slider-thumb { border-color: var(--c-long); }
.set-duration[data-kind="long"] .c-slider::-moz-range-thumb { border-color: var(--c-long); }

/* The cycle preview: N focus dots and the long break they earn. */
.set-cycle { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.set-cycle__dot { width: 10px; height: 10px; }
.set-cycle__long {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 20px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--c-break) 18%, var(--c-surface));
  color: var(--c-break);
  margin-inline-start: var(--sp-1);
}

/* Strict mode's four rules, stated rather than offered. */
.set-rules { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.set-rule { color: var(--c-ink-2); }
.set-rule > svg { color: var(--c-ok); }

/* =========================================================================
   SEGMENTED CONTROLS
   components.css styles the thumb and [aria-selected]; these are radio
   groups, so the selected colour needs saying once here.
   ========================================================================= */

/* The thumb is placed in pixels; clipping is the belt to that braces, so a
   stale measurement can never widen the page. */
.set-seg { overflow: hidden; }
.set-seg .c-seg__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
}
.set-seg .c-seg__btn[aria-checked="true"] { color: var(--c-accent-ink); }
.set-seg .c-seg__btn > svg { width: 16px; height: 16px; }

/* =========================================================================
   SOUND
   ========================================================================= */

.set-volume { display: flex; align-items: center; gap: var(--sp-2); color: var(--c-ink-3); }
.set-volume .c-slider { flex: 1 1 auto; min-width: 0; }

.set-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-2);
}
@media (min-width: 460px) { .set-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.set-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  min-height: 74px;
  padding: var(--sp-2);
  border-radius: var(--r-md);
  border: var(--bw) solid var(--c-line);
  background: var(--c-surface-2);
  color: var(--c-ink-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  text-align: center;
  transition:
    background var(--d-2) var(--e-out),
    border-color var(--d-2) var(--e-out),
    color var(--d-2) var(--e-out),
    transform var(--d-1) var(--e-out);
}
.set-tile__name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-tile:hover { border-color: var(--c-line-strong); }
.set-tile:active { transform: scale(0.96); }
.set-tile[aria-pressed="true"] {
  background: var(--c-accent-soft);
  border-color: var(--c-accent-line);
  color: var(--c-accent-deep);
}
.set-tile[aria-pressed="true"] .set-tile__art { color: var(--c-accent); }

/* =========================================================================
   NOTIFICATIONS
   ========================================================================= */

.set-permit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}
.set-permit__art {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: var(--r-lg);
  background: var(--c-surface-sunken);
  color: var(--c-ink-3);
}
.set-permit__body { flex: 1 1 12rem; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.set-permit__state { font-weight: var(--fw-semibold); }
.set-permit[data-state="granted"] .set-permit__art { background: var(--c-ok-soft); color: var(--c-ok); }
.set-permit[data-state="denied"] .set-permit__art { background: var(--c-danger-soft); color: var(--c-danger); }
.set-permit > .c-btn { flex: 1 1 100%; }

.set-notes { display: flex; flex-direction: column; gap: var(--sp-1); padding-inline: var(--sp-2); }
.set-note {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--c-ink-3);
}
.set-note > svg { flex: none; margin-top: 2px; color: var(--c-ok); }

/* =========================================================================
   THEME PREVIEW
   The one place in the app where a component is deliberately NOT theme
   agnostic: each card wears the shape language of the face it offers, so the
   choice is shown rather than described. Colour still comes from the tokens,
   because the preview must not lie about the accent already chosen.
   ========================================================================= */

.set-themes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }

.set-theme {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  text-align: start;
  background: var(--c-surface);
  border: var(--card-border);
  border-radius: var(--r-card);
  box-shadow: var(--sh-card);
  transition: border-color var(--d-2) var(--e-out), box-shadow var(--d-2) var(--e-out), transform var(--d-1) var(--e-out);
}
.set-theme:active { transform: translate(var(--btn-translate), var(--btn-translate)); }
.set-theme[aria-pressed="true"] { border-color: var(--c-accent); box-shadow: var(--sh-accent); }
.set-theme__name { font-weight: var(--fw-bold); }
.set-theme__hint { white-space: normal; }

.set-theme__art {
  position: relative;
  display: block;
  height: 88px;
  border-radius: var(--r-sm);
  background: var(--c-bg);
  overflow: hidden;
}
.set-theme__card {
  position: absolute;
  inset-inline-start: 10px;
  top: 14px;
  width: 62px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--c-surface);
}
.set-theme__bar { height: 6px; background: var(--c-line-strong); }
.set-theme__bar--short { width: 58%; }
.set-theme__chip {
  position: absolute;
  inset-inline-end: 12px;
  bottom: 12px;
  width: 40px;
  height: 18px;
  background: var(--c-accent);
}
.set-theme__ring {
  position: absolute;
  inset-inline-end: 14px;
  top: 12px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 5px solid var(--c-accent);
  border-inline-end-color: var(--c-track);
  border-bottom-color: var(--c-track);
}

/* Studio: soft radii, a diffuse shadow, nothing outlined. */
.set-theme[data-face="studio"] .set-theme__card {
  border-radius: 10px;
  box-shadow: 0 6px 14px color-mix(in srgb, var(--c-ink) 16%, transparent);
}
.set-theme[data-face="studio"] .set-theme__bar { border-radius: 99px; }
.set-theme[data-face="studio"] .set-theme__chip {
  border-radius: 99px;
  box-shadow: 0 4px 10px color-mix(in srgb, var(--c-accent) 45%, transparent);
}

/* Brutal: square, outlined, and falling into a hard offset shadow. */
.set-theme[data-face="brutal"] .set-theme__card {
  border-radius: 2px;
  border: 2px solid var(--c-ink);
  box-shadow: 4px 4px 0 var(--c-ink);
}
.set-theme[data-face="brutal"] .set-theme__bar { border-radius: 0; background: var(--c-ink); }
.set-theme[data-face="brutal"] .set-theme__chip {
  border-radius: 2px;
  border: 2px solid var(--c-ink);
  box-shadow: 3px 3px 0 var(--c-ink);
}
.set-theme[data-face="brutal"] .set-theme__ring { border-radius: 2px; }

/* Six hues, one row, at 360px too: fixed 44px swatches wrap to five and one,
   which reads as an accident rather than a palette. */
.set-accents {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--sp-2);
}
.set-accents .c-swatch { width: 100%; }

/* Eight avatar hues: four and four, never five and a stray three. */
.set-palette {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-2);
}
.set-palette .c-swatch { width: 100%; }
@media (min-width: 460px) { .set-palette { grid-template-columns: repeat(8, minmax(0, 1fr)); } }

/* =========================================================================
   LANGUAGE
   ========================================================================= */

.set-flag {
  flex: none;
  display: inline-flex;
  width: 24px;
  height: 16px;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--c-ink) 18%, transparent);
}
:root[data-theme="brutal"] .set-flag { border-radius: 0; box-shadow: 0 0 0 1.5px var(--c-ink); }

/* =========================================================================
   PROFILE
   ========================================================================= */

.set-profile-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  text-align: center;
  background: var(--c-accent-softer);
  border-color: var(--c-accent-line);
}
.set-avatar-wrap { position: relative; display: inline-flex; }
.set-avatar { font-size: var(--fs-3xl); box-shadow: var(--sh-2); }
.set-avatar[data-kind="initials"] { font-size: var(--fs-2xl); letter-spacing: var(--ls-tight); }
/* 36px is as large as the badge can be without swallowing the corner of the
   avatar it sits on, so the box stays 36 and the ::before below hands the
   thumb the --tap the rest of the app keeps. */
.set-avatar__shuffle {
  position: absolute;
  inset-inline-end: -6px;
  bottom: -6px;
  width: 36px;
  height: 36px;
  background: var(--c-surface);
  border: var(--card-border);
  box-shadow: var(--sh-1);
  color: var(--c-ink-2);
}
.set-avatar__shuffle::before {
  content: "";
  position: absolute;
  inset: calc((var(--tap) - 36px) / -2);
}
.set-hero__greeting { font-size: var(--fs-lg); font-weight: var(--fw-semibold); text-wrap: balance; }

.set-emoji {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--sp-2);
}
.set-emoji__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  font-size: 21px;
  line-height: 1;
  border-radius: var(--r-md);
  border: var(--bw) solid var(--c-line);
  background: var(--c-surface-2);
  transition: background var(--d-2) var(--e-out), border-color var(--d-2) var(--e-out), transform var(--d-1) var(--e-spring);
}
.set-emoji__btn:hover { transform: scale(1.06); }
.set-emoji__btn[aria-checked="true"] { background: var(--c-accent-soft); border-color: var(--c-accent); }

.set-stats { padding: var(--sp-4); }

/* =========================================================================
   DATA
   ========================================================================= */

.set-buttons { flex-wrap: wrap; }
.set-buttons > .c-btn { flex: 1 1 10rem; }
.set-filename { font-family: var(--font-mono); word-break: break-all; }

.set-code {
  max-height: 13rem;
  overflow: auto;
  margin: 0;
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--c-surface-sunken);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  line-height: 1.5;
  color: var(--c-ink-2);
  white-space: pre;
}

/* The file input stays in the DOM and out of the tab order: the visible
   control is a real button that clicks it. */
.set-file__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  opacity: 0;
  pointer-events: none;
}

.set-diff {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--c-surface-sunken);
  font-size: var(--fs-sm);
  animation: fx-rise var(--d-3) var(--e-out);
}
.set-diff[data-tone="bad"] { background: var(--c-danger-soft); color: var(--c-danger); }
.set-diff__line { display: flex; align-items: flex-start; gap: var(--sp-2); }
.set-diff__line > svg { flex: none; margin-top: 2px; }

.set-warn { color: var(--c-danger); font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.set-confirm .c-input { text-transform: uppercase; letter-spacing: var(--ls-wide); }
.set-danger { border-color: color-mix(in srgb, var(--c-danger) 40%, var(--c-line)); }
.set-raw { min-height: 40vh; font-family: var(--font-mono); font-size: var(--fs-2xs); }

/* =========================================================================
   ABOUT & SHORTCUTS
   ========================================================================= */

.set-about-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  text-align: center;
}
.set-about__mark { margin-bottom: var(--sp-1); }
.set-keys { flex: none; display: flex; gap: 4px; align-items: center; }

/* =========================================================================
   ONBOARDING
   ========================================================================= */

.onb {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding-top: var(--sa-t);
}
.onb-top {
  display: flex;
  justify-content: flex-end;
  min-height: 44px;
  padding: var(--sp-2) max(var(--sp-3), var(--sa-r)) 0 max(var(--sp-3), var(--sa-l));
}
.onb-viewport { flex: 1 1 auto; min-height: 0; overflow: hidden; }
/* paint() always writes a translate3d here, so the track is promoted by the
   transform itself — a standing will-change only made the layer permanent. */
.onb-track { display: flex; height: 100%; }

.onb-slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.onb-slide__inner {
  min-height: 100%;
  max-width: 30rem;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding: var(--sp-5) max(var(--sp-5), var(--sa-r)) var(--sp-6) max(var(--sp-5), var(--sa-l));
  text-align: center;
}
.onb-title {
  font-size: clamp(1.5rem, 7vw, 1.875rem);
  text-wrap: balance;
}
.onb-body { max-width: 34ch; text-wrap: pretty; }
.onb-caption { text-transform: var(--caps-transform); letter-spacing: var(--ls-wide); }

.onb-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) max(var(--sp-4), var(--sa-r)) calc(var(--sp-4) + var(--sa-b)) max(var(--sp-4), var(--sa-l));
}
.onb-dots { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; }
.onb-dot {
  width: 26px;
  height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.onb-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--c-line-strong);
  transition: transform var(--d-2) var(--e-spring), background var(--d-2) var(--e-out);
}
.onb-dot[aria-current="true"]::before { background: var(--c-accent); transform: scale(1.6); }
.onb-back.is-invisible { visibility: hidden; }
/* Twelve languages share this button and "Commencer à me concentrer" is not the
   width of "Next". .c-btn is nowrap because most buttons sit in a column that
   can grow sideways; this one is wedged between a back arrow and a pager, so it
   takes a second line rather than pushing the row past the viewport. */
.onb-next {
  min-width: 7.5rem;
  white-space: normal;
  line-height: var(--lh-tight);
  text-wrap: balance;
}
.onb-next--final { min-width: 9rem; }

/* The row cannot fit a small phone: 44px of back arrow + five 26px dots + a
   9rem CTA + the gutters is 366px of hard minimum, and .screen computes
   overflow-x: auto — so the very first thing a new visitor sees would scroll
   sideways. Below 380px the CTA takes a line of its own instead; the pager
   keeps its row at full size and nothing has to be shaved to fit. */
@media (max-width: 379px) {
  .onb-bar { flex-wrap: wrap; }
  .onb-next { flex: 1 0 100%; }
}

/* --- the ring that draws itself ------------------------------------------ */
.onb-hero { position: relative; width: 148px; height: 148px; display: grid; place-items: center; }
.onb-ring { width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.onb-ring__track { fill: none; stroke: var(--c-track); stroke-width: 8; }
.onb-ring__value {
  fill: none;
  stroke: var(--c-accent);
  stroke-width: 8;
  stroke-linecap: round;
  stroke-dasharray: 327;
  stroke-dashoffset: 327;
}
.onb-ring.is-drawn .onb-ring__value { animation: onb-draw var(--d-5) var(--e-out) forwards; }
.onb-hero__glyph { position: absolute; color: var(--c-accent); display: flex; }

@keyframes onb-draw { from { stroke-dashoffset: 327; } to { stroke-dashoffset: 0; } }

/* --- the cycle diagram --------------------------------------------------- */
.onb-cycle { display: flex; align-items: center; gap: var(--sp-2); }
.onb-cycle__block {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-md);
  background: var(--c-accent-soft);
  color: var(--c-accent-deep);
  border: var(--bw) solid var(--c-accent-line);
}
.onb-cycle__block--long {
  width: 54px;
  background: color-mix(in srgb, var(--c-break) 16%, var(--c-surface));
  color: var(--c-break);
  border-color: color-mix(in srgb, var(--c-break) 40%, var(--c-line));
}
.onb-cycle.is-playing .onb-cycle__block {
  animation: onb-pop var(--d-4) var(--e-spring) backwards;
  animation-delay: calc(var(--i, 0) * 160ms);
}
@keyframes onb-pop { from { opacity: 0; transform: scale(0.55); } to { opacity: 1; transform: none; } }

/* --- the rhythm gauge ---------------------------------------------------- */
.onb-gauge-wrap { position: relative; width: 148px; height: 148px; display: grid; place-items: center; }
.onb-gauge { width: 100%; height: 100%; transform: rotate(-90deg); }
.onb-gauge__track { fill: none; stroke: var(--c-track); stroke-width: 10; }
.onb-gauge__focus,
.onb-gauge__break {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  transition: stroke-dasharray var(--d-3) var(--e-out), stroke-dashoffset var(--d-3) var(--e-out);
}
.onb-gauge__focus { stroke: var(--c-focus); }
.onb-gauge__break { stroke: var(--c-break); }
.onb-gauge__label {
  position: absolute;
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  color: var(--c-ink);
}

.onb-numbers { display: flex; gap: var(--sp-5); flex-wrap: wrap; justify-content: center; }
.onb-number { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); }
.onb-number__label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-ink-3);
}

/* --- name and face ------------------------------------------------------- */
.onb-avatar-wrap { display: inline-flex; }
.onb-avatar { font-size: var(--fs-3xl); box-shadow: var(--sh-2); }
.onb-greeting { font-size: var(--fs-lg); font-weight: var(--fw-semibold); text-wrap: balance; }
.onb-field { width: min(100%, 20rem); text-align: start; }
/* A grid, not a scroller: a horizontally scrolling row inside a deck that is
   itself dragged sideways is two gestures fighting over one finger. */
.onb-emoji {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--sp-2);
  width: min(100%, 20rem);
  padding: 2px;
}
.onb-emoji__btn {
  flex: none;
  width: 100%;
  height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 21px;
  line-height: 1;
  border-radius: var(--r-pill);
  border: var(--bw) solid var(--c-line);
  background: var(--c-surface-2);
  transition: transform var(--d-1) var(--e-spring), background var(--d-2) var(--e-out), border-color var(--d-2) var(--e-out);
}
.onb-emoji__btn[aria-checked="true"] { background: var(--c-accent-soft); border-color: var(--c-accent); transform: scale(1.08); }
/* Narrow enough to break four and four rather than six and a ragged two. */
.onb-colours { justify-content: center; max-width: 15rem; }

/* --- the look ------------------------------------------------------------ */
.onb-themes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); width: min(100%, 24rem); }
.onb-theme .set-theme__art { height: 74px; }
.onb-modes { justify-content: center; }

/* =========================================================================
   CELEBRATION
   ========================================================================= */

.cel-stage {
  position: relative;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding:
    calc(var(--sa-t) + var(--sp-7))
    max(var(--sp-5), var(--sa-r))
    calc(var(--sa-b) + var(--sp-6))
    max(var(--sp-5), var(--sa-l));
}

.cel-wash {
  position: absolute;
  inset: -20%;
  pointer-events: none;
  background: radial-gradient(circle at 50% 42%, var(--c-accent-soft) 0%, transparent 62%);
  animation: cel-wash var(--d-5) var(--e-out) both;
}
.cel-stage[data-kind="cycle"] .cel-wash,
.cel-stage[data-kind="session"] .cel-wash {
  background: radial-gradient(circle at 50% 42%, color-mix(in srgb, var(--c-break) 22%, transparent) 0%, transparent 62%);
}
@keyframes cel-wash { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }

.cel-close { position: absolute; top: calc(var(--sa-t) + var(--sp-2)); inset-inline-end: var(--sp-2); z-index: 1; }

.cel-body {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  max-width: 26rem;
  text-align: center;
}
.cel-title { font-size: clamp(1.6rem, 8vw, 2.25rem); text-wrap: balance; }
.cel-text { max-width: 32ch; text-wrap: pretty; }

/* --- the trophy ---------------------------------------------------------- */
.cel-trophy-wrap { width: min(46vw, 164px); }
.cel-trophy { width: 100%; height: auto; stroke: var(--c-ink); }
.cel-trophy__fill { fill: var(--c-accent); stroke: none; }
.cel-trophy__piece {
  transform-box: fill-box;
  transform-origin: center;
  animation: cel-rise var(--d-4) var(--e-spring) backwards;
}
.cel-trophy__handles { animation-delay: 0ms; }
.cel-trophy__cup { animation-delay: 60ms; }
.cel-trophy__base { animation-delay: 120ms; }
@keyframes cel-rise { from { opacity: 0; transform: translateY(10px) scale(0.82); } to { opacity: 1; transform: none; } }

.cel-trophy__shine {
  fill: #ffffff;
  stroke: none;
  opacity: 0.5;
  transform-box: fill-box;
  transform-origin: center;
  animation: cel-shine 2.6s var(--e-in-out) 700ms infinite;
}
@keyframes cel-shine {
  0%, 60%, 100% { opacity: 0; transform: translateX(-14px); }
  70% { opacity: 0.55; }
  85% { opacity: 0; transform: translateX(34px); }
}
/* The flat face does not do gradient sweeps. */
:root[data-theme="brutal"] .cel-trophy__shine { display: none; }

/* --- the numbers --------------------------------------------------------- */
.cel-stats { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2); width: 100%; }
.cel-stat {
  flex: 1 1 5.5rem;
  min-width: 5.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: var(--sp-3) var(--sp-2);
  border-radius: var(--r-card);
  border: var(--card-border);
  background: color-mix(in srgb, var(--c-surface) 86%, transparent);
  box-shadow: var(--sh-card);
}
.cel-stat__art { color: var(--c-accent); display: flex; }
.cel-stat__value { font-size: var(--fs-xl); font-weight: var(--fw-bold); line-height: 1.1; }
.cel-stat__label { font-size: var(--fs-2xs); color: var(--c-ink-3); }

.cel-actions { width: 100%; }

/* --- the auto-return ----------------------------------------------------- */
.cel-timer-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); }
.cel-timer {
  width: min(100%, 11rem);
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--c-track);
  overflow: hidden;
}
.cel-timer__fill {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--c-accent);
  transform-origin: left center;
  transform: scaleX(1);
}
[dir="rtl"] .cel-timer__fill { transform-origin: right center; }
.cel-timer.is-static .cel-timer__fill { opacity: 0.45; }
@keyframes cel-deplete { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* --- the still answer to confetti ---------------------------------------- */
.cel-fan {
  position: absolute;
  bottom: 0;
  inset-inline-start: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}
.cel-fan__ribbon {
  position: absolute;
  bottom: 0;
  inset-inline-start: -3px;
  width: 6px;
  height: 92px;
  border-radius: var(--r-pill);
  transform-origin: bottom center;
  opacity: 0.45;
}

/* =========================================================================
   REDUCED MOTION
   base.css already crushes durations, which is right for a transition and
   wrong for anything that must end somewhere: a 1 ms draw is a flicker. So
   the ring is simply drawn, the trophy is simply there, and the shine — an
   infinite loop — is switched off by name.
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) .onb-ring__value { animation: none; stroke-dashoffset: 0; }
  :root:not([data-motion="full"]) .onb-cycle.is-playing .onb-cycle__block,
  :root:not([data-motion="full"]) .cel-trophy__piece,
  :root:not([data-motion="full"]) .cel-wash { animation: none; opacity: 1; transform: none; }
  :root:not([data-motion="full"]) .cel-trophy__shine { display: none; }
  :root:not([data-motion="full"]) .onb-track { transition: none; }
}

:root[data-motion="reduced"] .onb-ring__value { animation: none; stroke-dashoffset: 0; }
:root[data-motion="reduced"] .onb-cycle.is-playing .onb-cycle__block,
:root[data-motion="reduced"] .cel-trophy__piece,
:root[data-motion="reduced"] .cel-wash { animation: none; opacity: 1; transform: none; }
:root[data-motion="reduced"] .cel-trophy__shine { display: none; }
:root[data-motion="reduced"] .onb-track { transition: none; }

/* =========================================================================
   WIDER SCREENS
   The phone is the design; a desktop gets air and two columns where two
   columns actually help.
   ========================================================================= */

@media (min-width: 700px) {
  .set-emoji { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cel-trophy-wrap { width: 176px; }
  .onb-slide__inner { gap: var(--sp-5); }
}
