/* Family App — layout and components.
 * Responsive per DES-10/11/12: one column on a phone, two on a tablet, three on
 * a laptop, from one auto-fit grid rather than per-breakpoint rewrites. */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* DES-1 — explicit, so the page never borrows a dark host's ground. */
  background: var(--canvas);
  color-scheme: light;
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* Room for the phone tab bar; overridden once the bar goes away. */
  padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
}

button { font: inherit; color: inherit; cursor: pointer; }

:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; border-radius: 4px; }

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

/* ------------------------------------------------------------------ shell */

.app {
  max-width: var(--wide-max);
  margin: 0 auto;
  padding: var(--s-5) var(--s-4) var(--s-6);
}

.view { display: none; }
.view.on { display: block; animation: fade .18s ease-out; }

@keyframes fade { from { opacity: 0; transform: translateY(4px); } }

/* ------------------------------------------------------- the record screen */

/* The record screen is one button. It stays a column however wide the window
 * gets — a 1080px-wide "hold to record" would be absurd. Only the lists use
 * the extra room, which is what gives DES-10 its third column on a laptop. */
.home {
  max-width: var(--app-max);
  margin-inline: auto;
  width: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-5);
  padding: var(--s-6) var(--s-4) var(--s-5);
  /* Centred in what is left after the tab bar, so the one button sits where the
   * thumb already is rather than floating above a screenful of nothing. svh
   * rather than vh: on a phone, vh ignores the browser's own chrome. */
  min-height: calc(100svh - 150px);
}

/* DES-6 — the twin swirl, crossing behind her portrait. The swirl is a child of
 * .crown, not of .home, so it tracks the portrait instead of the top of the
 * screen. The negative inset is .home's own padding, which is what carries the
 * lines to the edges of the phone. */
.crown { position: relative; width: 100%; display: flex; justify-content: center; }

.swirl {
  position: absolute;
  /* An <svg> with a viewBox has an intrinsic width, and that beats a left/right
   * pair — the element drew at its viewBox's 344px and simply stopped, which on
   * a phone happened to be almost exactly right and on a laptop was not.
   * Setting width explicitly is what actually carries it edge to edge. */
  left: calc(-1 * var(--s-4));
  width: calc(100% + var(--s-4) * 2);
  top: 50%; translate: 0 -50%;
  height: 118px;
  z-index: 0;
  pointer-events: none;
}

.home > * { position: relative; z-index: 1; }
.crown .portrait { z-index: 1; }

/* DES-7 — her portrait, at the diameter of the disc. */
.portrait { position: relative; width: calc(var(--disc) + 6px); height: calc(var(--disc) + 6px); }

.portrait::before {
  content: "";
  position: absolute;
  inset: -14px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, var(--rose-lo), transparent 68%);
}

.portrait .ring {
  position: relative;
  padding: 3px;
  border-radius: 50%;
  background: linear-gradient(150deg, var(--silver-3), var(--silver-2) 42%, var(--silver-1));
}

.portrait img {
  display: block;
  width: var(--disc); height: var(--disc);
  border-radius: 50%;
  object-fit: cover;
}

.momname {
  font-family: var(--serif);           /* DES-4 — one of two serif uses here */
  font-size: var(--t-xl);
  line-height: 1;
}

/* DES-11 — 128px on every device. */
.disc {
  width: var(--disc); height: var(--disc);
  border-radius: 50%;
  border: none;
  background: var(--pink);
  color: var(--rose-ink);
  font-size: calc(0.9062rem * var(--scale)); font-weight: 600; line-height: 1.3;
  touch-action: none;                  /* a hold must not become a scroll */
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 0 0 3px var(--silver-2), 0 0 0 4px var(--silver-3),
              0 12px 28px -10px color-mix(in srgb, var(--pink) 70%, transparent),
              inset 0 -3px 0 color-mix(in srgb, var(--pink) 62%, black);
  transition: transform .12s ease-out, box-shadow .12s ease-out;
}

.disc[data-holding="1"] {
  transform: scale(.955);
  box-shadow: 0 0 0 3px var(--silver-2), 0 0 0 5px var(--pink),
              0 6px 16px -8px color-mix(in srgb, var(--pink) 70%, transparent),
              inset 0 -2px 0 color-mix(in srgb, var(--pink) 62%, black);
}

.disc:disabled { opacity: .45; cursor: default; }

