/* Hushly.css
   The Native build's page layer. Component_App.css is the system (the GPRNT App design system); this file
   lays the screens out like an installed phone app and fills the few gaps the system has no component for
   (a page shell, a sticky bar and foot, a sheet that rises from the bottom, Pip, a night timeline, the
   breathing circle). The recording screens (orb, ripples, ring) live in Listening.css, not here.
   House rules, all of them from the App design system:
   - every colour, gap, padding and radius is a system token: var(--text-*), var(--surface-*), var(--primary*),
     var(--secondary*), var(--outline-*), var(--status-*), var(--space-*), var(--space-rounded-corner),
     var(--type-*), var(--shadow-*). No raw colour values, no bare px for padding, margin, gap or radius
   - type is set only as font: var(--type-*), or by a .type-* class in the markup
   - a system component is never edited: a page rule sits under an hu- class or a compound selector
   Where the system has no token, the nearest real token is used and the line says so.
   Classes here start with hu- so they can never collide with a system class. */

:root {
  /* The phone column. No width token exists; the system's container width (343) plus 88 is about 430,
     the original shell, on the system's own steps. */
  --hu-column: calc(var(--space-container-width) + var(--space-22));
  /* The bottom navigation's height without the home-indicator area. 56 is Space_14. */
  --hu-nav: var(--space-14);
  --hu-safe-top: env(safe-area-inset-top, 0px);
  --hu-safe-bottom: env(safe-area-inset-bottom, 0px);
  /* The gap between the window and the phone column. None on a phone; a desktop window sets it (see Page and shell). */
  --hu-frame: var(--space-0);
  /* The glyph on a soft brand tile. --text-brand-primary alone is about 2.4 to 1 on the light container, so it is
     pulled toward the text colour: darker in light mode, still bright on the dark container. */
  --hu-tileInk: color-mix(in srgb, var(--text-brand-primary) 70%, var(--text-on-surface));
  /* Inks that clear 4.5 to 1 on every surface the page uses, in light and in dark (checked on the surface, container-lowest
     to container-high and the soft status fills). The system's own brand blue, dim grey and alert red are 2.4 to 4.2 to 1
     on its light surfaces, so the page layer points the system tokens at these inside the shell and the sheets (see
     Contrast below). Each is the system's token pulled toward a stronger one, as --hu-tileInk is, and no raw colour. */
  --hu-linkInk: color-mix(in srgb, var(--text-brand-primary) 60%, var(--text-on-surface));
  --hu-dimInk: color-mix(in srgb, var(--text-on-surface-variant) 85%, var(--surface-container-lowest));
  --hu-alertInk: var(--status-alert-bold);
  /* The label on the brand gradient stays the system's white (the owner's design system draws its primary button that
     way; white is about 2.4 to 1 on the cyan end, a known gap left to the system). The alert button and badge are
     another matter: in light their fill is the bold red, which white passes; in dark the fills stay and the label is the
     dark inverse text (see the dark blocks below). */
  --hu-onBrand: var(--text-on-primary);
  /* Dark text on Pip's cream badge, which stays cream in both themes. */
  --hu-onCream: var(--text-on-surface);
  --hu-alertFill: var(--status-alert-bold);
  --hu-onAlert: var(--text-on-primary);
  /* The least size of a thing a finger must hit: 44, which is Space_10 plus Space_1 (no 44 token exists). */
  --hu-tap: calc(var(--space-10) + var(--space-1));
  --hu-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  color-scheme: light dark;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
/* The shadow under the desktop phone column. The system's level 2 is a light grey (its dark value was never read), which
   glows on a dark page, so in dark the quieter level 1 stands in. */
:root { --hu-lift: var(--shadow-level-2); }
:root[data-theme="dark"] { --hu-lift: var(--shadow-level-1); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --hu-lift: var(--shadow-level-1); } }
/* In dark the soft red is light enough for the dark inverse text, so the alert fill stays the system's. */
:root[data-theme="dark"] { --hu-onCream: var(--text-inverse-on-surface); --hu-alertFill: var(--status-alert-base); --hu-onAlert: var(--text-inverse-on-surface); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --hu-onCream: var(--text-inverse-on-surface); --hu-alertFill: var(--status-alert-base); --hu-onAlert: var(--text-inverse-on-surface); } }

/* ---------- Motion switches ----------
   Settings > Motion puts Full, Gentle or Off in data-motion on :root (Theme.js). The phone's reduce-motion
   setting counts as Off while nothing is chosen. Every animation below reads these, so one place turns
   motion up or down: Full moves, Gentle only fades (slower and softer), Off keeps everything still.
   Pace-keeping loops (the breathing circle) and the spinner keep going in every mode: they are information,
   not decoration. Nothing marked IsSafety ever animates (see the end of this file). */

:root {
  --hu-move: 1;
  --hu-press: 0.97;
  --hu-dur: 260ms;
  --hu-sheetDur: 320ms;
  --hu-tdur: 140ms;
  --hu-grow: 360ms;
  --hu-breath: 0.24;
  --hu-aPush: hu-push;
  --hu-aBack: hu-back;
  --hu-aTab: hu-fade;
  --hu-aSheet: hu-sheetRise;
  --hu-aPop: hu-sheetPop;
  --hu-aFade: hu-fade;
  --hu-aBlink: hu-blink;
  --hu-aZ: hu-sleepZ;
}
:root[data-motion="Gentle"] {
  --hu-move: 0;
  --hu-press: 1;
  --hu-dur: 200ms;
  --hu-sheetDur: 240ms;
  --hu-grow: 0ms;
  --hu-breath: 0.12;
  --hu-aPush: hu-fade;
  --hu-aBack: hu-fade;
  --hu-aSheet: hu-fade;
  --hu-aPop: hu-fade;
  --hu-aBlink: none;
  --hu-aZ: hu-sleepZ;
}
:root[data-motion="Off"] {
  --hu-move: 0;
  --hu-press: 1;
  --hu-dur: 0ms;
  --hu-sheetDur: 0ms;
  --hu-tdur: 0ms;
  --hu-grow: 0ms;
  --hu-breath: 0;
  --hu-aPush: none;
  --hu-aBack: none;
  --hu-aTab: none;
  --hu-aSheet: none;
  --hu-aPop: none;
  --hu-aFade: none;
  --hu-aBlink: none;
  --hu-aZ: none;
}
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion]) {
    --hu-move: 0;
    --hu-press: 1;
    --hu-dur: 0ms;
    --hu-sheetDur: 0ms;
    --hu-tdur: 0ms;
    --hu-grow: 0ms;
    --hu-breath: 0;
    --hu-aPush: none;
    --hu-aBack: none;
    --hu-aTab: none;
    --hu-aSheet: none;
    --hu-aPop: none;
    --hu-aFade: none;
    --hu-aBlink: none;
    --hu-aZ: none;
  }
}

/* ---------- Page and shell ----------
   An app, not a web page: no tap flash, no rubber-band scrolling past the ends, no double-tap zoom, no text
   selection on bars, the bottom navigation or buttons (body text stays selectable), and no scrollbar. */

