/**
 * The account app.
 *
 * This page used to borrow its looks from two places that were never meant
 * for it: drawer.css, which dresses a 320px panel sliding over a television,
 * and remote.css, left behind by the pairing UI. Controls sized for a remote
 * control, laid out for a phone, on a laptop-width page — which is why a
 * screen's name and its collection ran together with no space between them.
 *
 * The palette, the weight-300 type and the blue are the landing page's and
 * the frame's. One product, one hand. What is new here is the shape of the
 * things:
 *
 *   A screen is a card, 16:9, and it is lit. Its brightness is how recently
 *   the display checked in — bright means it is on the wall working, cold
 *   means nobody has heard from it. That is the one question an owner
 *   actually has, and `lastSeenAt` already comes back in the payload.
 *
 *   A collection is a row. It is a set, not an object in a room, and giving
 *   it the same card as a screen is what made the old page unreadable.
 *
 * drawer.css is still loaded and still wanted: its unscoped `.field`,
 * `.switch` and `.albums` rules are the shared control styling that
 * `buildPanel` emits, and duplicating them here would mean two definitions of
 * a switch. Only its `#drawer`-scoped chrome is irrelevant, and that scopes
 * itself out.
 */

:root {
  --void:   #0b0b0d;
  --lift:   #191920;
  --panel:  rgba(255, 255, 255, .045);
  --raised: rgba(255, 255, 255, .09);
  /*
   * Two border weights, and the difference is not decorative:
   *
   *   --edge         hairlines between rows. Decorative, may be faint.
   *   --edge-strong  the visible boundary of a control — a button, an input,
   *                  a slider track. WCAG wants 3:1 against the background
   *                  for these, and both themes are set to clear it. At the
   *                  old .18 a button in daylight measured 1.7:1 and read as
   *                  disabled.
   */
  --edge:   rgba(255, 255, 255, .12);
  --edge-strong: rgba(255, 255, 255, .34);

  /* The accent the frame's switches use. Kept for light and focus only. */
  --glow: #8ab4f8;
  --glow-hover: #a8c8ff;
  --on-glow: #10131a;          /* text on a glow-filled control */

  /* 16.9:1, 6.9:1 and 4.8:1 on --void. --faint was .38, which measured
     3.5:1 and put every slider readout and photo count under the floor. */
  --paper: rgba(255, 255, 255, .93);
  --muted: rgba(255, 255, 255, .58);
  --faint: rgba(255, 255, 255, .48);

  --ok:     var(--glow);
  --warn:   rgba(240, 205, 140, .9);
  --danger: #ffb4a8;
  --danger-tint: rgba(255, 120, 100, .08);

  --input-bg: rgba(0, 0, 0, .25);
  --code-bg:  rgba(0, 0, 0, .3);
  --bar-bg:   rgba(11, 11, 13, .82);
  --option-bg: #16161b;
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23ffffff' stroke-opacity='.5' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --measure: 62rem;
  --radius: .85rem;
}

/*
 * Daylight. The composer is the page that gets used on a phone at noon, so
 * unlike the frame it has a light scheme — a photo frame is a dark surround
 * by definition, and frame.css keeps it that way. Which scheme runs is a
 * `data-theme` attribute, set before first paint by app.html: the device's
 * preference until somebody picks one in the top bar, and that choice stays
 * in this browser. Cool gallery neutrals rather than warm paper: the
 * product's world is lit screens on walls, and the accent deepens so it can
 * carry text. The screen faces themselves stay dark glass in both schemes —
 * a display on a white wall is still a dark rectangle.
 */
:root[data-theme="light"] {
  --void:   #eef0f4;
  --lift:   #fdfdfe;
  --panel:  rgba(18, 20, 26, .045);
  --raised: rgba(18, 20, 26, .10);
  /*
   * Higher alphas than the dark scheme, not mirrored ones. Dark ink on a
   * light ground loses contrast much faster as alpha drops than white ink on
   * a dark ground does, so copying the dark values across is exactly what
   * left this scheme looking bleached: buttons at 1.7:1 reading as disabled
   * and slider tracks at 1.1:1 reading as absent.
   */
  --edge:   rgba(18, 20, 26, .18);
  --edge-strong: rgba(18, 20, 26, .46);

  --glow: #2d64c8;
  --glow-hover: #24549e;
  --on-glow: #ffffff;

  /* 14:1, 6.1:1 and 4.6:1 on --void. */
  --paper: rgba(14, 16, 21, .92);
  --muted: rgba(14, 16, 21, .68);
  --faint: rgba(14, 16, 21, .60);

  --warn:   #96690f;
  --danger: #b23c2b;
  --danger-tint: rgba(178, 60, 43, .08);

  --input-bg: rgba(18, 20, 26, .045);
  --code-bg:  rgba(18, 20, 26, .05);
  --bar-bg:   rgba(250, 250, 252, .85);
  --option-bg: #ffffff;
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23101318' stroke-opacity='.55' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Native controls (scrollbars, spinners, pickers) follow the chosen scheme,
   not the device's. */
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  background: var(--void);
  background-image: radial-gradient(120% 60% at 50% 0%, var(--lift) 0%, var(--void) 55%);
  background-attachment: fixed;
  min-height: 100%;
}

