/* The look of the apps: Kode Mono and the orange of the logos, light or dark with the system. */

@font-face {
  font-family: "Kode Mono";
  src: url("../fonts/KodeMono.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}

:root {
  --accent: #de5833;
  /* The orange is 3.3:1 on the light page: fine for headings and buttons, too light for small text
     links, so links and small accented text use this darker shade. */
  --accent-text: #b13f1c;
  --bg: #f6f4f1;
  --surface: #ffffff;
  --border: #e3ded7;
  --text: #211d1a;
  --muted: #6b635c;
  --code-bg: #f1ece6;
  --shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 4px 16px rgba(0, 0, 0, .05);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --accent-text: #f0845f;
    --bg: #181614;
    --surface: #221f1c;
    --border: #36312c;
    --text: #efebe6;
    --muted: #a79f97;
    --code-bg: #2b2723;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 16px rgba(0, 0, 0, .25);
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Kode Mono", ui-monospace, "Cascadia Mono", "DejaVu Sans Mono", monospace;
  font-size: 1rem;
  line-height: 1.6;
}

a { color: var(--accent-text); text-underline-offset: .15em; }
a:hover { text-decoration-thickness: 2px; }

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

/* Sideways only: the header, main and footer set their own vertical padding. */
.wrap { max-width: 64rem; margin: 0 auto; padding-inline: 1rem; }

/* ---------- Header ---------- */

.site-header { border-bottom: 1px solid var(--border); background: var(--surface); }

.site-header .wrap {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem 1.25rem;
  padding-top: .75rem;
  padding-bottom: .75rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: .6rem;
  color: var(--text);
  font-weight: 700;
  text-decoration: none;
  margin-right: auto;
}

.brand img { width: 2rem; height: 2rem; }

/* ---------- Logo glint ----------
   The same shine as the animated profile pictures (Assets/c-logo/C-logo-glint-*.gif): a light band
   crosses the logo diagonally, from top-left to bottom-right. It sits on a layer masked to the logo's
   own shape, so only the logo lights up, never the page behind it. Every logo glints at the GIF's
   pace and rhythm: the band moves about one logo-diagonal per second, once every 3.84 s. The logos start at different times,
   so they don't all flash at once. Nothing moves for people who ask for reduced motion. */
.glint { position: relative; display: inline-flex; line-height: 0; }
.glint::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* A band perpendicular to the diagonal, in the middle of a 2x2 image; 13.5% of that image is about
     a quarter of the logo, like the GIF's band. Moving the image from 100% to 0% carries the band
     once across the logo, from its top-left corner to its bottom-right one. The first version used a
     3x3 image, so the band travelled twice as far and looked far faster than the GIF. */
  background: linear-gradient(135deg,
    transparent 43.25%, rgb(255 255 255 / .35) 47.4%, rgb(255 255 255 / .85) 50%,
    rgb(255 255 255 / .35) 52.6%, transparent 56.75%) 100% 100% / 200% 200% no-repeat;
  -webkit-mask: center / contain no-repeat;
  mask: center / contain no-repeat;
}
/* Set per logo and not through a custom property: browsers disagree on whether a url() inside a
   custom property resolves against the stylesheet or the page, and a mask that fails to load hides
   the layer completely. */
.glint-c::after { -webkit-mask-image: url("../img/c-logo.svg"); mask-image: url("../img/c-logo.svg"); }
.glint-gt::after { -webkit-mask-image: url("../img/grocerytracker.svg"); mask-image: url("../img/grocerytracker.svg"); }
.glint-lh::after { -webkit-mask-image: url("../img/launchheim.svg"); mask-image: url("../img/launchheim.svg"); }

/* The GIF's loop is 3.84 s (a 3.04 s first frame, then 20 frames of 40 ms), and its band covers 0.84
   logo-diagonals in 0.8 s: 1.04 per second. This band travels a full diagonal (it also crosses the
   empty corners), so it needs 0.96 s for the same pace: the last 25% of the 3.84 s. */
@keyframes glint-loop {
  0%, 75% { background-position: 100% 100%; }
  100% { background-position: 0% 0%; }
}

@media (prefers-reduced-motion: no-preference) {
  /* Linear like the GIF, whose frames move the band by the same step every 40 ms. */
  .glint::after { animation: glint-loop 3.84s linear infinite; }
  .glint-gt::after { animation-delay: 1.25s; }
  .glint-lh::after { animation-delay: 2.5s; }
}

.site-header nav { display: flex; flex-wrap: wrap; gap: .25rem 1rem; }
.site-header nav a { color: var(--text); text-decoration: none; }
.site-header nav a:hover, .site-header nav a[aria-current="page"] { color: var(--accent-text); text-decoration: underline; }

/* ---------- Content ---------- */

main { padding: 2.5rem 0 3rem; }

h1, h2, h3 { line-height: 1.2; }
h1 { font-size: clamp(1.7rem, 5vw, 2.6rem); margin: 0 0 .75rem; }
h2 { font-size: clamp(1.35rem, 3.6vw, 1.8rem); margin: 0 0 .5rem; }
h3 { font-size: 1.1rem; margin: 1.75rem 0 .5rem; }

.lead { font-size: 1.1rem; color: var(--muted); max-width: 44rem; margin: 0 0 2rem; }

.apps { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 1.5rem;
}

.app-card { display: flex; flex-direction: column; }
.app-card header { display: flex; align-items: center; gap: 1rem; margin-bottom: .75rem; }
.app-card header img { width: 3.5rem; height: 3.5rem; }
.app-card header .glint { flex: none; }
.app-card header h2 { margin: 0; }
.app-card header p { margin: 0; color: var(--muted); font-size: .9rem; }
.app-card ul { padding-left: 1.2rem; margin: .5rem 0 1.25rem; }
.app-card li { margin: .3rem 0; }
.app-card .actions { margin-top: auto; }

.actions { display: flex; flex-wrap: wrap; gap: .6rem; }

.button {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .6rem 1.05rem;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 700;
  text-decoration: none;
  line-height: 1.3;
}

.button:hover { border-color: var(--accent); text-decoration: none; }
/* White on the orange is 3.8:1, which is fine for these bold labels. */
.button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.button.primary:hover { filter: brightness(1.08); }
.button small { font-weight: 400; opacity: .85; }

/* Screenshots (the Microsoft Store listing's): a row that scrolls sideways and snaps to each picture,
   so a phone shows one at a time and a wide screen about two. Each opens full size. */
.shots { margin-top: 1.25rem; }
.shots h2 { display: flex; align-items: center; gap: .6rem; }
.shots h2 img { width: 2rem; height: 2rem; }
.shot-strip {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
  scrollbar-color: var(--muted) transparent;
  list-style: none;
  margin: 1rem 0 0;
  padding: 0 0 .75rem;
}
.shot-strip li { flex: 0 0 min(88%, 30rem); scroll-snap-align: start; }
.shot-strip figure { margin: 0; }
.shot-strip a { display: block; line-height: 0; border-radius: 10px; }
.shot-strip img { width: 100%; height: auto; border: 1px solid var(--border); border-radius: 10px; }
.shot-strip figcaption { margin-top: .5rem; color: var(--muted); font-size: .9rem; }

.support {
  margin-top: 2.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.support p { margin: 0; max-width: 40rem; }

/* ---------- Download page ---------- */

.toc { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 2rem; }

/* One app at a time. The app is picked by the address: download.html#launchheim, or an anchor inside
   its section such as #launchheim-changes, which is what the front page and the buttons here link
   to. Picked, its section shows in full, the other one is hidden and the bar on top switches between
   them. Nothing picked, both show only their header and a button that picks them. Without :has()
   (browsers before 2023) all of this is skipped and both sections show in full, as before. */
.app-open { display: none; }
@supports selector(:has(*)) {
  main:not(:has(.app-section:target, .app-section :target)) .toc,
  main:not(:has(.app-section:target, .app-section :target)) .app-more { display: none; }
  main:not(:has(.app-section:target, .app-section :target)) .app-open { display: inline-flex; }
  main:has(.app-section:target, .app-section :target) .app-section:not(:target):not(:has(:target)) { display: none; }
  main:has(#grocerytracker:target, #grocerytracker :target) .toc [href="#grocerytracker"],
  main:has(#launchheim:target, #launchheim :target) .toc [href="#launchheim"] {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
    background: var(--code-bg);
  }
}

/* Room above a picked app for the bar that switches between them (see "One app at a time" above). */
.app-section { margin-bottom: 2.5rem; scroll-margin-top: 5rem; }
.app-section > header { display: flex; align-items: center; gap: 1rem; margin-bottom: .5rem; }
.app-section > header img { width: 3rem; height: 3rem; }
.app-section > header .glint { flex: none; }
.app-section > header h2 { margin: 0; }
.version { color: var(--muted); font-size: .9rem; margin: 0; }

.downloads { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); margin: 1rem 0; }
.downloads .button { justify-content: space-between; }
/* The version history from each CHANGELOG.md: one <details> per release, newest open. */
.changelog details { border-left: 3px solid var(--border); padding: .1rem 0 .1rem .9rem; margin: .6rem 0; }
.changelog details[open] { border-left-color: var(--accent); }
.changelog summary .version { display: inline; margin-left: .4rem; }
.changelog h4 { margin: .6rem 0 .2rem; font-size: .95rem; }
.changelog ul { margin: 0 0 .4rem; padding-left: 1.2rem; }
.changelog .tag { margin-left: .4rem; font-size: .75rem; padding: .05rem .45rem; border-radius: 999px; border: 1px solid var(--accent); color: var(--accent); }

/* Download picker: one tab per way to get an app, and only the picked one's download and instructions
   show. Each tab is the <label> of a radio button; the radios stay focusable and keep the keyboard
   behaviour of a radio group, they're just not drawn. They come first in .get, so "~" reaches the tabs
   and panels after them. Every way of getting it needs its line in each of the three lists below. */
.get { margin: 1rem 0; }
.get > input { position: absolute; opacity: 0; pointer-events: none; }
.get-tabs { display: grid; gap: .6rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); }
/* Two in a row on a phone rather than one: six tabs stacked push the instructions off the screen. */
@media (max-width: 30rem) { .get-tabs { grid-template-columns: 1fr 1fr; } }
.get-tabs label {
  display: flex;
  flex-direction: column;
  padding: .55rem .9rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-weight: 700;
  line-height: 1.3;
  cursor: pointer;
}
.get-tabs label:hover { border-color: var(--accent); }
.get-tabs small { font-weight: 400; color: var(--muted); }
.get-panel {
  display: none;
  margin-top: .75rem;
  padding: 1rem 1.1rem .25rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
}
.get-panel > .button:first-child { margin-bottom: .25rem; }
.get-panel > pre:first-child { margin-top: 0; }
.get-panel p:first-child { margin-top: 0; }

#lh-get-store:checked ~ .get-store,
#lh-get-setup:checked ~ .get-setup,
#lh-get-arch:checked ~ .get-arch,
#lh-get-deb:checked ~ .get-deb,
#lh-get-rpm:checked ~ .get-rpm,
#lh-get-android:checked ~ .get-android { display: block; }

#lh-get-store:checked ~ .get-tabs [for="lh-get-store"],
#lh-get-setup:checked ~ .get-tabs [for="lh-get-setup"],
#lh-get-arch:checked ~ .get-tabs [for="lh-get-arch"],
#lh-get-deb:checked ~ .get-tabs [for="lh-get-deb"],
#lh-get-rpm:checked ~ .get-tabs [for="lh-get-rpm"],
#lh-get-android:checked ~ .get-tabs [for="lh-get-android"] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  background: var(--code-bg);
}