html, body { margin: 0; }
html {
  overscroll-behavior-y: none;
  -webkit-text-size-adjust: 100%;
  scrollbar-width: none;
}
html::-webkit-scrollbar { display: none; }
body {
  background: var(--surface);
  color: var(--text-on-surface);
  font: var(--type-body-01-regular);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
*, *::before, *::after { box-sizing: border-box; }
h1, h2, h3, h4, p, ul, ol, figure, fieldset { margin: 0; }
ul, ol { padding: 0; list-style: none; }
fieldset { border: 0; padding: 0; min-inline-size: 0; }
legend { padding: 0; }
img, svg { max-inline-size: 100%; }
button, input, select, textarea { font-family: inherit; }
[hidden] { display: none !important; }
.hu-bar, .hu-nav, .hu-foot, .btn, .link-btn, .icon-btn, .tab, .badge, .tag, .bottom-sheet__handle {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

.hu-shell {
  position: relative;
  inline-size: 100%;
  max-inline-size: var(--hu-column);
  min-block-size: calc(100dvh - 2 * var(--hu-frame));
  margin-inline: auto;
  margin-block: var(--hu-frame);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  overflow-x: clip;
}
/* On a tablet or a desktop the app sits in a centred phone column on a darker ground. */
@media (min-width: 480px) {
  body { background: var(--surface-container); }
  .hu-shell { box-shadow: var(--hu-lift); }
}
/* In a window tall enough for it the column reads as a phone floating in the window: Space_6 of the page shows above and
   below it, its corners are round, and it has the system's level 2 shadow (level 1 in dark). The page still scrolls as one document, so the
   frame is drawn over it: a fixed, click-through box with the phone's shape whose huge spread shadow paints the page colour
   everywhere outside it. Whatever scrolls past the top or bottom is cut off at the rounded edge, so the sticky bar, the
   bottom navigation and the sticky foot all sit inside the column, and they offset themselves by --hu-frame. */
@media (min-width: 480px) and (min-height: 600px) {
  :root { --hu-frame: var(--space-6); }
  .hu-shell { box-shadow: none; }
  body::after {
    content: "";
    position: fixed;
    z-index: 30;
    inset-block: var(--hu-frame);
    inset-inline: 0;
    inline-size: var(--hu-column);
    margin-inline: auto;
    border-radius: var(--space-6);
    box-shadow: var(--hu-lift), 0 0 0 100vmax var(--surface-container);
    pointer-events: none;
  }
}
/* Until the app has cleared the sample content and found out who is signed in, no screen shows (Boot.js sets
   data-app="Booting" and takes it off again, after 10 seconds at the latest). */
:root[data-app="Booting"] :is(.hu-main, .hu-nav) { visibility: hidden; }

/* The launch screen, like an installed app's: Pip, the name and a small spinner on the page colour, in the page only
   while it is Booting (so it can never cover the app once it has started, and the 10 second fallback in Boot.js takes it
   away with the attribute). It takes no touches. On a desktop it sits under the frame (z-index 25 against the frame's 30),
   so it fills the phone column and not the window. Nothing on it moves under motion Off. */
.hu-launch { display: none; }
:root[data-app="Booting"] .hu-launch {
  position: fixed;
  inset: 0;
  z-index: 25;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  background: var(--surface);
  color: var(--text-on-surface);
  pointer-events: none;
}
.hu-launch .loader { margin-block-start: var(--space-2); }
:root[data-motion="Off"] .hu-launch .loader { animation: none; }
@media (prefers-reduced-motion: reduce) { :root:not([data-motion]) .hu-launch .loader { animation: none; } }

/* The real input inside a painted control: invisible, still focusable and still the source of truth
   (AppSync.js paints the system's is-checked, is-active and is-focused from it). */
.hu-native {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}
.hu-visuallyHidden {
  position: absolute !important;
  inline-size: 1px;
  block-size: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.hu-sprite { position: absolute; inline-size: 0; block-size: 0; overflow: hidden; }

/* A Material Symbol sits in an .icon box so it sizes with --icon-size like the system's own icons
   (icon--16, icon--20, icon--24, icon--32). This is the one rule that sets a font size. */
.icon.hu-symbol { display: inline-grid; place-items: center; }
.hu-symbol > .material-symbols-rounded {
  font-size: var(--icon-size, var(--space-6));
  -webkit-user-select: none;
  user-select: none;
}

/* A keyboard focus ring for a control whose real input is hidden, and for anything else that can focus. */
:is(.hu-choice, .hu-switch, .hu-chip, .hu-segment > .tab, .btn):has(.hu-native:focus-visible) {
  outline: 2px solid var(--outline-brand-primary);
  outline-offset: calc(var(--space-1) / 2);
}
:focus-visible { outline-color: var(--outline-brand-primary); }
:focus:not(:focus-visible) { outline: none; }
/* Headings the app focuses on a screen change (tabindex=-1) move the screen reader, not a visible ring. */
[tabindex="-1"]:focus { outline: none; }

/* A press: buttons, rows and the navigation sink a little (Full motion only; --hu-press is 1 otherwise). */
.btn, .link-btn, .icon-btn, .app-bar__action, .bottom-nav__item, .bottom-nav__scan-and-pay, .hu-card--link,
.hu-sound, a.list-view, button.list-view, label.list-view {
  transition: transform var(--hu-tdur) var(--hu-ease), background-color var(--hu-tdur) var(--hu-ease);
}
.btn:active, .link-btn:active, .icon-btn:active, .app-bar__action:active, .bottom-nav__item:active,
.bottom-nav__scan-and-pay:active, .hu-card--link:active, .hu-sound:active,
a.list-view:active, button.list-view:active, label.list-view:active {
  transform: scale(var(--hu-press));
}
.link-btn.is-disabled, .link-btn:disabled, .icon-btn.is-disabled, .icon-btn:disabled {
  color: var(--text-on-surface-disabled);
  cursor: not-allowed;
}
a.is-disabled { pointer-events: none; }

/* ---------- Which screen shows ----------
   The app routes by hash, so the screen with :target shows (Router.js also sets html[data-screen] and
   html[data-nav]). The static prototype (?Prototype) shows Welcome when nothing is targeted. */

.hu-main { flex: 1 1 auto; display: flex; flex-direction: column; }
.hu-screen {
  position: relative;
  display: none;
  flex: 1 1 auto;
  flex-direction: column;
  min-block-size: calc(100dvh - 2 * var(--hu-frame));
  background: var(--surface);
}
.hu-screen:target,
.hu-screen:has(:target),
.hu-screen.IsActive { display: flex; }
:root:not([data-router="Js"]):not(:has(.hu-screen:target, .hu-screen :target)) #Welcome { display: flex; }
:root[data-router="Js"] .hu-screen:not(.IsActive) { display: none; }
.hu-screen[data-tabs] { padding-block-end: calc(var(--hu-nav) + var(--hu-safe-bottom)); }
/* The raised Listen circle reaches Space_8 above the bar, so on every tab screen the last line of the body ends
   clear of it (Space_12), and a foot on a tab screen keeps its buttons above the circle too. */
.hu-screen[data-tabs] .hu-body { padding-block-end: var(--space-12); }
.hu-form { display: flex; flex: 1 1 auto; flex-direction: column; }

/* ---------- App bar: sticky, back or brand on the left, Help now on the right ----------
   The system's app bar is a fixed 375 wide; here it fills the column and clears the status bar. */

.hu-bar.app-bar {
  position: sticky;
  inset-block-start: var(--hu-frame);
  z-index: 5;
  inline-size: 100%;
  padding-block-start: var(--hu-safe-top);
  transition: box-shadow var(--hu-tdur) var(--hu-ease);
}
.hu-bar .app-bar__row { align-items: center; }
.hu-bar a.app-bar__action { text-decoration: none; }
.hu-bar .app-bar__title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hu-bar .app-bar__trailing { gap: var(--space-2); }
.hu-helpBtn { white-space: nowrap; }
/* A very narrow phone: the bar's own side padding shrinks so a title, Sign in and Help now all fit. */
@media (max-width: 359px) {
  .hu-bar .app-bar__row { padding-inline: var(--space-2); }
  .hu-bar .app-bar__trailing { gap: var(--space-1); }
}
/* The brand: Pip's mark and the word Hushly. */
.hu-brand.app-bar__content { flex-direction: row; align-items: center; justify-content: flex-start; gap: var(--space-2); }
.hu-brand .app-bar__title { inline-size: auto; }
.hu-progress { inline-size: 100%; }
/* Sign up progress: one, two, then three thirds of the bar. The fill grows from where the last step ended
   (Full motion only: --hu-grow is 0 otherwise). */
.hu-progress--1 .app-bar__progress-fill { inline-size: calc(100% / 3); animation: hu-growTo1 var(--hu-grow) var(--hu-ease) backwards; }
.hu-progress--2 .app-bar__progress-fill { inline-size: calc(100% * 2 / 3); animation: hu-growTo2 var(--hu-grow) var(--hu-ease) backwards; }
.hu-progress--3 .app-bar__progress-fill { inline-size: 100%; animation: hu-growTo3 var(--hu-grow) var(--hu-ease) backwards; }
/* The old stepper's step markers are kept in the page as inert hooks. */
.hu-stepMark { display: none; }
/* A tab root: the small title stays hidden until the large title has scrolled under the bar (AppBar.js adds
   is-collapsed), and app-bar--scrolled gives the system's shadow once the page has moved. */
.hu-bar--large .app-bar__title { opacity: 0; transition: opacity var(--hu-tdur) var(--hu-ease); }
.hu-bar--large.is-collapsed .app-bar__title { opacity: 1; }
.hu-bar--large .app-bar__content { padding-inline: var(--space-2); }
.hu-largeTitle { padding-block: var(--space-2) var(--space-0); }
.hu-largeTitle .app-bar__title--lg { white-space: normal; inline-size: auto; }
/* The recording screens: a transparent bar laid over the screen. Listening.css sets --hu-immersive-ink to
   the ink that suits its own ground. */
.hu-bar--immersive.app-bar {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  background-color: transparent;
  color: var(--hu-immersive-ink, var(--text-on-surface));
}
.hu-bar--immersive :is(.app-bar__action, .app-bar__title) { color: inherit; }

/* ---------- Bottom navigation: fixed to the foot of the column, five items, Listen raised ----------
   It shows only while a tab screen shows (data-tabs). The active item fills its symbol. */

.hu-nav.bottom-nav {
  display: none;
  position: fixed;
  inset-inline: 0;
  inset-block-end: var(--hu-frame);
  z-index: 20;
  inline-size: 100%;
  max-inline-size: var(--hu-column);
  margin-inline: auto;
  align-items: flex-end;
  padding: var(--space-0) var(--space-1) var(--hu-safe-bottom);
  background-color: var(--surface-container-lowest);
  border-block-start: 1px solid var(--outline-softer);
}
:root:has(.hu-screen[data-tabs]:target) .hu-nav,
:root[data-router="Js"]:has(.hu-screen[data-tabs].IsActive) .hu-nav,
:root:is([data-screen="Listen"], [data-screen="NightLog"], [data-screen="NightLogEmpty"], [data-screen="Soothe"], [data-screen="Learn"], [data-screen="Settings"]) .hu-nav { display: flex; }
/* Five items share the bar. The system gives an item 72 and Space_2 either side, which wraps "Night log" at 320; here the
   items split what the raised Listen item leaves, take Space_1 either side, and keep their label on one line (an
   ellipsis only as a last resort). */
.hu-nav .bottom-nav__item {
  position: relative;
  flex: 1 1 0;
  min-inline-size: 0;
  inline-size: auto;
  padding-block: var(--space-2);
  padding-inline: var(--space-1);
  text-decoration: none;
  white-space: nowrap;
}
.hu-nav :is(.bottom-nav__item, .bottom-nav__scan-and-pay) > span:last-child { max-inline-size: 100%; overflow: hidden; text-overflow: ellipsis; }
.hu-nav .bottom-nav__item.is-active .material-symbols-rounded,
.hu-nav .bottom-nav__item[aria-current="page"] .material-symbols-rounded { font-variation-settings: "FILL" 1; }
.hu-nav .bottom-nav__item[aria-current="page"] { color: var(--hu-linkInk); }
.hu-navIcon { position: relative; display: inline-flex; }
.hu-navBadge { position: absolute; inset-block-start: calc(-1 * var(--space-1)); inset-inline-start: 55%; }
/* Listen: the system's gradient circle, lifted half out of the bar. Its ring takes the bar's own fill. */
.hu-nav .hu-navListen {
  flex: 0 0 auto;
  align-self: flex-end;
  margin-block-start: calc(-1 * var(--space-8));
  padding-block-end: var(--space-2);
  text-decoration: none;
}
.hu-navListen .bottom-nav__scan-and-pay-circle {
  flex: none;
  aspect-ratio: 1;
  border-color: var(--surface-container-lowest);
  box-shadow: var(--shadow-level-1);
  color: var(--hu-onBrand);
}
.hu-navListen.is-active,
.hu-navListen[aria-current="page"] { font: var(--type-metadata-03-bolder); color: var(--hu-linkInk); }

/* ---------- Body, head and foot ----------
   The page gutter is Space_4 (the system's 343 container is a 375 phone less 16 each side). Sections inside
   the body sit Space_6 apart. The foot is sticky, with the buttons stacked full width for a thumb. */

.hu-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--space-4) var(--space-4) var(--space-6);
}
.hu-body--center { justify-content: center; }
.hu-head { display: flex; flex-direction: column; gap: var(--space-2); }
.hu-head.hu-center { align-items: center; }
.hu-foot {
  position: sticky;
  inset-block-end: var(--hu-frame);
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) calc(var(--space-3) + var(--hu-safe-bottom));
  background-color: var(--surface-container-lowest);
  box-shadow: var(--shadow-reversed);
}
.hu-foot > .btn,
.hu-foot > form > .btn,
.hu-foot .hu-full { inline-size: 100%; }
.hu-foot > .link-btn,
.hu-foot > .hu-row { align-self: center; justify-content: center; }
.hu-screen[data-tabs] .hu-foot {
  inset-block-end: calc(var(--hu-nav) + var(--hu-safe-bottom) + var(--hu-frame));
  padding-block-end: calc(var(--space-3) + var(--space-8));
}