body {
  font-family: "Google Sans", "Product Sans", Roboto, -apple-system,
               "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  color: var(--paper);
  line-height: 1.55;
}

/* ============================================================
   Shell
   ============================================================ */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .85rem clamp(1rem, 4vw, 2rem);
  border-bottom: 1px solid var(--edge);
  background: var(--bar-bg);
  backdrop-filter: blur(12px);
}

.wordmark {
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--paper);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: .9rem;
  min-width: 0;
}

.whoami {
  font-family: var(--mono);
  font-size: .76rem;
  color: var(--faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#app {
  width: min(100%, var(--measure));
  margin: 0 auto;
  padding: clamp(1.75rem, 5vh, 3rem) clamp(1rem, 4vw, 2rem) 5rem;
}

/* ============================================================
   Type
   ============================================================ */

#app h1 {
  font-size: clamp(1.7rem, 3.6vw, 2.2rem);
  font-weight: 300;
  letter-spacing: -.022em;
  line-height: 1.1;
}

/*
 * The eyebrow marks a region of the page. Monospace and letterspaced because
 * these are labels for machinery, not headings in prose.
 */
.eyebrow {
  font-family: var(--mono);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--faint);
}

#app .hint {
  font-size: .9rem;
  font-weight: 400;
  color: var(--muted);
  max-width: 46em;
}

/* Machine facts: counts, timestamps, ids. Not prose, and typed as such. */
.fact {
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   Page header and sections
   ============================================================ */

.page-head { margin-bottom: clamp(1.5rem, 4vh, 2.25rem); }
.page-head .eyebrow { display: block; margin-bottom: .55rem; }
.page-head .hint { margin-top: .7rem; }

/* `first-child`, not `first-of-type`: a section that follows the screen grid
   is still mid-page, and first-of-type gave the only section on the page a
   zero margin no matter what stood above it. */
.section { margin-top: clamp(2.25rem, 6vh, 3.5rem); }
.section:first-child { margin-top: 0; }

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: .7rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--edge);
}

/* ============================================================
   Buttons
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .45em;
  padding: .55em 1.05em;
  font: inherit;
  font-size: .9rem;
  font-weight: 400;
  color: var(--paper);
  background: var(--panel);
  border: 1px solid var(--edge-strong);
  border-radius: .55rem;
  cursor: pointer;
  transition: background 130ms ease, border-color 130ms ease, transform 130ms ease;
}
.btn:hover:not(:disabled) { background: var(--raised); border-color: var(--paper); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: default; }

.btn--primary {
  background: var(--glow);
  border-color: transparent;
  color: var(--on-glow);
  font-weight: 500;
}
.btn--primary:hover:not(:disabled) { background: var(--glow-hover); border-color: transparent; }

/* A text button. For actions that are available but not being encouraged. */
.btn--quiet {
  padding: .4em .2em;
  background: none;
  border-color: transparent;
  color: var(--muted);
}
.btn--quiet:hover:not(:disabled) {
  background: none;
  border-color: transparent;
  color: var(--paper);
}

.btn--danger { color: var(--muted); }
.btn--danger:hover:not(:disabled) {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--danger-tint);
}

.back {
  margin-bottom: 1.5rem;
  font-size: .86rem;
  color: var(--muted);
}

:where(a, button, input, select, summary):focus-visible {
  outline: 2px solid var(--glow);
  outline-offset: 2px;
  border-radius: .3rem;
}

/* ============================================================
   Screens — the signature
   ============================================================ */

.screen-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
  gap: clamp(1rem, 2.5vw, 1.6rem);
  list-style: none;
}

