/* Appearance ▸ Looks — the theme, accent, icon, card and conversation pickers.

   Split out of styles.css on 2026-09-05. Two reasons, and the second is the real one:

   1. styles.css is 219 KB and every feature in the app has a stake in it, so a panel that is
      being redesigned in place is a panel that is permanently in conflict with something.
   2. This screen is the ONE place where every theme has to look like itself at once. The
      cards are miniatures of six different design languages sitting in a row, each drawn in
      the theme it represents rather than in the theme you are wearing — which means the rules
      here have to be immune to whatever the worn theme is doing to everything else.
      That is a different job from the rest of styles.css and it reads better with a border
      around it.

   Loaded from index.html right after styles.css and BEFORE theme-boot.js, so a theme sheet
   still wins over anything in here — the source-order rule in themes/README.md applies to this
   file exactly as it applies to styles.css.

   The miniatures are iframes, and everything they contain is styled by the copy of styles.css
   the FRAME loads, not by this file: nothing below reaches inside one, and nothing below could
   if it wanted to. See the long note on configuratorHTML in app.js for why that is the whole
   point rather than an implementation detail. */

/* `.looks` exists mainly to hold this one line: the first-run picker centres its column, and
   a settings screen whose labels are centred reads as a splash page. */
.looks { text-align: left; }

.lk-sec + .lk-sec { margin-top: 22px; }

/* Two headings and then a rule. Theme and Accent are the decisions someone came here to make;
   the four under the rule are details of one view each, and the type says so before any of
   them is read. This is the whole of the "structure that matches how much each decision
   matters" — a size, a weight and a line, rather than an accordion. */
.lk-h {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 0 0 10px;
  font-family: var(--font-d); font-size: var(--fs-xl); font-weight: var(--fw-bold); letter-spacing: calc(-.01em * var(--tracking));
}
.lk-note { font-family: var(--font-b); font-size: calc(var(--fs-sm) + var(--fs-half)); font-weight: var(--fw-regular); color: var(--mut); }

/* ---- the theme cards ----
   auto-fit at 210px puts three across the 760px dialog and two on a phone, and the frame
   inside scales to whatever that came out as. Nothing here is a fixed pixel width, because
   the app also runs at 80% and 140% and the card is not allowed to know which. */
.lk-themes { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; }
.lk-card {
  display: block; padding: 0; overflow: hidden; text-align: left;
  border: 1px solid var(--line); border-radius: var(--r); background: var(--panel);
  transition: border-color .14s, transform .14s var(--ease);
}
.lk-card:hover { transform: translateY(-2px); border-color: var(--line2); }
.lk-card.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.lk-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* (2026-10-01, round five) One height for every card, not one per row: a tagline that wraps or
   a pair of flags made Gloss's and Kirameki's second row 18px taller than the first. Every row
   is as tall as the tallest card, and the card is a column whose body takes what is left. */
.lk-themes { grid-auto-rows: 1fr; }
.lk-themes > .lk-card { display: flex; flex-direction: column; }
.lk-themes > .lk-card > .lk-prev { flex: none; }
.lk-themes > .lk-card > .lk-body { flex: 1 1 auto; }

/* The slot the miniature is scaled into. `--mini-s` is written by mountThemePreviews, because
   the ratio between the frame's fixed 820px and this box's width is a division of a length by
   a length and CSS cannot do one. The aspect-ratio has to agree with MINI_W / MINI_H in app.js
   or the frame will not fill it; 820 / 520 is 41 / 26.

   The background is the theme's own ground colour from the registry, so the moment before the
   frame paints shows the right colour rather than the worn theme's panel. */
.lk-prev {
  display: block; position: relative; width: 100%; aspect-ratio: 41 / 26;
  overflow: hidden; border-bottom: 1px solid var(--line);
}
.lk-frame {
  position: absolute; left: 0; top: 0;
  width: 820px; height: 520px; border: 0; background: transparent;
  transform: scale(var(--mini-s, .28)); transform-origin: 0 0;
  /* A frame inside a button would otherwise swallow every click meant for the card. */
  pointer-events: none;
}

