/* Copyright (c) 2026 FR&D. All rights reserved. */

/* /home: the promo, framed, above the landing (home-film.html; the Worker composes the page
   from index.html, so everything below the film is styles.css's). The film is one viewport
   tall — the small viewport, so a phone's toolbar collapsing mid-scroll does not resize the
   promo — and the landing follows at its own height. The landing's header is where Read on
   and ↓ land; it takes focus so keys go on from there, without a ring for a scroll. */
.film { height: 100vh; height: 100svh; background: var(--paper); }
.film-frame { display: block; width: 100%; height: 100%; border: 0; }
#landing:focus { outline: none; }

/* The seam: the promo's play bar becomes the landing's top bar. With home.js running
   (the html gets .home-seam before the body exists), the header is pulled up over the film's
   last strip — the promo's bottom bar: 57 px on a desktop, 10 px of padding round a 36 px
   button and its line, which the header matches here — and paints above the film, so the
   two share one strip. home.js sets --seam from the scroll: 0 while the film is on the
   screen (the header hidden, the play bar under it the control), rising to 1 over the
   strip's last stretch to the top of the viewport, where the header pins (sticky) and the
   landing reads on under it. Between, the header is a dissolve over the bar that takes no
   clicks, its wordmark and links settling in from a few pixels below. Without the script the
   header simply follows the film, as any section would. */
.home-seam .site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  margin-top: -57px;
  background: var(--paper);
  opacity: var(--seam, 0);
}
.home-seam .site-header .container { min-height: 56px; translate: 0 calc((1 - var(--seam, 0)) * 10px); }
.home-seam .site-header[data-seam="off"] { visibility: hidden; }
.home-seam .site-header[data-seam="mid"] { pointer-events: none; }
/* iOS 26 Safari lays the page out under its bars: the sticky header pins at the top of the
   layout viewport, below the collapsed address chip, and what has scrolled past goes on
   painting in the strip under the chip (the reading's first line showed there, over the
   pinned header). Safari extends a fixed element's background into that strip on its own; a
   sticky one gets nothing, so the pinned header paints its own paper upward. Anywhere else
   the strip is above the viewport and never shows. */
.home-seam .site-header[data-seam="on"]::before { content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 200px; background: var(--paper); }
.film { position: relative; z-index: 30; }
@media (prefers-reduced-motion: reduce) { .home-seam .site-header .container { translate: none; } }
/* The promo's Dark/Light toggle in the header (spliced by the Worker, src/index.ts): the play
   bar's own pill, in the landing's tokens, showing the theme in use the way the promo's does
   (a moon and Dark, or a sun and Light). Which pair shows follows the OS, or data-theme on
   <html> when the visitor has chosen, spelled out both ways like styles.css's tokens. Without
   home.js it can do nothing, so it hides until the script marks the document. */
.theme-toggle { display: none; }
.home-seam .theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 36px;
  padding: 6px 14px 6px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color .18s ease, border-color .18s ease;
}
.home-seam .theme-toggle:hover { background: var(--surface); border-color: var(--muted); }
.home-seam .theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.theme-toggle .theme-icon { display: block; flex: none; }
.theme-toggle .theme-icon-moon, .theme-toggle .theme-name-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .theme-icon-moon, :root:not([data-theme="light"]) .theme-toggle .theme-name-dark { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .theme-icon-sun, :root:not([data-theme="light"]) .theme-toggle .theme-name-light { display: none; }
}
:root[data-theme="dark"] .theme-toggle .theme-icon-moon, :root[data-theme="dark"] .theme-toggle .theme-name-dark { display: block; }
:root[data-theme="dark"] .theme-toggle .theme-icon-sun, :root[data-theme="dark"] .theme-toggle .theme-name-light { display: none; }
/* On a phone the header row is the wordmark and three links; the word goes, the icon stays. */
@media (max-width: 520px) {
  .home-seam .theme-toggle { padding: 6px 10px; }
  .theme-toggle .theme-name { display: none !important; }
}

/* The promo's link-preview card (home-card.html), at the end of the reading: the still a
   share unfurls, opening the standalone promo. After the request-access form and before
   the closing section, in the landing's own tokens; only the frame is new. The scroll
   margin keeps the pinned header off it when /home#card is opened. */
.og-card { padding: clamp(56px, 8vw, 96px) 0; border-top: 1px solid var(--line); scroll-margin-top: 57px; }
.og-card-inner { width: min(100% - 48px, 720px); margin: 0 auto; }
.og-card .eyebrow { margin-bottom: 14px; }
.og-card-link { display: block; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--surface); box-shadow: var(--shadow-md); }
.og-card-img { display: block; width: 100%; height: auto; }
.og-card-caption { margin: 14px 2px 0; color: var(--muted); font-size: 14px; line-height: 1.5; }
.og-card-caption a { color: var(--ink); font-weight: 600; }