.screen-card {
  display: flex;
  flex-direction: column;
  gap: .85rem;
  width: 100%;
  padding: 0;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/*
 * The display itself.
 *
 * `--lum` is set per card from how recently the screen was last heard from:
 * 1 for one that checked in moments ago, 0 for one nobody has heard from. The
 * glow is the reading — which is why it does not pulse. A brightness that
 * moves cannot also be a measurement.
 */
.screen-face {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background:
    radial-gradient(120% 100% at 50% 45%,
      rgba(150, 190, 255, calc(.20 * var(--lum, 0))) 0%,
      rgba(120, 165, 240, calc(.09 * var(--lum, 0))) 55%,
      rgba(90, 130, 210, calc(.03 * var(--lum, 0))) 100%),
    linear-gradient(180deg, rgba(255, 255, 255, .055), rgba(255, 255, 255, .012));
  /* Contained: the spill is close to the edge, the way a screen lights the wall
     just behind it rather than casting a shadow onto the floor. */
  box-shadow:
    inset 0 0 3rem rgba(150, 190, 255, calc(.12 * var(--lum, 0))),
    0 0 0 1px rgba(138, 180, 248, calc(.22 * var(--lum, 0))),
    0 .4rem 2rem -.9rem rgba(138, 180, 248, calc(.55 * var(--lum, 0)));
  overflow: hidden;
  transition: box-shadow 200ms ease, border-color 200ms ease, transform 200ms ease;
}

.screen-card:hover .screen-face,
.screen-card:focus-visible .screen-face {
  transform: translateY(-2px);
  border-color: var(--edge-strong);
}

.screen-meta { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }

/* The bug the old page had: these two sat inline with nothing between them. */
.screen-name {
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.screen-showing {
  font-size: .85rem;
  font-weight: 400;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.screen-showing[data-empty="true"] { color: var(--faint); font-style: italic; }

.liveness { display: flex; align-items: center; gap: .45rem; margin-top: .1rem; }
.liveness::before {
  content: "";
  width: .42rem;
  height: .42rem;
  border-radius: 50%;
  flex: none;
  background: color-mix(in srgb, var(--glow) calc(var(--lum, 0) * 100%), rgba(255,255,255,.22));
  box-shadow: 0 0 .5rem rgba(138, 180, 248, calc(.9 * var(--lum, 0)));
}

/*
 * The frame's own overlay, to scale. frame.css puts the clock at
 * left 4.4vw / bottom 5.2vh of the display; these are the same fractions of
 * the card, so the miniature sits where the real thing does.
 */
.face-overlay {
  position: absolute;
  left: 4.4%;
  bottom: 5.2%;
  right: 4.4%;
  display: flex;
  flex-direction: column;
  gap: .1em;
  line-height: 1.15;
  color: rgba(255, 255, 255, calc(.30 + .55 * var(--lum, 0)));
  text-shadow: 0 1px 6px rgba(0, 0, 0, .6);
  pointer-events: none;
}
.face-time {
  font-size: 1.5rem;
  font-weight: 300;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.face-date { font-size: .68rem; font-weight: 300; opacity: .72; }

/* A screen with no collection has nothing to show, and says so — which is what
   the frame itself puts on the wall in that state. */
.face-overlay--idle {
  inset: 0;
  align-items: center;
  justify-content: center;
}
.face-idle {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Add a screen. Same shape as the thing it makes, so the grid stays a grid. */
.screen-add .screen-face {
  display: grid;
  place-items: center;
  border-style: dashed;
  border-color: var(--edge);
  background: none;
  box-shadow: none;
  color: var(--muted);
  font-size: .92rem;
}
.screen-add:hover .screen-face { border-color: var(--edge-strong); color: var(--paper); }

/* ============================================================
   Collections — rows, because a set is not an object
   ============================================================ */

.rows { list-style: none; border-top: 1px solid var(--edge); }
.rows li { border-bottom: 1px solid var(--edge); }

.row {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  padding: .95rem .75rem;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  border: 0;
  border-radius: .5rem;
  cursor: pointer;
  transition: background 130ms ease;
}
.row:hover { background: var(--panel); }
.row-name { flex: 1; min-width: 0; font-weight: 400; overflow: hidden; text-overflow: ellipsis; }
.row-chevron { color: var(--faint); flex: none; }
.row:hover .row-chevron { color: var(--paper); }

/* ============================================================
   Empty states — an invitation, not an apology
   ============================================================ */

.empty {
  padding: 2.25rem 1.5rem;
  text-align: center;
  border: 1px dashed var(--edge);
  border-radius: var(--radius);
  color: var(--muted);
  font-weight: 400;
}
.empty strong { display: block; color: var(--paper); font-weight: 400; margin-bottom: .3rem; }

/* ============================================================
   Forms
   ============================================================ */

.card {
  padding: clamp(1.1rem, 3vw, 1.6rem);
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
}

#app input[type="email"],
#app input[type="url"],
#app input[type="text"],
#app input[type="search"],
#app select {
  width: 100%;
  padding: .7em .9em;
  font: inherit;
  font-size: .95rem;
  color: var(--paper);
  background: var(--input-bg);
  border: 1px solid var(--edge-strong);
  border-radius: .55rem;
}
#app input::placeholder { color: var(--faint); }
#app input:focus, #app select:focus { border-color: var(--glow); outline: none; }

#app select {
  appearance: none;
  padding-right: 2.4em;
  cursor: pointer;
  /* Inline chevron: a data URI token, because no request may leave this origin. */
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right .95em center;
}
#app select option { background: var(--option-bg); color: var(--paper); }

.inline-form { display: flex; gap: .6rem; align-items: stretch; }
/* `display: flex` outranks the user agent's `[hidden] { display: none }`, so
   without this the reveal form is open before anyone asks for it. */
.inline-form[hidden] { display: none; }
.inline-form.reveal { margin-bottom: 1.25rem; }
.inline-form.add-album { margin-top: 1.25rem; }
.inline-form input { flex: 1; }
.inline-form .btn { flex: none; }

/* Sign in is the whole page rather than a panel on one. */
.signin {
  max-width: 26rem;
  margin: clamp(2rem, 12vh, 6rem) auto 0;
}
.signin h1 { font-size: clamp(1.6rem, 4vw, 2.1rem); }
.signin .hint { margin-top: .7rem; }
.signin form { margin-top: 1.4rem; display: grid; gap: .7rem; }
.signin input[inputmode="numeric"] {
  font-size: 1.5rem;
  letter-spacing: .34em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   Status
   ============================================================ */

.status {
  margin-top: .8rem;
  font-size: .88rem;
  font-weight: 400;
  color: var(--muted);
}
.status:empty { display: none; }
#app .status--error { color: var(--danger); }
#app .status--ok { color: var(--ok); }
#app .status--warn { color: var(--warn); }
#app .status--busy { color: var(--muted); }

/* ============================================================
   Kiosk setup and devices
   ============================================================ */

.kiosk-url {
  display: block;
  width: 100%;
  margin: 1rem 0;
  padding: .85em 1em;
  font-family: var(--mono);
  font-size: .8rem;
  line-height: 1.6;
  color: var(--paper);
  background: var(--code-bg);
  border: 1px solid var(--edge);
  border-radius: .55rem;
  word-break: break-all;
}
.kiosk-url[data-empty="true"] { color: var(--faint); }

.actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .25rem; }
.actions + .hint { margin-top: .9rem; }

/*
 * Two kinds of row, and they differ in what carries the width. A device row's
 * only content is its timestamp, so that flexes. An album row's name flexes
 * and the count sits beside the action — sharing one class made album counts
 * stretch to half the row and float in the middle of nothing.
 */
.device-row, .album-row { display: flex; align-items: center; gap: 1rem; padding: .8rem .75rem; }

.device-row .fact { flex: 1; }
.album-row .row-name { flex: 1; }

/* ============================================================
   The settings panel, which is shared with the frame's drawer
   ============================================================ */

#app .settings-panel { display: grid; gap: 2rem; }
#app .settings-panel > section { display: grid; }

/*
 * Group headings are a second level below the section eyebrow, so they get a
 * different treatment rather than a smaller copy of the same one: sentence
 * case, no tracking, quiet. buildPanel emits an `h2` — targeting `h3` here is
 * why these first rendered at browser-default size, louder than the page
 * title they sit under.
 */
#app .settings-panel h2 {
  font-size: .84rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--paper);
  padding-bottom: .5rem;
  margin-bottom: .2rem;
  border-bottom: 1px solid var(--edge);
}

#app .settings-panel .field { padding: .75rem 0; border-bottom: 1px solid var(--edge); }
#app .settings-panel .field:last-child { border-bottom: 0; }
#app .settings-panel .field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
#app .settings-panel .field-label { font-size: .95rem; font-weight: 400; }
#app .settings-panel .readout {
  font-family: var(--mono);
  font-size: .76rem;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
#app .settings-panel .hint { margin-top: .3rem; font-size: .82rem; }

/*
 * The place search. drawer.css styles its input and suggestion list only under
 * `#drawer`, so on this page they arrived as an unstyled box the width of its
 * placeholder.
 */
#app input[type="search"] { width: 100%; }
#app .places { list-style: none; margin-top: .5rem; display: grid; gap: .25rem; }
#app .places button {
  width: 100%;
  padding: .5em .7em;
  font: inherit;
  font-size: .9rem;
  text-align: left;
  color: var(--paper);
  background: var(--panel);
  border: 1px solid var(--edge-strong);
  border-radius: .45rem;
  cursor: pointer;
}
#app .places button:hover { background: var(--raised); }
#app .places-empty { margin-top: .5rem; font-size: .85rem; color: var(--faint); }