/* ---------- Groups, stacks, rows and text helpers ---------- */

.hu-group { display: flex; flex-direction: column; gap: var(--space-3); }
.hu-group > .hu-head { gap: var(--space-1); }
.hu-group > legend { margin-block-end: var(--space-3); }
.hu-stack { display: flex; flex-direction: column; gap: var(--space-2); }
.hu-stack--4 { gap: var(--space-4); }
.hu-stack--6 { gap: var(--space-6); }
.hu-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.hu-row--4 { gap: var(--space-4); }
.hu-row--between { justify-content: space-between; flex-wrap: nowrap; }
.hu-grow { flex: 1 1 auto; min-inline-size: 0; }
.hu-center { text-align: center; }
.hu-variant { color: var(--text-on-surface-variant); }
.hu-dim { color: var(--text-on-surface-dim); }
.hu-alertText { color: var(--hu-alertInk); }
.hu-full { inline-size: 100%; }
.hu-selfStart { align-self: flex-start; }
.hu-selfCenter { align-self: center; }
.hu-bullets { display: flex; flex-direction: column; gap: var(--space-1); padding-inline-start: var(--space-6); color: var(--text-on-surface-variant); list-style: disc; }
ol.hu-bullets { list-style: decimal; }
.hu-bullets > li { display: list-item; }
.hu-hero { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); text-align: center; }
/* Three numbers side by side (the night so far). */
.hu-statRow { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: var(--space-3); }
.hu-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-3);
  border-radius: var(--space-rounded-corner);
  background-color: var(--surface-container-lowest);
  box-shadow: var(--shadow-level-1);
}
.hu-statValue { font: var(--type-h3-bolder); letter-spacing: 0; color: var(--text-on-surface); font-variant-numeric: tabular-nums; }
.hu-statLabel { font: var(--type-body-02-regular); letter-spacing: 0; color: var(--text-on-surface-variant); }
/* A group heading in a screen body. The system's section header is padded for a full-width list (Space_6 on the left,
   Space_4 on the right); in a body it lines up with the cards under it, so its side padding goes and a small top
   padding stays so groups breathe. (A sheet's header keeps the system padding.) */
.hu-body .section-header { padding: var(--space-2) var(--space-0) var(--space-0); }
.hu-body .section-header__subheading { padding-inline-end: var(--space-0); }
.NoteHint { scroll-margin-block-end: var(--space-28); }
[data-bind="PastCryLearned"] { white-space: pre-line; }

/* ---------- Cards ----------
   hu-card is the system's surface-container-lowest on a radius of space-rounded-corner with shadow level 1.
   Two quieter surfaces, and a card that is a link. */

.hu-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4);
  border-radius: var(--space-rounded-corner);
  background-color: var(--surface-container-lowest);
  box-shadow: var(--shadow-level-1);
  color: var(--text-on-surface);
}
.hu-card--soft { background-color: var(--surface-container-low); box-shadow: none; }
.hu-card--sunk { background-color: var(--surface-container-high); box-shadow: none; }
.hu-card--link { text-decoration: none; color: inherit; cursor: pointer; }
.hu-cardRow { display: flex; align-items: center; gap: var(--space-4); }
.hu-card > .hu-cardRow > .hu-stack { flex: 1 1 auto; min-inline-size: 0; }