.lk-body { display: block; padding: calc(9 * var(--sp)) calc(11 * var(--sp)) calc(11 * var(--sp)); }
.lk-nm { display: block; font-weight: var(--fw-bold); font-size: calc(var(--fs-base) + var(--fs-half)); }
.lk-tag { display: block; margin-top: 2px; font-size: calc(var(--fs-sm) + var(--fs-half)); color: var(--mut); line-height: 1.4; }

/* The two things the picture cannot say. Deliberately words and not icons: "this rebuilds the
   app" and "this makes a noise" are both claims, and a claim wants a sentence fragment rather
   than a glyph somebody has to hover to decode. */
.lk-flags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.lk-flag {
  font-size: calc(var(--fs-xs) + var(--fs-half)); line-height: 1.5; padding: calc(1 * var(--sp)) calc(6 * var(--sp));
  border: 1px solid var(--line); border-radius: var(--r-pill); color: var(--mut); white-space: nowrap;
}

/* ---- does the theme get to speak ----
   A plain checkbox in a bordered strip, sitting with the theme grid rather than three headings
   down among the effects — see themeSound() in theme-boot.js for why it is not feel.js's sound
   switch. Rendered only for a theme that has cues, so it is never a control with nothing on
   the other end of it. */
.lk-sw {
  display: flex; align-items: flex-start; gap: 10px; margin-top: 12px;
  padding: calc(10 * var(--sp)) calc(12 * var(--sp)); min-height: 24px;
  border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer;
}
.lk-sw:hover { border-color: var(--line2); }
.lk-sw input { flex: none; width: 16px; height: 16px; margin: 1px 0 0; accent-color: var(--accent); }
.lk-sw > span { display: block; font-size: var(--fs-base); font-weight: var(--fw-semi); }
.lk-sw em { display: block; margin-top: 2px; font-style: normal; font-size: calc(var(--fs-sm) + var(--fs-half)); font-weight: var(--fw-regular); color: var(--mut); }

/* ---- accent ----
   A swatch and a name, and nothing else. The old accent card was a five-rectangle miniature of
   the app with an accent pill in it, which answered "what does this theme look like" a second
   time in the section that is not about themes. What is being chosen here is a colour, the
   whole app previews it on hover, and so the preview is the colour. */
.lk-accents { display: grid; grid-template-columns: repeat(auto-fit, minmax(116px, 1fr)); gap: 8px; }
.lk-acc {
  display: flex; align-items: center; gap: 9px; min-height: 38px; padding: calc(8 * var(--sp)) calc(11 * var(--sp));
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--panel);
  text-align: left; transition: border-color .14s, transform .14s var(--ease);
}
.lk-acc:hover { transform: translateY(-1px); border-color: var(--line2); }
.lk-acc.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.lk-acc:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lk-acc .lk-nm { font-size: calc(var(--fs-md) + var(--fs-half)); font-weight: var(--fw-semi); }
/* The inset ring rather than a border, so a swatch the colour of the card is still a disc. */
.lk-dot { flex: none; width: 18px; height: 18px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgb(0 0 0 / .22); }
.lk-custom { position: relative; cursor: pointer; }
.lk-custom input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }

/* ---- the four smaller ones ----
   One rule above them is the whole demotion. Each keeps the grid it already had; only the
   heading changes, from a heading to a label. */
.lk-minor { margin-top: 22px; padding-top: calc(18 * var(--sp)); border-top: 1px solid var(--line); }
.lk-row + .lk-row { margin-top: 16px; }
.lk-lbl {
  display: block; margin-bottom: 7px;
  font-size: calc(var(--fs-xs) + var(--fs-half)); font-weight: var(--fw-semi); letter-spacing: calc(.09em * var(--tracking)); text-transform: var(--label-case);
  color: var(--faint);
}
/* Smaller than they were: four card shapes at 140px each pushed the row to two lines in the
   760px dialog, and a setting that wraps reads as two settings. */