/* The promo's song button and Mute, following the visitor while its music plays under the
   reading (home.js shows the dock once the film is out of view): the promo's header pair in
   the landing's own tokens, at the foot of the viewport. */
.music-dock {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  animation: music-dock-in .35s ease both;
}
/* `display: flex` above outranks the browser's own `[hidden] { display: none }`, so the
   attribute home.js sets did nothing and the dock showed from page load, over the promo's bars. */
.music-dock[hidden] { display: none; }
/* The polite announcement of a track change, for screen readers only. */
.music-status { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.music-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 40px;
  padding: 8px 16px 8px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper-deep);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .01em;
  line-height: 1;
  box-shadow: var(--shadow-md);
  cursor: pointer;
}
.music-btn:hover { background: var(--surface); }
.music-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.music-note { color: var(--accent); font-size: 14px; }
.music-track { max-width: 18ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.music-count { color: var(--faint); font-family: var(--mono); font-size: 11px; font-weight: 500; }
.music-count:empty { display: none; }
.music-speaker { display: block; flex: none; }
/* The music's clock between the song button and Mute: the promo's ♪ clock (interactive.css
   .clock-music) in the landing's tokens, a reading rather than a control, so no pill. Empty
   until the promo has said a time. */
.music-clock { color: var(--ink); font-family: var(--mono); font-size: 12px; font-weight: 500; white-space: nowrap; }
.music-clock:empty { display: none; }
.music-clock::before { content: '♪ '; color: var(--accent); font-family: inherit; }
/* The volume icon follows its state (home.js: on, muted, quiet): both waves, the cross, or
   one wave. Icon only: the words moved into the popover under it. */
.music-btn-icon { padding: 8px 11px; gap: 0; }
.music-mute .music-on, .music-mute .music-off, .music-mute .music-half { display: none; }
.music-mute[data-state="on"] .music-on, .music-mute[data-state="muted"] .music-off, .music-mute[data-state="quiet"] .music-half { display: inline; }
.music-mute[data-state="muted"] { color: var(--muted); }
.music-mute[aria-expanded="true"] { background: var(--surface); border-color: var(--ink); }
/* The volume popover (home-film.html): a vertical slider standing over the icon, opened by a
   press on it and closed by another, Escape, a press outside or focus leaving it (home.js).
   Anchored to the icon's box so it rises from the pill's centre; the level reads out over the
   slider and Mute sits at its foot. The slider is a range input written vertically
   (writing-mode + rtl direction, so up is louder), with the promo's own slider look:
   the accent thumb over a hairline track. */
.music-volume { position: relative; display: grid; }
.music-volume-pop {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 10px);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 10px 8px 8px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper-deep);
  color: var(--ink);
  box-shadow: var(--shadow-md);
  animation: music-pop-in .16s ease both;
}
.music-volume-pop[hidden] { display: none; }
.music-volume-value { min-width: 4ch; color: var(--ink); font-family: var(--mono); font-size: 11px; font-weight: 500; text-align: center; white-space: nowrap; }
.music-volume-slider { display: flex; align-items: center; justify-content: center; width: 40px; height: 132px; }
.music-sr { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.music-volume-range {
  writing-mode: vertical-lr;
  direction: rtl;
  width: 24px;
  height: 100%;
  margin: 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.music-volume-range:focus-visible { outline: none; }
.music-volume-range::-webkit-slider-runnable-track { width: 2px; border-radius: 1px; background: var(--line); }
.music-volume-range::-moz-range-track { width: 2px; border-radius: 1px; background: var(--line); }
.music-volume-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-left: -6px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--paper-deep);
  transition: transform .12s ease;
}
.music-volume-range::-moz-range-thumb { width: 14px; height: 14px; border: 0; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--paper-deep); }
.music-volume-range:hover::-webkit-slider-thumb, .music-volume-range:focus-visible::-webkit-slider-thumb { transform: scale(1.2); }
.music-volume-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 2px var(--paper-deep), 0 0 0 4px var(--accent); }
.music-volume-range:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 2px var(--paper-deep), 0 0 0 4px var(--accent); }
.music-volume-mute {
  min-width: 68px;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.music-volume-mute:hover { background: var(--surface); }
.music-volume-mute:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.music-volume-mute[aria-pressed="true"] { color: var(--muted); }
@keyframes music-pop-in { from { opacity: 0; transform: translate(-50%, 6px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes music-dock-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .music-dock, .music-volume-pop { animation: none; } .music-volume-range::-webkit-slider-thumb { transition: none; } }
@media (max-width: 720px) {
  .music-dock { right: 12px; bottom: 12px; gap: 6px; }
  .music-btn { min-height: 38px; padding: 7px 13px 7px 11px; }
  .music-track { display: none; }
}