.timer {
  font-family: var(--serif);           /* the second and last serif use */
  font-size: var(--t-display);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.cap { font-size: calc(0.7812rem * var(--scale)); color: var(--muted); text-align: center; }
.cap.warn { color: var(--rose); }

/* The level meter — real amplitude, not a decorative loop. */
.wave { display: flex; align-items: center; gap: 4px; height: 40px; }
.wave i {
  width: 3px; border-radius: 3px; background: var(--pink);
  display: block; opacity: .85; height: 4px;
  transition: height .08s linear;
}

/* DES-8 — hearts rise and fade. The only ambient motion in the app. */
.hearts { display: flex; justify-content: center; gap: 16px; height: 34px; }
.hearts svg { width: 17px; height: 17px; animation: rise 4.6s ease-in-out infinite; }
.hearts svg:nth-child(2) { animation-delay: .9s; }
.hearts svg:nth-child(3) { animation-delay: 1.8s; }
.hearts svg:nth-child(4) { animation-delay: 2.7s; }
.hearts svg:nth-child(5) { animation-delay: 3.6s; }

@keyframes rise {
  0%   { transform: translateY(10px) scale(.85); opacity: 0; }
  22%  { opacity: .95; }
  70%  { opacity: .5; }
  100% { transform: translateY(-24px) scale(1.05); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hearts svg { animation: none; opacity: .7; }
  .view.on { animation: none; }
  .wave i { transition: none; }
}

/* --------------------------------------------------------------- topbar */

/* Home, upper left. NOT named .home — that is the record screen's own
 * container, and two rules by that name would fight. */
.topbar { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-3); }

/* Quiet by design. It is a diagnostic, not a feature — but it must be legible
 * enough to read aloud over the phone. */
.version { font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums;
           letter-spacing: .04em; flex: 0 0 auto; }

/* The wordmark. Sans at 600 rather than the serif: Instrument Serif ships only
 * one weight, and at 400 the pink would miss the contrast floor. Bold sans at
 * 19px clears the large-text threshold, so both colours stay legible. */
.wordmark {
  flex: 1 1 auto; text-align: center; margin: 0;
  font-family: var(--sans); font-size: calc(1.1875rem * var(--scale)); font-weight: 600;
  letter-spacing: .005em; white-space: nowrap;
}
.wordmark-btn {
  border: none; background: none; padding: 4px 6px; margin: -4px -6px;
  font: inherit; color: inherit; letter-spacing: inherit; white-space: nowrap;
  border-radius: 10px; cursor: pointer;
}
.wordmark-btn:hover { background: var(--silver-2); }
.wordmark i { font-style: normal; }
.wordmark .p { color: var(--pink); }
.wordmark .b { color: var(--blue); }

.homebtn {
  width: 44px; height: 44px; border-radius: 50%;          /* DES-12 */
  border: 1px solid var(--silver-1); background: var(--paper); color: var(--rose);
  display: grid; place-items: center; padding: 0;
}
/* On the record screen it is where you already are: shown, still working, just
 * not calling for attention. Expressed on the surface because the house keeps
 * its own two colours. */
.homebtn[aria-current="page"] { background: var(--silver-2); border-color: var(--silver-2); }
.homebtn[aria-current="page"] .houseicon .door { fill: var(--silver-2); }
.homebtn:hover { border-color: var(--silver-3); background: var(--silver-2); }
.homebtn svg { width: 21px; height: 21px; }

/* The house is two colours in its own right, so it does not take the button's
   currentColor. "You are here" therefore moves to the button's own surface
   rather than the icon's colour. */
.houseicon .floor { fill: var(--silver-3); }
.houseicon .roof  { fill: var(--pink); }
.houseicon .door  { fill: var(--paper); }

/* ------------------------------------------------------------ lists, cards */

.head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3);
        margin-bottom: var(--s-4); flex-wrap: wrap; }
.head h2 { font-size: var(--t-lg); font-weight: 600; margin: 0; }
.head .count { font-size: var(--t-sm); color: var(--muted); font-variant-numeric: tabular-nums; }

.daygroup { margin-bottom: var(--s-5); }
.dayname { font-size: var(--t-xs); font-weight: 600; letter-spacing: .09em;
           text-transform: uppercase; color: var(--rose); margin-bottom: var(--s-2); }

/* DES-10 — the one responsive rule. Nothing else changes layout by breakpoint. */
.grid { display: grid; gap: var(--s-3);
        grid-template-columns: repeat(auto-fit, minmax(288px, 1fr)); align-items: start; }

.card { padding: 2px; border-radius: var(--radius);
        background: linear-gradient(145deg, var(--silver-3), var(--silver-2) 30%,
                    var(--silver-1) 55%, var(--silver-3) 78%, var(--silver-2));
        box-shadow: var(--shadow-sm); }

.card > .inner { background: var(--paper); border-radius: calc(var(--radius) - 2px);
                 padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); }