/* The radio has the focus but isn't drawn, so its tab shows the ring. */
#lh-get-store:focus-visible ~ .get-tabs [for="lh-get-store"],
#lh-get-setup:focus-visible ~ .get-tabs [for="lh-get-setup"],
#lh-get-arch:focus-visible ~ .get-tabs [for="lh-get-arch"],
#lh-get-deb:focus-visible ~ .get-tabs [for="lh-get-deb"],
#lh-get-rpm:focus-visible ~ .get-tabs [for="lh-get-rpm"],
#lh-get-android:focus-visible ~ .get-tabs [for="lh-get-android"] {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* License notes under the downloads: required to be there, not meant to compete with them. */
.fine-print { color: var(--muted); font-size: .85rem; margin: 0 0 1rem; }

ol.steps { padding-left: 1.4rem; }
ol.steps > li { margin: .6rem 0; }

pre, code { font-family: inherit; }
code { background: var(--code-bg); border-radius: 5px; padding: .08em .35em; font-size: .92em; overflow-wrap: anywhere; }

pre {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: .8rem 1rem;
  /* Long commands scroll instead of wrapping, so copy and paste stays exact. */
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--muted) transparent;
  line-height: 1.5;
  font-size: .88rem;
  margin: .5rem 0 1rem;
}

pre code { background: none; padding: 0; font-size: inherit; overflow-wrap: normal; }

.note {
  border-left: 4px solid var(--accent);
  background: var(--code-bg);
  border-radius: 0 10px 10px 0;
  padding: .75rem 1rem;
  margin: 1rem 0;
}

.note p { margin: .25rem 0; }

details { margin: .5rem 0; }
summary { cursor: pointer; font-weight: 700; }

/* ---------- Footer ---------- */

.site-footer { border-top: 1px solid var(--border); color: var(--muted); font-size: .85rem; }
.site-footer .wrap { padding-top: 1.25rem; padding-bottom: 1.5rem; display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; }
.site-footer p { margin: 0; }

/* Long-form text (the privacy policy): a readable line length and room between sections. */
.policy { max-width: 48rem; }
.policy h2 { font-size: 1.2rem; margin: 1.75rem 0 .5rem; }
.policy ul { padding-left: 1.2rem; }
.policy li { margin: .35rem 0; }