/* A row of buttons that share the width (did it help, keep or forget). */
.hu-btnRow { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.hu-btnRow > .btn { flex: 1 1 auto; }
/* A round tile holding one icon (the need on a cry's detail, a leading mark on a row). */
.hu-thumb {
  display: grid;
  flex: none;
  place-items: center;
  inline-size: var(--space-14);
  block-size: var(--space-14);
  border-radius: 50%;
  background: var(--primary-container);
  color: var(--hu-tileInk);
  --icon-size: var(--space-8);
}
/* The same tile at row size, the way an installed app leads a row: a soft brand circle (Space_10 across) with the need or
   care glyph in it (the icon keeps its data-need-icon hook inside). A row's leading slot centres it beside the text. */
.hu-tile {
  display: inline-grid;
  flex: none;
  place-items: center;
  inline-size: var(--space-10);
  block-size: var(--space-10);
  border-radius: 50%;
  background: var(--primary-container);
  color: var(--hu-tileInk);
}
.hu-tile > .icon { --icon-size: var(--space-5); }

/* ---------- Lists ----------
   Rows are the system's .list-view. A group of rows sits in .hu-list: one card with a divider between rows.
   The system's row is a fixed 375 wide with a single line of text; here it fills its container and wraps. */

.list-view, .list-card, .info-banner, .accordion { inline-size: 100%; }
.list-view__primary,
.list-card__primary { white-space: normal; overflow: visible; text-overflow: clip; }
.list-view__leading { color: var(--text-on-surface-variant); align-self: center; }
:is(a, button, label).list-view,
:is(a, button, label).list-card { color: inherit; text-decoration: none; text-align: start; cursor: pointer; }
button.list-view, button.list-card { border: 0; font: inherit; }
:is(a, button, label).list-view:active { background-color: var(--surface-container-low); }
.hu-list {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--space-rounded-corner);
  background-color: var(--surface-container-lowest);
  box-shadow: var(--shadow-level-1);
}
.hu-list > :last-child .list-view__divider { display: none; }
.hu-list > li > :is(a, button, label).list-view { padding-inline-end: var(--space-0); }
.list-view__trailing-data.hu-dim { color: var(--text-on-surface-dim); }
/* Pill, tag and age lines inside rows keep to their own size. */
.tag.Pill { align-self: flex-start; }

/* ---------- Chips: the system's tab pill, with a tick so a chosen chip never relies on colour alone ---------- */

.hu-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.hu-chipWrap { display: inline-flex; align-items: center; gap: var(--space-1); }
.hu-chip {
  position: relative;
  align-items: center;
  min-block-size: var(--space-10);
  cursor: pointer;
  white-space: normal;
  text-align: start;
}
.hu-chipTick { display: none; }
.hu-chip.is-active .hu-chipTick { display: inline-block; }
/* A red-flag sign the parent ticks reads in the alert family, never the calm secondary of an ordinary chip. */
.hu-chipWrap.IsWarn .hu-chip.is-active {
  background-color: var(--status-alert-softest);
  box-shadow: inset 0 0 0 1px var(--status-alert-base);
  color: var(--status-alert-bold);
}
/* Cue pictures ("Show pictures"): a chip with a picture becomes a small tile, the picture over the label,
   the tick in the corner. */
.hu-chips[data-pictures="true"],
.hu-chips:has(.HasPicture) { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--space-28), 1fr)); }
.hu-chipWrap.HasPicture { position: relative; display: flex; }
.hu-chipWrap.HasPicture .hu-chip { flex-direction: column; justify-content: flex-start; inline-size: 100%; padding: var(--space-2); text-align: center; border-radius: var(--space-rounded-corner); }
.hu-chipPicture, .hu-chipPicture > * { display: block; }
.hu-chipWrap.HasPicture .hu-chipTick { position: absolute; inset-block-start: var(--space-2); inset-inline-start: var(--space-2); }
.hu-chipWrap.HasPicture .ChipInfo { position: absolute; inset-block-start: 0; inset-inline-end: 0; }

/* ---------- Segments: a few big choices side by side (did it help, how long to settle, timers) ---------- */

.hu-segment { display: flex; flex-wrap: wrap; gap: var(--space-2); max-inline-size: 100%; }
.hu-segment > .tab {
  position: relative;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  min-block-size: var(--space-12);
  text-align: center;
  cursor: pointer;
}

/* ---------- Choices and switches: the real input is hidden, the system paints the control ---------- */

.hu-choice {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  cursor: pointer;
  font: var(--type-body-01-regular);
  letter-spacing: 0;
  color: var(--text-on-surface);
}
.hu-choice > :is(.radio, .checkbox) { flex: none; margin-block: calc(-1 * var(--space-2)); margin-inline-start: calc(-1 * var(--space-2)); }
.hu-choiceText { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 0; min-inline-size: 0; }
.hu-choiceMeta { font: var(--type-body-02-regular); letter-spacing: 0; color: var(--text-on-surface-variant); }
.hu-choice:has(.hu-native:disabled) { color: var(--text-on-surface-disabled); cursor: not-allowed; }
/* The painted box carries its tick icon in the markup. The system draws an unticked box as an empty ring and a ticked
   one as a filled box, so AppSync's is-checked decides whether the tick is there. */
.checkbox:not(.is-checked) .checkbox__glyph { display: none; }
.hu-switch {
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  cursor: pointer;
}
.hu-switch > .toggle { flex: none; margin-block: calc(-1 * var(--space-2)); }
.hu-switchText, .hu-toggleText { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 0; min-inline-size: 0; }
.hu-switchLabel { font: var(--type-body-01-bolder); letter-spacing: 0; color: var(--text-on-surface); }
.hu-switchMeta { font: var(--type-body-02-regular); letter-spacing: 0; color: var(--text-on-surface-variant); }
.hu-toggleRow { display: flex; align-items: flex-start; inline-size: 100%; }
.toggle__track, .toggle__knob { transition-duration: var(--hu-tdur); }

/* ---------- Fields ---------- */

.hu-body .field__label, .hu-sheet .field__label { color: var(--text-on-surface-variant); }
.field__control { outline: none; }
/* The system fills a select with surface and a text field with surface-container-lowest; side by side in a form
   that reads as two kinds of box, so a select here takes the text field's fill. */
.hu-body .select .field__input, .hu-sheet .select .field__input { background-color: var(--surface-container-lowest); }
.field__input:has(select) { position: relative; }
select.field__control { appearance: none; -webkit-appearance: none; cursor: pointer; padding-inline-end: var(--space-6); }
.field__input select ~ .field__trailing { position: absolute; inset-inline-end: var(--space-4); pointer-events: none; }
/* If the script has not painted is-focused yet, the browser's own focus still shows the system's focus look. */
.field:not(.is-focused) .field__input:focus-within { box-shadow: inset 0 0 0 1px var(--outline-brand-primary), var(--halo-focus); }
.field.is-error:not(.is-focused) .field__input:focus-within { box-shadow: inset 0 0 0 1px var(--status-alert-base), var(--halo-focus-error); }
.hu-error { margin: 0; color: var(--hu-alertInk); }
.hu-error:empty { display: none; }
.field__helper.hu-error,
.field.is-error .field__helper { color: var(--hu-alertInk); }
.field:is(.textarea) .textarea__control { font: var(--type-body-01-regular); }

/* ---------- Banners in the body ---------- */

.hu-body .info-banner { align-items: flex-start; }
.info-banner__content > .btn { align-self: flex-start; }
.hu-banner__text { display: flex; flex-direction: column; gap: var(--space-2); min-inline-size: 0; flex: 1 1 0; }
.info-banner--alert .info-banner__icon { color: var(--status-alert-base); }
.info-banner--notice .info-banner__icon { color: var(--status-notice-bold); }
.info-banner--informative .info-banner__icon { color: var(--status-informative-bold); }
.info-banner--positive .info-banner__icon { color: var(--status-positive-bold); }
.hu-offline { inline-size: auto; margin: var(--space-2) var(--space-4) var(--space-0); }