/* ============================================================
   Motion
   ============================================================ */

/*
 * One orchestrated moment: the screens light up in sequence on arrival, the
 * way a row of displays does when the power comes back.
 */
@keyframes rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.screen-grid > li,
.rows > li {
  animation: rise 320ms cubic-bezier(.2, .7, .3, 1) backwards;
  animation-delay: calc(var(--i, 0) * 45ms);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
  }
}

@media (max-width: 34rem) {
  .topbar { padding: .7rem 1rem; }
  .whoami { display: none; }
  .section-head { flex-wrap: wrap; }
}

/* ------------------------------------------------------------- composer -- */

/* The screen's address as a QR, on its own light plate — a QR needs a hard
   black-on-white edge to scan off a lit screen. */
.qr {
  margin-top: 1.1rem;
  width: min(11rem, 60vw);
}
.qr svg { display: block; width: 100%; height: auto; }

/*
 * The shared controls, re-grounded in this page's tokens.
 *
 * drawer.css dresses buttons, sliders and switches only under `#drawer`,
 * which is correct there and absent here — without these rules the album
 * "Add" button and every range slider render as bare native controls. The
 * overrides also carry the light scheme: drawer.css is dark by definition,
 * this page is not.
 */

#app .switch { background: var(--raised); border-color: var(--edge-strong); }
#app .switch::after { background: var(--paper); }
#app .switch:checked { background: var(--glow); border-color: transparent; }
#app .switch:checked::after { background: var(--on-glow); }