.card.playing > .inner { background: var(--pink-lo); }
/* Briefly, after arriving from a search — enough to say "this one". */
.card.found > .inner { box-shadow: inset 0 0 0 2px var(--pink); }
.card.held    > .inner { background: var(--silver-2); }

.row { display: flex; align-items: center; gap: var(--s-3); }
.row .grow { flex: 1; min-width: 0; }

.title { font-size: var(--t-md); font-weight: 500; overflow-wrap: anywhere; }
.meta  { font-size: var(--t-xs); color: var(--muted); display: flex; gap: var(--s-2);
         flex-wrap: wrap; font-variant-numeric: tabular-nums; }
.meta .who { color: var(--rose); font-weight: 500; }
/* The countdown on a news message. Slate, not rose: it is a fact about the
   message, not a warning about it. */
.meta .going { color: var(--slate); font-weight: 500; }

.kindrow { justify-content: space-between; gap: var(--s-2); flex-wrap: wrap; }
.kindrow .states { flex: 1 1 auto; }
.kindrow .btn { padding: 8px 12px; font-size: var(--t-xs); min-height: 40px; }

/* DES-12 — every tap target at least 44px. */
.play {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--silver-1); background: var(--paper); color: var(--pink);
  display: grid; place-items: center;
}
.play[aria-pressed="true"] { background: var(--pink); color: var(--rose-ink); border-color: var(--pink); }
.play svg { width: 17px; height: 17px; }

.bar { height: 3px; border-radius: 3px; background: var(--silver-1); overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--pink); width: 0; }

/* ------------------------------------------------------------ song table */

.songbar { display: flex; align-items: center; justify-content: space-between;
           gap: var(--s-3); flex-wrap: wrap; margin-bottom: var(--s-5); }

/* A native <select> rather than another row of chips: three more chips would
   have cost a whole line of screen on a phone to say something read rarely. */
.sortwrap { flex: 0 0 auto; }
.sortwrap select {
  font: inherit; font-size: var(--t-sm); color: var(--ink);
  background: var(--paper); border: 1px solid var(--silver-1);
  border-radius: 999px; padding: 10px 13px; min-height: 44px;
}
.sortwrap select:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

/* Duration sits under the title rather than in a fourth column: a column would
   have taken 52px from the song name, which is the thing people actually read. */
.sdur { display: block; font-size: var(--t-xs); color: var(--muted);
        font-variant-numeric: tabular-nums; margin-top: 2px; }

/* R1-32 — one row per song. The three state columns are a fixed width so the
 * ticks line up vertically and the whole library reads down a column. */
.stable { --col: 52px; width: 100%; }

.shead, .srow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--col) var(--col) var(--col);
  align-items: center;
  gap: var(--s-2);
}

.shead {
  position: sticky; top: 0; z-index: 5;
  background: var(--paper);
  border-bottom: 1px solid var(--silver-1);
  padding: 8px 0;
  font-size: calc(0.6562rem * var(--scale)); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.shead span + span { text-align: center; }

.srow { border-bottom: 1px solid var(--hair); min-height: 52px; }
.srow:last-child { border-bottom: none; }
.srow.hold .sname    { color: var(--muted); }
.srow.deleted .sname { color: var(--muted); text-decoration: line-through;
                       text-decoration-color: var(--silver-3); }

/* The song name is the row's main control, so it takes the WHOLE cell rather
 * than only the area its text happens to cover. It was a button sized to its
 * own text: a short title left most of the row dead, and the gap between the
 * two lines of a wrapped title missed entirely. Reported on a phone as "very
 * hard to get it selected". */
.sname {
  font-size: calc(0.9062rem * var(--scale));
  overflow-wrap: anywhere;
  display: flex; flex-direction: column; justify-content: center;
  align-items: flex-start; text-align: left;
  width: 100%; min-height: 52px; padding: 8px 6px 8px 0;
  border: none; background: none; color: inherit; border-radius: 10px;
  margin-left: -6px; padding-left: 6px;   /* keeps the text optically aligned */
}
.sname:active { background: var(--pink-lo); }
.sname:hover { background: var(--silver-2); }

/* DES-12 — 44px minimum, met by height plus the row gap. */
.scell {
  height: 44px; width: 100%; padding: 0;
  border: none; background: none; border-radius: 10px;
  display: grid; place-items: center; color: var(--silver-1);
}
/* An empty cell with no affordance is untappable-looking. The ring says
 * "this is a choice"; the tick says "this is the one". */
.scell::before {
  content: ""; position: absolute; width: 21px; height: 21px;
  border-radius: 50%; border: 1.5px solid var(--silver-1);
}
.scell { position: relative; }
.scell svg { width: 19px; height: 19px; position: relative; }
.scell[aria-checked="true"]::before { border-color: transparent; }
.scell[aria-checked="true"] { color: var(--green); }
.srow .scell[data-set="hold"][aria-checked="true"]    { color: var(--slate); }
.srow .scell[data-set="deleted"][aria-checked="true"] { color: var(--rose); }
.scell:hover:not([aria-checked="true"])::before { border-color: var(--silver-3); }

/* --------------------------------------------------------------- controls */

.btn {
  border: 1px solid var(--silver-1); background: var(--paper); color: var(--ink);
  border-radius: 999px; padding: 10px 15px; font-size: var(--t-sm); font-weight: 500;
  min-height: 44px;
}
.btn:hover { border-color: var(--silver-3); }
.btn.on { border-color: var(--rose); background: var(--rose-lo); color: var(--rose); }
.btn.danger { color: var(--rose); border-color: var(--rose); }
.btn.ghost { border-color: transparent; color: var(--muted); }

.send {
  width: 100%; background: var(--pink); color: var(--rose-ink); border: none;
  border-radius: var(--radius); padding: 17px; font-size: var(--t-md); font-weight: 600;
  min-height: 44px;
  box-shadow: 0 0 0 2px var(--silver-2),
              0 10px 24px -10px color-mix(in srgb, var(--pink) 75%, transparent);
}

.states { display: flex; gap: var(--s-2); flex-wrap: wrap; }


.edit { font: inherit; font-size: var(--t-md); font-weight: 500; color: var(--ink);
        border: none; border-bottom: 1px solid var(--silver-1); background: none;
        padding: 2px 0; width: 100%; border-radius: 0; }
.edit:focus { outline: none; border-bottom-color: var(--pink); }

/* ------------------------------------------------------------------- nav */

nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: flex; justify-content: center; gap: var(--s-1);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--hair);
  padding: 6px 8px calc(6px + env(safe-area-inset-bottom, 0px));
}