/* ---------- Accordion: a native <details> drawn with the system's accordion header, body and chevron ---------- */

.accordion > summary.accordion__header { list-style: none; }
.accordion > summary.accordion__header::-webkit-details-marker { display: none; }
.accordion > summary.accordion__header:focus-visible { outline: 2px solid var(--outline-brand-primary); outline-offset: calc(-1 * var(--space-1) / 2); }
.accordion__chevron { transition: transform var(--hu-tdur) var(--hu-ease); }
.accordion[open] > summary .accordion__chevron { transform: rotate(180deg); }
.accordion__body { display: flex; flex-direction: column; gap: var(--space-3); color: var(--text-on-surface-variant); }
/* A stand-alone accordion in the body reads as a card. */
.accordion.hu-accordion { overflow: hidden; border-block-end: 0; border-radius: var(--space-rounded-corner); box-shadow: var(--shadow-level-1); }
.accordion.hu-accordion .accordion__body { padding-inline-end: var(--space-4); }
.hu-warning > summary { list-style: none; }

/* ---------- Sheets: a popover holding the system's bottom sheet, rising from the bottom on a phone ----------
   Markup: .hu-sheet[popover] > .bottom-sheet > .hu-sheetClose, .bottom-sheet__body (handle, then the
   .section-header), .hu-sheetBody (the part that scrolls), .bottom-sheet__actions (the foot buttons).
   Above 480 wide it is a centred dialog. */

.hu-sheet {
  inset: auto 0 0 0;
  margin: 0 auto;
  inline-size: 100%;
  max-inline-size: var(--hu-column);
  max-block-size: 92dvh;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-on-surface);
  overflow: visible;
}
.hu-sheet::backdrop { background: var(--surface-overlay-base); }
.hu-sheet > .bottom-sheet {
  position: relative;
  inline-size: 100%;
  max-block-size: 92dvh;
  padding-block-end: var(--hu-safe-bottom);
}
.hu-sheet .bottom-sheet__body { flex: none; padding-block-end: var(--space-2); }
.hu-sheet .section-header { padding-inline-end: var(--space-12); }
.hu-sheetBody {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--space-4);
  min-block-size: 0;
  inline-size: 100%;
  padding: var(--space-2) var(--space-6) var(--space-4);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.hu-sheet .bottom-sheet__actions { flex: none; padding-block-start: var(--space-2); }
.bottom-sheet__actions > form { display: contents; }
.hu-sheetClose {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-end: var(--space-2);
  z-index: 1;
}
@media (min-width: 480px) {
  .hu-sheet { inset: 0; margin: auto; block-size: fit-content; }
  .hu-sheet > .bottom-sheet { border-radius: var(--space-6); }
  .hu-sheet .bottom-sheet__body { border-radius: var(--space-6); }
  .hu-sheet .bottom-sheet__handle { block-size: var(--space-4); }
  .hu-sheet .bottom-sheet__puller { display: none; }
}

/* ---------- Safety screens and the Help now list ---------- */

.hu-screen--safety .hu-head h1 { color: var(--hu-alertInk); }
.hu-helpLines {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--space-rounded-corner);
  box-shadow: inset 0 0 0 1px var(--outline-softer);
}
.hu-helpLine.list-view { color: inherit; text-decoration: none; }
.hu-helpLines > :last-child .list-view__divider { display: none; }
.hu-helpLine.IsEmergency { background-color: var(--status-alert-softest); color: var(--hu-alertInk); }
.hu-helpLine.IsEmergency .list-view__leading,
.hu-helpLine.IsEmergency .list-view__primary,
.hu-helpLine.IsEmergency .list-view__secondary { color: var(--hu-alertInk); }
.hu-helpNumber { font: var(--type-body-01-bolder); letter-spacing: 0; color: var(--text-on-surface); font-variant-numeric: tabular-nums; }
.hu-helpLine.IsEmergency .hu-helpNumber { color: var(--hu-alertInk); }

/* ---------- Pip, the owl, and the baby art ----------
   Illustrations, not icons: Pip keeps its SVG and its own colours, and the baby art keeps the colours the parent
   chose for their baby's look (BabyArt.js). Pip is Hushly's own art, so it takes no design-system colour: the sprite
   falls back to Hushly's palette, the same in light and dark. */

.hu-pip { flex: none; inline-size: var(--space-24); block-size: auto; aspect-ratio: 120 / 140; }
.hu-pip--mark { inline-size: var(--space-6); }
.hu-pip--small { inline-size: var(--space-8); }
.hu-pip--medium { inline-size: var(--space-16); }
.hu-pip--large { inline-size: var(--space-36); }
/* Pip holding the need's badge: the need's icon is laid over the badge. */
.hu-pipHold { position: relative; inline-size: var(--space-36); aspect-ratio: 120 / 140; flex: none; align-self: center; }
.hu-pipHold > .hu-pip { inline-size: 100%; block-size: 100%; }
.hu-pipHold > :is(.icon, .NeedIcon) {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-start: 72.9%;
  transform: translate(-50%, -50%);
  --icon-size: var(--space-8);
  /* The badge is Pip's cream in light and in dark, so the glyph is the brand pulled toward the dark text: deep blue in
     light (6 to 1 on the cream) and deep teal in dark (5 to 1), where the bright dark-mode brand would wash out. */
  color: color-mix(in srgb, var(--primary) 55%, var(--hu-onCream));
}
/* A slow blink, in Full motion only. */
.PipLid { opacity: 0; animation-name: var(--hu-aBlink); animation-duration: 6s; animation-iteration-count: infinite; }
/* Pip asleep on the empty night log. */
.hu-sleepStage { position: relative; display: grid; place-items: center; inline-size: var(--space-36); margin-inline: auto; }
.hu-sleepZ {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-end: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-0);
  color: var(--text-on-surface-variant);
}
.hu-sleepZ > :nth-child(2) { margin-inline-start: var(--space-3); }
.hu-sleepZ > :nth-child(3) { margin-inline-start: var(--space-6); }
.hu-sleepZ > * { animation-name: var(--hu-aZ); animation-duration: 4s; animation-timing-function: ease-in-out; animation-iteration-count: 3; }
.hu-sleepZ > :nth-child(2) { animation-delay: 0.6s; }
.hu-sleepZ > :nth-child(3) { animation-delay: 1.2s; }
.hu-baby { display: inline-block; flex: none; border-radius: 50%; overflow: hidden; background: var(--surface-container-high); }
.hu-baby svg { display: block; inline-size: 100%; block-size: 100%; }
.hu-scene { display: block; align-self: center; border-radius: var(--space-rounded-corner); overflow: hidden; }

/* ---------- Breathe with Pip: the circle grows on the in-breath and shrinks on the out-breath ----------
   This is a pace to follow, so it keeps going in every motion setting; Off holds the circle still and the
   arc and the words still alternate. The circle is a graphic, so it is painted in Hushly's own colours, and those live
   in Listening.css (the one sheet with its own palette); this sheet keeps only its sizes, its pace and its pause. */

.hu-breathe { position: relative; display: grid; place-items: center; align-self: center; inline-size: calc(var(--space-36) + var(--space-16)); aspect-ratio: 1; }
.hu-breathe > svg { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; transform: rotate(-90deg); pointer-events: none; }
/* The ring is drawn in the viewBox's own units (a 2-unit stroke is about 4px on screen). Its path length is 1 (pathLength in
   the markup), so the dash and the offset below are fractions of the circle; a non-scaling stroke would make
   them screen pixels and draw dots. */