#app input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: min(22rem, 100%);
  height: 1.1rem;
  margin-top: .4rem;
  background: none;
}
#app input[type="range"]::-webkit-slider-runnable-track {
  height: .28rem;
  border-radius: 1rem;
  background: var(--edge-strong);
}
#app input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: .95rem;
  height: .95rem;
  margin-top: -.34rem;
  border: 0;
  border-radius: 50%;
  background: var(--glow);
  cursor: pointer;
}
#app input[type="range"]::-moz-range-track {
  height: .28rem;
  border-radius: 1rem;
  background: var(--edge-strong);
}
#app input[type="range"]::-moz-range-thumb {
  width: .95rem;
  height: .95rem;
  border: 0;
  border-radius: 50%;
  background: var(--glow);
  cursor: pointer;
}

/* The album list, page colours instead of drawer.css's fixed dark. */
#app .albums li { background: var(--panel); border-color: var(--edge); }
#app .album-count { color: var(--faint); }
#app .albums-empty { color: var(--faint); border-color: var(--edge); background: none; }
#app .album-add { gap: .6rem; margin-top: .9rem; }
#app .album-add input { flex: 1; }

.album-remove {
  flex: none;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  padding: .3rem .45rem;
  cursor: pointer;
  border-radius: .4rem;
}
.album-remove:hover { color: var(--danger); background: var(--danger-tint); }

/* The theme button is an icon, so it gets icon geometry: square padding
   and no text metrics. */
#theme { padding: .45em; color: var(--muted); }
#theme:hover:not(:disabled) { color: var(--paper); }
#theme svg { display: block; width: 1.15rem; height: 1.15rem; }

/* Links dressed as what they are. */
.topbar a, #app a { color: inherit; text-decoration: none; }
.back { display: inline-block; }
a.back:hover { color: var(--paper); }

/* Cards rest at a quiet uniform glow — with no liveness data there is no
   measurement to fake, so every face gets the same low light. */
.screen-card { --lum: .45; }
.screen-add { --lum: 0; }
.screen-face { background-color: #0e0f13; }
.screen-add .screen-face { background-color: transparent; }
.face-time { font-size: 1.05rem; font-weight: 400; letter-spacing: -.01em; }