.lk-minor .icon-cards { grid-template-columns: repeat(auto-fit, minmax(124px, 1fr)); gap: 8px; }
.lk-minor .ic-card { padding: calc(10 * var(--sp)) calc(10 * var(--sp)) calc(9 * var(--sp)); }
.lk-minor .ic-card .badge { --tile: 26px; }
.lk-lbl .lk-note { text-transform: none; letter-spacing: 0; margin-left: 4px; }
.lk-minor .motion-seg { gap: 8px; }

/* ---- the first-run dialog ----
   The same cards as Appearance, smaller: theme miniatures three to a row with the name only,
   the accents in one row, the icon cards without their sentences. Grids that fit themselves
   rather than breakpoints, because a width query meets the UI zoom and is off by its factor.
   It has to fit a 945px-tall window at 110% without scrolling, so the body is not a scroller
   of its own here — on a phone the whole overlay scrolls instead. */
.firstrun .fr-inner { width: 700px; max-width: 100%; }
/* A column no taller than the screen, the body scrolling between a fixed head and foot, so Start
   is always on screen (judges 17.10.2026: at 360x780 the dialog was 1054 px and Start scrolled
   away with it). 100dvh is divided by the UI zoom, which it is measured before. */
.firstrun .fr-inner { display: flex; flex-direction: column; max-height: calc(100dvh / var(--ui-z, 1) - 24px); }
.firstrun .fr-inner > .modal-head, .firstrun .fr-inner > .modal-foot { flex: none; }
/* Three classes deep because Lucid caps every dialog body at 58vh from `html[data-deep] .modal-body`
   (0,2,1), which left the icons row running under the footer. */
.firstrun .fr-inner > .modal-body { flex: 1 1 auto; min-height: 0; max-height: none; overflow: auto; overscroll-behavior: contain; padding: calc(14 * var(--sp)) calc(18 * var(--sp)) calc(16 * var(--sp)); }
.firstrun .lk-sec + .lk-sec { margin-top: 14px; }
.firstrun .lk-h { margin-bottom: 8px; font-size: calc(var(--fs-base) + var(--fs-half)); }
.fr-themes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.fr-themes .lk-body { padding: calc(6 * var(--sp)) calc(9 * var(--sp)) calc(7 * var(--sp)); }
.fr-themes .lk-nm { font-size: calc(var(--fs-md) + var(--fs-half)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fr-acc { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 6px; }
.fr-acc .lk-acc { min-height: 34px; padding: calc(6 * var(--sp)) calc(9 * var(--sp)); gap: 7px; }
.fr-acc .lk-dot { width: 16px; height: 16px; }
.fr-ic { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
/* A card is a third of a phone, and less again under a theme that pads its sections, so the
   badges size to the card rather than the card to the badges: 24px where there is room, down
   to whatever three and two gaps leave where there is not. */
.fr-ic .ic-card { padding: calc(9 * var(--sp)) calc(10 * var(--sp)) calc(8 * var(--sp)); container-type: inline-size; }
.fr-ic .ic-row { gap: 5px; margin-bottom: 7px; }
.fr-ic .badge { --tile: min(24px, calc((100cqw - 10px) / 3)); }
.fr-ic .th-name { font-size: calc(var(--fs-md) + var(--fs-half)); }
.firstrun .modal-foot { align-items: center; }
.fr-note { margin-right: auto; font-size: var(--fs-md); color: var(--mut); }

/* A preference asked of the system outranks every hover flourish above. */
@media (prefers-reduced-motion: reduce) {
  .lk-card, .lk-acc { transition: none; }
  .lk-card:hover, .lk-acc:hover { transform: none; }
}

/* One column below the width where two cards would each be narrower than their own text. */
@media (max-width: 460px) {
  .lk-themes { grid-template-columns: 1fr; }
}