.hu-breathe .hu-ringTrack { fill: none; stroke-width: 2; }
.hu-breathe .hu-ringFill {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 1 2;
  stroke-dashoffset: 1;
  animation: hu-breatheArc 10s linear infinite;
}
.hu-breatheOrb {
  display: grid;
  place-items: center;
  inline-size: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  text-align: center;
  animation: hu-breatheOrb 10s linear infinite;
}
.hu-breatheCue { display: grid; }
.hu-breatheCue > span { display: inline; grid-area: 1 / 1; }
.hu-breatheCue .CueIn { animation: hu-cueIn 10s linear infinite; }
.hu-breatheCue .CueOut { animation: hu-cueOut 10s linear infinite; }
#Breathe:has(#BreathePause:checked) .hu-breathe *,
#Breathe[data-paused="true"] .hu-breathe * { animation-play-state: paused; }
.hu-ifPaused { display: none; }
#Breathe:has(#BreathePause:checked) .hu-ifRunning,
#Breathe[data-paused="true"] .hu-ifRunning { display: none; }
#Breathe:has(#BreathePause:checked) .hu-ifPaused,
#Breathe[data-paused="true"] .hu-ifPaused { display: inline; }

/* ---------- Pip's speech, and what the parent said ---------- */

.hu-bubble {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-inline-size: 88%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--space-rounded-corner);
  background: var(--surface-container-lowest);
  box-shadow: inset 0 0 0 1px var(--outline-softer);
  color: var(--text-on-surface);
}
.hu-bubble--pip { align-self: flex-start; border-end-start-radius: var(--space-1); }
.hu-bubble--you { align-self: flex-end; background: var(--primary-container); box-shadow: none; border-end-end-radius: var(--space-1); }

/* ---------- The night timeline: time, a dot, then what happened ---------- */

.hu-timeline { display: flex; flex-direction: column; }
.hu-timelineItem {
  position: relative;
  display: grid;
  grid-template-columns: var(--space-14) var(--space-10) 1fr auto;
  gap: var(--space-2);
  align-items: start;
  padding-block: var(--space-3);
}
.hu-timelineItem::before {
  content: "";
  position: absolute;
  inset-inline-start: calc(var(--space-14) + var(--space-2) + var(--space-10) / 2 - 1px); /* the dot column's centre: an alignment value, not spacing */
  inset-block: 0;
  inline-size: 2px;
  background: var(--status-neutral-softer);
}
.hu-timelineItem:first-child::before { inset-block-start: var(--space-6); }
.hu-timelineItem:last-child::before { inset-block-end: calc(100% - var(--space-6)); }
.hu-timelineTime { padding-block-start: var(--space-2); white-space: nowrap; font: var(--type-body-03-bolder); letter-spacing: 0; color: var(--text-on-surface-variant); font-variant-numeric: tabular-nums; }
.hu-timelineDot {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  inline-size: var(--space-10);
  block-size: var(--space-10);
  border-radius: 50%;
  background: var(--status-neutral-softest);
  box-shadow: 0 0 0 var(--space-1) var(--surface);
  color: var(--text-on-surface-variant);
  --icon-size: var(--space-5);
}
.hu-timelineItem[data-kind="Cry"] .hu-timelineDot { background: var(--primary-container); color: var(--hu-tileInk); }
.hu-timelineBody { display: flex; flex-direction: column; gap: var(--space-0); min-inline-size: 0; padding-block-start: var(--space-1); }
.hu-timelineTitle { color: var(--text-on-surface); text-decoration: none; }
.hu-timelineTitle[href]::after { content: ""; position: absolute; inset: 0; }

/* ---------- How sure: three short bars ---------- */

.hu-meter { display: inline-flex; gap: var(--space-1); max-inline-size: 100%; }
.hu-meterSeg { flex: 0 1 var(--space-6); min-inline-size: var(--space-2); block-size: var(--space-1); border-radius: var(--space-1); background: var(--status-neutral-softer); } /* no 6px token: Space_1 is the nearest bar */
.hu-meterSeg[data-filled], .hu-meterSeg.IsFilled,
[data-confidence="StrongClue"] .hu-meterSeg,
[data-confidence="Possible"] .hu-meterSeg:nth-child(-n+2),
[data-confidence="HardToTell"] .hu-meterSeg:nth-child(1) { background: var(--primary); }
.hu-confidence { display: inline-flex; align-items: center; gap: var(--space-3); }
.hu-fingerprint { inline-size: var(--space-24); block-size: var(--space-6); flex: none; fill: none; stroke: var(--primary); stroke-width: 2; stroke-linecap: round; }

/* ---------- The look picker: skin, hair and outfit tiles for the baby's picture ---------- */