nav button {
  flex: 1 1 0; max-width: 160px; min-height: 52px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: none; background: none; color: var(--muted);
  font-size: calc(0.6875rem * var(--scale)); font-weight: 600; letter-spacing: .02em; border-radius: 12px;
}
nav button svg { width: 21px; height: 21px; }
nav button[aria-current="page"] { color: var(--pink); }

/* Tablet and up: the bar becomes a segmented control at the top of the page. */
@media (min-width: 700px) {
  body { padding-bottom: var(--s-6); }
  nav {
    position: static; border-top: none; backdrop-filter: none; background: none;
    max-width: var(--wide-max); margin: var(--s-5) auto var(--s-2); padding: 0;
    gap: var(--s-2); justify-content: flex-start;
  }
  nav button {
    flex: 0 0 auto; max-width: none; min-height: 44px;
    flex-direction: row; gap: var(--s-2); padding: 9px 16px;
    border: 1px solid var(--silver-1); border-radius: 999px; font-size: var(--t-sm);
  }
  nav button[aria-current="page"] { border-color: var(--pink); background: var(--pink-lo); }
  .app { padding-top: var(--s-2); }
}

@media (min-width: 1024px) {
  .app { padding-left: var(--s-6); padding-right: var(--s-6); }
  .home { padding-top: var(--s-7); }
}

/* ------------------------------------------------------- empty, toast, dlg */

.empty { text-align: center; color: var(--muted); padding: var(--s-7) var(--s-4); }
.empty strong { display: block; color: var(--ink); font-size: var(--t-md);
                font-weight: 500; margin-bottom: var(--s-2); }

.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(84px + env(safe-area-inset-bottom, 0px)); z-index: 40;
  background: var(--ink); color: #fff; padding: 11px 18px; border-radius: 999px;
  font-size: var(--t-sm); box-shadow: var(--shadow); max-width: calc(100vw - 32px);
}
.toast[hidden] { display: none !important; }
@media (min-width: 700px) { .toast { bottom: var(--s-5); } }

dialog {
  border: none; padding: 0; border-radius: var(--radius-lg); max-width: 340px; width: calc(100% - 40px);
  box-shadow: var(--shadow); color: var(--ink); background: var(--paper);
}
dialog::backdrop { background: rgba(40, 30, 36, .34); }
dialog .inner { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-4); }
dialog h3 { margin: 0; font-family: var(--serif); font-size: var(--t-lg); font-weight: 400; }
dialog p { margin: 0; font-size: var(--t-sm); color: var(--muted); }

.offline { background: var(--rose-lo); color: var(--rose); border-radius: var(--radius);
           padding: 10px 14px; font-size: var(--t-sm); margin-bottom: var(--s-4); }
.offline[hidden] { display: none !important; }