.hu-look { display: flex; flex-direction: column; gap: var(--space-4); }
.hu-lookGroup { display: flex; flex-direction: column; gap: var(--space-2); }
.hu-lookChoices { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.hu-lookChoice { position: relative; }
.hu-lookLabel {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: var(--space-12);
  block-size: var(--space-12);
  border-radius: 50%;
  border: 2px solid var(--outline-softer);
  cursor: pointer;
  overflow: hidden;
}
.hu-lookChoice:has(.hu-native:checked) .hu-lookLabel { border-color: var(--outline-brand-primary); }
.hu-lookChoice:has(.hu-native:focus-visible) .hu-lookLabel { outline: 2px solid var(--outline-brand-primary); outline-offset: calc(var(--space-1) / 2); }
.hu-lookFace { position: absolute; inset: 0; border-radius: 50%; }
/* icon-status-tick-mark-filled is a disc with the tick cut out; a masked icon paints only its glyph, so it takes the colour and no fill. */
.hu-lookTick { position: absolute; display: none; color: var(--primary); --icon-size: var(--space-4); }
.hu-lookChoice:has(.hu-native:checked) .hu-lookTick { display: inline-block; }
.hu-lookPreview { display: flex; justify-content: center; }

/* ---------- What to tell them (the doctor or nurse) ---------- */

.hu-tell { display: flex; flex-direction: column; gap: var(--space-3); margin: 0; }
.hu-tellItem { display: flex; flex-direction: column; gap: var(--space-1); }
.hu-tellValue { margin: 0; }

/* ---------- Take a break: intro, then a ten-minute clock, then done ----------
   The three states are :target driven, as in the original build (the ids BreakTimer and BreakDone). */

.hu-break { display: flex; flex: 1 1 auto; flex-direction: column; }
.hu-break--timer, .hu-break--done { display: none; }
#TakeABreak:has(#BreakTimer:target) .hu-break--intro,
#TakeABreak:has(#BreakDone:target) .hu-break--intro { display: none; }
#TakeABreak:has(#BreakTimer:target) .hu-break--timer,
#TakeABreak:has(#BreakDone:target) .hu-break--done { display: flex; }
.hu-break--timer .hu-body, .hu-break--done .hu-body { justify-content: center; }
.hu-breakClock { font: var(--type-h1-bolder); letter-spacing: 0; text-align: center; font-variant-numeric: tabular-nums; }
.hu-breakIcon {
  display: grid;
  place-items: center;
  align-self: flex-start;
  inline-size: var(--space-18);
  block-size: var(--space-18);
  border-radius: 50%;
  background: var(--primary-container);
  color: var(--hu-tileInk);
  --icon-size: var(--space-8);
}

/* ---------- Soothe: pick a sound, see it playing, stop it ---------- */

.hu-sound { cursor: pointer; }
.hu-sound:has(.SoundInput:checked) { background-color: var(--primary-container); box-shadow: inset 0 0 0 1px var(--outline-brand-primary); }
.hu-sound:has(.SoundInput:focus-visible) { outline: 2px solid var(--outline-brand-primary); outline-offset: calc(var(--space-1) / 2); }
.hu-sound .hu-pauseIcon { display: none; }
.hu-sound:has(.SoundInput:checked) .hu-playIcon { display: none; }
.hu-sound:has(.SoundInput:checked) .hu-pauseIcon { display: inline-grid; }
#Soothe:not(:has(.SoundInput:not([value="None"]):checked)) .hu-ifPlaying { display: none; }
.hu-wave { inline-size: 100%; block-size: var(--space-12); fill: none; stroke: var(--primary); stroke-width: 2; stroke-linecap: round; }

/* ---------- Screen change, sheets rising, and the keyframes ----------
   Router.js sets html[data-nav] to push (deeper), back (returning to the screen before) or tab (between tab
   roots) and the screen that appears plays its change. The Help now sheet and every IsSafety screen skip
   all of it (end of this file). */

@keyframes hu-fade { from { opacity: 0; } }
@keyframes hu-push {
  from { opacity: 0; transform: translateX(calc(var(--space-6) * var(--hu-move))); }
  to { opacity: 1; transform: none; }
}
@keyframes hu-back {
  from { opacity: 0; transform: translateX(calc(-1 * var(--space-6) * var(--hu-move))); }
  to { opacity: 1; transform: none; }
}
@keyframes hu-sheetRise { from { transform: translateY(100%); } to { transform: none; } }
@keyframes hu-sheetPop { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes hu-growTo1 { from { inline-size: 0; } }
@keyframes hu-growTo2 { from { inline-size: calc(100% / 3); } }
@keyframes hu-growTo3 { from { inline-size: calc(100% * 2 / 3); } }
@keyframes hu-sleepZ {
  0% { opacity: 0; transform: translate(0, calc(var(--space-2) * var(--hu-move))); }
  40% { opacity: 1; transform: translate(0, 0); }
  85% { opacity: 1; transform: translate(calc(var(--space-1) * var(--hu-move)), calc(-1 * var(--space-3) * var(--hu-move))); }
  100% { opacity: 0; transform: translate(calc(var(--space-2) * var(--hu-move)), calc(-1 * var(--space-4) * var(--hu-move))); }
}
@keyframes hu-blink { 0%, 92%, 100% { opacity: 0; } 94%, 96% { opacity: 1; } }
@keyframes hu-breatheOrb {
  0% { transform: scale(calc(1 - var(--hu-breath))); animation-timing-function: var(--hu-ease); }
  40% { transform: scale(1); animation-timing-function: var(--hu-ease); }
  100% { transform: scale(calc(1 - var(--hu-breath))); }
}
@keyframes hu-breatheArc { 0% { stroke-dashoffset: 1; } 40% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 1; } }
@keyframes hu-cueIn { 0%, 38% { opacity: 1; } 42%, 98% { opacity: 0; } 100% { opacity: 1; } }
@keyframes hu-cueOut { 0%, 38% { opacity: 0; } 42%, 98% { opacity: 1; } 100% { opacity: 0; } }

.hu-screen { animation-duration: var(--hu-dur); animation-timing-function: var(--hu-ease); animation-fill-mode: backwards; }
:root[data-nav="push"] .hu-screen:is(:target, :has(:target), .IsActive) { animation-name: var(--hu-aPush); }
:root[data-nav="back"] .hu-screen:is(:target, :has(:target), .IsActive) { animation-name: var(--hu-aBack); }
:root[data-nav="tab"] .hu-screen:is(:target, :has(:target), .IsActive) { animation-name: var(--hu-aTab); }
.hu-sheet:popover-open > .bottom-sheet { animation-name: var(--hu-aSheet); animation-duration: var(--hu-sheetDur); animation-timing-function: var(--hu-ease); animation-fill-mode: backwards; }
.hu-sheet:popover-open::backdrop { animation: hu-fade var(--hu-sheetDur) var(--hu-ease) backwards; }
:root[data-motion="Off"] .hu-sheet::backdrop { animation: none; }
@media (prefers-reduced-motion: reduce) { :root:not([data-motion]) .hu-sheet::backdrop { animation: none; } }
@media (min-width: 480px) {
  .hu-sheet:popover-open > .bottom-sheet { animation-name: var(--hu-aPop); }
}

/* Nothing on a safety screen, in the Help now sheet or in a red-flag block ever moves, fades or slides.
   Red flag content is never delayed. */
.IsSafety, .IsSafety *,
.hu-screen--safety, .hu-screen--safety *,
.info-banner--alert, .info-banner--alert *,
.hu-warning, .hu-warning *,
.hu-sheet.IsSafety::backdrop { animation: none !important; transition: none !important; }

/* ---------- Night log, history, a cry and logging a missed cry ---------- */

/* The Night log (and its empty night), History, a cry and Log a cry screens, and the Similar and Forget sheets. */

/* A row link with no address (another baby's cry in the similar list: the app takes its href away) is not a
   control, so it does not sink or tint when touched. */
a.list-view:not([href]) { cursor: default; }
a.list-view:not([href]):active { transform: none; background-color: var(--surface-container-lowest); }

/* A list inside a sheet sits on the sheet's own white, so it takes a hairline border in place of the card shadow. */
.hu-sheetBody .hu-list { box-shadow: none; border: 1px solid var(--outline-softer); }

/* The night timeline. A cry row opens (a chevron at the end, the bin is not offered); a care row is removed (the
   bin, no chevron). The dot of a cry row is decoration, so a touch on it still reaches the row's link. */
.hu-timelineItem[data-kind="Cry"] [data-action="DeleteCareEvent"] { display: none; }
.hu-timelineItem[data-kind="Care"] > .hu-timelineGo { display: none; }
.hu-timelineItem[data-kind="Cry"] .hu-timelineDot { pointer-events: none; }
.hu-timelineGo { align-self: center; color: var(--text-on-surface-dim); }

/* "What Pip is noticing": each finding is a short sentence led by a small dot in the brand colour. */
.hu-finding { display: flex; align-items: flex-start; gap: var(--space-2); }
.hu-finding > .icon { margin-block-start: var(--space-1); color: var(--hu-tileInk); }
.hu-finding .material-symbols-rounded { font-variation-settings: "FILL" 1; }

/* An empty line, an empty list and an empty text slot take no room, wherever they sit (a card, the foot, the body, a stack),
   so a column's gap never opens round nothing. A live status or alert line is in the page from the start so it is
   announced when its text arrives, so it is not hidden: while it is empty it is a clipped one-pixel box taken out of the
   flow (an out-of-flow child takes no gap), and it is an ordinary line again the moment it has text. */
p:is([role="status"], [role="alert"]):empty {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
[data-list]:not(:has(> *)),
p[data-bind]:empty:not([role]) { display: none; }

/* ---------- Soothe, Breathe, settings, what Pip knows, learn and the safety screens ---------- */

/* ---------- A status line that is red only while it is an error ----------
   The line under Save changes says "Saved." as often as it says what went wrong. Settings.js adds hu-error (and
   the old data-state) only for an error. An empty line takes no room in the body's gap. */

.hu-note { margin: 0; color: var(--text-on-surface-variant); }
.hu-note:empty { display: none; }
.hu-note.hu-error,
.hu-note[data-state="Error"] { color: var(--hu-alertInk); }

/* ---------- Soothe: a sound is a choosable card ----------
   Hushly.css already draws the chosen card (primary-container fill, brand outline) and swaps play for pause. The
   round button on the right is a plain system icon button in the brand tint; while its sound plays it fills in. */

.hu-sound { position: relative; }
.hu-sound .list-card__primary { flex: none; }
.hu-soundBtn { background-color: var(--primary-container); color: var(--hu-tileInk); }
.hu-sound:has(.SoundInput:checked) .hu-soundBtn { background-color: var(--primary); color: var(--hu-onBrand); }

/* ---------- What Pip knows ----------
   A whole row opens its cry: the title link is stretched over the row. A helper with no guide to read is a quiet
   tag among the chips and does not stretch to the chips' height. */

#Memory .HistoryRow { position: relative; }
#Memory .HistoryLink { color: inherit; text-decoration: none; }
#Memory .HistoryLink[href]::after { content: ""; position: absolute; inset: 0; }
.hu-chips > .ChipStatic { align-self: center; }

/* ---------- Ask Pip and Delete sheets ----------
   The send button is the system's large primary button squared up round its one icon. The sheet's second action is a
   link button, centred under the full-width one. */

.hu-sendBtn.btn--lg { padding-inline: var(--space-3); }
#DeleteSheet .bottom-sheet__actions .link-btn { align-self: center; }

/* ---------- Quick check, the three results, no cry heard, microphone off and the feedback sheet ---------- */

/* ---------- Why we think so: reasons and the chip that opens the earlier cries ----------
   A reason with nothing behind it is a grey tag; one that opens the earlier cries is a chip (a button with a
   chevron, made by Result.js). The tag takes the chip's height and pill shape so the two sit in one row as one
   family, and a long reason wraps instead of running off the screen. */

.hu-why .tag {
  min-block-size: var(--space-10);
  padding-inline: var(--space-4);
  border-radius: var(--space-10);
  white-space: normal;
  text-align: start;
}

/* ---------- Rows that are buttons ----------
   A button has its own bottom padding; a row from the system has none. */

button.list-view, button.list-card { padding-block-end: var(--space-0); }

/* ---------- Try this now: one step per row ----------
   The whole row is a label (list-view__body with hu-choice), so a tap anywhere on the step ticks it. The painted
   check is Space_10 wide with a Space_2 pull on its left (hu-choice), so the sound button under a step starts
   where the step's words start: Space_2 + Space_8 + Space_2. */

.hu-stepTime { display: flex; align-items: center; gap: var(--space-1); }
.hu-step > .StepSound {
  margin-inline-start: calc(var(--space-2) + var(--space-8) + var(--space-2));
  margin-block-end: var(--space-3);
}

/* ---------- Pip's note: Pip sits at the top of the card, beside the first line, however long the note is ---------- */

.NoteCard .hu-cardRow { align-items: flex-start; }

/* ---------- The foot of a result screen ----------
   The thanks lines, the Help now hint and the two answers sit in the sticky foot, so what happens after a tap is
   in view whatever the page is scrolled to. A status line with nothing in it stays in the page (a live region
   must exist before its text does) but takes no room (see the empty lines rule under Night log).
   The lines a saved answer adds come one per line in a single text node. */

[data-bind="FeedbackLearned"] { white-space: pre-line; }
.hu-foot .hu-btnRow > .btn { flex: 1 1 0; }
/* Each answer label stays on one line ("That helped"). A very narrow phone trims a large button's side padding so two of them fit. */
.hu-btnRow > .btn { white-space: nowrap; }
@media (max-width: 359px) { .hu-btnRow > .btn--lg { padding-inline: var(--space-3); } }

/* ---------- The feedback sheet: a question's helper line sits tight under the chips it explains ---------- */

.hu-sheet .hu-sheetBody > .hu-group > .hu-chips + .field__helper { margin-block-start: calc(-1 * var(--space-2)); }

/* ---------- Edge swipe back and the keyboard (Gestures.js and Router.js set the classes) ---------- */


/* Edge swipe back. A pushed screen lets the page pan up and down (and pinch to zoom) but not sideways, so a drag from the
   left edge reaches the script and the browser keeps out of it. The tab roots and the see-through recording screen are left
   alone: they have no swipe. */
.hu-screen:not([data-tabs], #Listening) { touch-action: pan-y pinch-zoom; }
/* While the finger drags, the screen follows it (the script sets --hu-swipe in pixels) with a soft shadow on its edge. A
   screen marked IsSafety, and any screen under motion Gentle or Off, never gets this class: it does not follow the finger. */
.hu-screen.is-swiping {
  transform: translateX(var(--hu-swipe, 0));
  box-shadow: var(--shadow-level-1);
  transition: none;
}
/* Let go: the screen slides off or springs back, at the pace of a screen change (three quarters of --hu-dur). */
.hu-screen.is-swiping.is-swipeSettling { transition: transform calc(var(--hu-dur) * 0.75) var(--hu-ease); }

/* The keyboard is up. Gestures.js puts hu-typing on <html> while a text field, text area or menu inside the app has focus on
   a touch device. The bottom nav goes, and so does the room a tab screen keeps for it, so the field is not squeezed; the
   tab screen's foot (Save) drops to the bottom edge where the nav was. The nav's rule for showing it
   on a tab screen is more specific than this one, hence the !important. */
:root.hu-typing .hu-nav.bottom-nav { display: none !important; }
:root.hu-typing .hu-screen[data-tabs] { padding-block-end: var(--space-0); }
:root.hu-typing .hu-screen[data-tabs] .hu-body { padding-block-end: var(--space-6); }
:root.hu-typing .hu-screen[data-tabs] .hu-foot {
  inset-block-end: 0;
  padding-block-end: calc(var(--space-3) + var(--hu-safe-bottom));
}

/* ---------- Swipe down to close a sheet (Gestures.js sets the classes and the two variables) ---------- */


/* The handle, the heading and the close button are where a sheet is grabbed: the browser does not pan from there, so a
   downward drag always reaches the script. The body keeps its own scrolling; the script claims a downward pull in it only
   when it is scrolled to the top (it cancels that touch's scroll itself). */
.hu-sheet .bottom-sheet__body, .hu-sheet .hu-sheetClose { touch-action: none; }

/* While the finger drags, the sheet's card follows it (the script sets --hu-sheetDrag in pixels on the sheet) and the backdrop
   fades a little (--hu-sheetFade, 1 to 0; the backdrop inherits it from the sheet). A sheet marked IsSafety, and any sheet under
   motion Gentle or Off, never gets this class: it does not follow the finger. (The opening animation is left alone: dropping it
   here would make it play again when the class goes.) */
.hu-sheet.is-sheetDragging > .bottom-sheet {
  transform: translateY(var(--hu-sheetDrag, 0));
  transition: none;
}
.hu-sheet.is-sheetDragging::backdrop {
  opacity: var(--hu-sheetFade, 1);
  transition: none;
}

/* Let go: the sheet drops away (the backdrop with it) or springs back, at the pace of a sheet opening (three quarters of --hu-sheetDur). */
.hu-sheet.is-sheetDragging.is-sheetSettling > .bottom-sheet { transition: transform calc(var(--hu-sheetDur) * 0.75) var(--hu-ease); }
.hu-sheet.is-sheetDragging.is-sheetSettling::backdrop { transition: opacity calc(var(--hu-sheetDur) * 0.75) var(--hu-ease); }

/* ---------- Contrast ----------
   Checked at 390 wide in light and dark on every screen and sheet (4.5 to 1 for text, 3 to 1 for large text and for icons).
   The system's own colours are short on its light surfaces: the brand blue text is 3.1 to 1, the dim grey 3.2 to 1, the
   alert red 4.2 to 1, white on the brand cyan 2.4 to 1 and white on the alert red 4.2 to 1 (2.6 to 1 in dark). The system's
   tokens are pointed at stronger ones here, inside the shell and the sheets, so every system component that reads them
   (link buttons, secondary buttons, helper lines, row notes, placeholders, banner links) clears 4.5 to 1 without a change to
   the component. A `:where()` scope keeps these at the system's own specificity, so a pressed state still wins. */

:where(.hu-shell, .hu-sheet) {
  --text-brand-primary: var(--hu-linkInk);
  --text-on-surface-dim: var(--hu-dimInk);
  --text-on-surface-placeholder: var(--hu-dimInk);
}
/* An alert button is the bold red with white in light, the soft red with dark text in dark. */
body .btn--alert { background-color: var(--hu-alertFill); color: var(--hu-onAlert); }
body .btn--alert:active,
body .btn--alert.is-pressed { color: var(--hu-onAlert); }
body .btn--secondary-alert { color: var(--hu-alertInk); }
/* The count on a badge. */
body .badge { background-color: var(--hu-alertFill); color: var(--hu-onAlert); }
/* The soft status tags: the label takes the status family's boldest ink (the system's bold is 3.6 to 4.2 to 1 on its fill). */
body .tag--green { color: var(--status-positive-boldest); }
body .tag--blue { color: var(--status-informative-boldest); }
body .tag--orange { color: var(--status-notice-boldest); }
body .status--positive { color: var(--status-positive-boldest); }
body .status--informative { color: var(--status-informative-boldest); }
body .status--notice { color: var(--status-notice-boldest); }

/* ---------- Tap size ----------
   A finger needs 44 by 44 (--hu-tap). These keep the size the design draws and gain an invisible hit area of at least that
   size, centred on them: a pseudo-element, so the layout does not move. A thing already 44 across gets none (the inset is
   never positive). The stretched row links (.hu-timelineTitle, #Memory .HistoryLink) cover their row already. */

:where(.btn--sm, .link-btn, .icon-btn, .app-bar__action, .hu-choice, .hu-chip) { position: relative; }
:is(.btn--sm, .link-btn, .icon-btn, .app-bar__action, .hu-choice, .hu-chip)::after {
  content: "";
  position: absolute;
  inset-block: min(var(--space-0), calc((100% - var(--hu-tap)) / 2));
  inset-inline: min(var(--space-0), calc((100% - var(--hu-tap)) / 2));
}
