/* Loopky landing page.
   Colours are the app's own tokens, from LoopkyColors.kt / LoopkyColor.swift. */

:root {
  /* Tells the browser which way the page leans, so native parts it paints itself,
     the select popup, the form controls, the page scrollbar, follow along. */
  color-scheme: light;

  --surface-primary: #FFFBF5;
  --surface-secondary: #FFF4EA;
  --surface-card: #FFFFFF;
  --accent: #FF5C00;
  --accent-soft: #FFE8D6;
  --accent-2: #7A4CFF;
  --accent-2-soft: #E9E0FF;
  --fg: #1B1B1F;
  --fg-2: #5A5A66;
  --fg-muted: #8B8B99;
  --on-accent: #FFFFFF;
  --navbar: #1A1326;
  --border: #F0E6D9;
  --good: #21C97A;
  --again: #FF4E64;
  --hard: #F5A524;
  --easy: #3B82F6;
  --shadow-low: 0 1px 2px rgba(26, 19, 38, .05);
  --shadow-mid: 0 4px 14px rgba(26, 19, 38, .07);
  --shadow-high: 0 14px 40px rgba(26, 19, 38, .10);
  --glow: 0 10px 30px rgba(255, 92, 0, .20);
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 26px;
  --r-pill: 999px;
  --maxw: 1140px;
}

/* Dark.
   The switch in the top bar writes data-theme onto <html>; nothing there means the
   visitor has not chosen and the system decides. So the palette is spelled twice: a
   media query for the system, an attribute for the choice. A media query and an
   attribute cannot share one selector, and the :not() keeps a visitor who picked
   light out of the system's dark.

   The two blocks must hold the same declarations. tools/check.mjs compares them. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --surface-primary: #0D0B11;
    --surface-secondary: #1E1A28;
    --surface-card: #2D2839;
    --accent: #FF6B2C;
    --accent-soft: #38221A;
    --accent-2: #9B7BFF;
    --accent-2-soft: #2B2443;
    --fg: #EDEBF1;
    --fg-2: #B5AEBD;
    --fg-muted: #9C94A8;
    --navbar: #262032;
    --border: #3B3550;
    --shadow-low: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow-mid: 0 4px 14px rgba(0, 0, 0, .45);
    --shadow-high: 0 14px 40px rgba(0, 0, 0, .55);
    --glow: 0 10px 30px rgba(255, 107, 44, .22);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --surface-primary: #0D0B11;
  --surface-secondary: #1E1A28;
  --surface-card: #2D2839;
  --accent: #FF6B2C;
  --accent-soft: #38221A;
  --accent-2: #9B7BFF;
  --accent-2-soft: #2B2443;
  --fg: #EDEBF1;
  --fg-2: #B5AEBD;
  --fg-muted: #9C94A8;
  --navbar: #262032;
  --border: #3B3550;
  --shadow-low: 0 1px 2px rgba(0, 0, 0, .35);
  --shadow-mid: 0 4px 14px rgba(0, 0, 0, .45);
  --shadow-high: 0 14px 40px rgba(0, 0, 0, .55);
  --glow: 0 10px 30px rgba(255, 107, 44, .22);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--surface-primary);
  color: var(--fg);
  font: 400 17px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial,
        "Noto Sans", "Noto Sans JP", "Noto Sans KR", "Noto Sans SC", "Noto Sans TC", sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { line-height: 1.15; letter-spacing: -.02em; margin: 0 0 .5em; }
h1 { font-size: clamp(2.2rem, 5.5vw, 3.6rem); font-weight: 800; }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.4rem); font-weight: 800; }
h3 { font-size: 1.12rem; font-weight: 700; }
p { margin: 0 0 1em; }
a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; height: auto; display: block; }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 22px; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #fff; padding: 12px 18px; border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }

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

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  background: var(--accent); color: var(--on-accent);
  border: 0; border-radius: var(--r-pill);
  padding: 13px 24px; font: inherit; font-weight: 700; font-size: .98rem;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); box-shadow: var(--glow); }
.btn:active { transform: translateY(0); }
.btn-lg { padding: 16px 30px; font-size: 1.05rem; }
.btn-sm { padding: 9px 17px; font-size: .88rem; }
.btn-ghost {
  background: transparent; color: var(--accent-2);
  border: 1.5px solid var(--border);
}
.btn-ghost:hover { background: var(--accent-2-soft); box-shadow: none; }
.btn-invert { background: #fff; color: #FF5C00; }
.btn-invert:hover { box-shadow: 0 10px 30px rgba(0, 0, 0, .18); }

/* ---------- top bar ---------- */
.topbar {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--surface-primary) 88%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--border);
}
.topbar-in { display: flex; align-items: center; gap: 18px; height: 66px; }
.brand {
  display: flex; align-items: center; gap: 10px;
  color: var(--fg); font-weight: 800; font-size: 1.16rem; letter-spacing: -.02em;
}
.brand:hover { text-decoration: none; }
.brand img { border-radius: 9px; }
.topnav { display: flex; gap: 24px; margin-left: auto; }
.topnav a { color: var(--fg-2); font-weight: 600; font-size: .95rem; }
.topnav a:hover { color: var(--accent); text-decoration: none; }
.topright { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.topnav + .topright { margin-left: 0; }
.lang select {
  appearance: none;
  background: var(--surface-card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='%238B8B99' d='M2 4.5 6 8.5l4-4z'/%3E%3C/svg%3E") no-repeat right 10px center/11px;
  border: 1.5px solid var(--border); color: var(--fg);
  border-radius: var(--r-pill); padding: 8px 30px 8px 14px;
  font: inherit; font-size: .88rem; font-weight: 600; cursor: pointer;
}

/* One button, three states, cycling system to light to dark. It carries the same
   pill as the language picker beside it, because an icon on its own read as
   decoration and people walked past it. The label says which state is on; the icon
   agrees with it. The sun and the moon each stand for a choice the visitor made, so
   neither is drawn while the system is still deciding. */
.themebtn {
  display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto;
  background: var(--surface-card); color: var(--fg);
  border: 1.5px solid var(--border); border-radius: var(--r-pill);
  padding: 7px 15px 7px 12px;
  font: inherit; font-size: .88rem; font-weight: 600;
  cursor: pointer;
  transition: color .12s ease, border-color .12s ease;
}
.themebtn:hover { color: var(--accent); border-color: var(--accent); }
.themebtn svg { display: none; flex: 0 0 auto; }
.themebtn[data-state="system"] .ico-system,
.themebtn[data-state="light"] .ico-light,
.themebtn[data-state="dark"] .ico-dark { display: block; }
/* The three words are different lengths, and without a floor the whole right side
   of the bar nudges sideways on every click. */
.themebtn-label { min-width: 3.4em; text-align: left; }

@media (max-width: 860px) {
  .topnav { display: none; }
}
@media (max-width: 420px) {
  .lang select { padding: 8px 26px 8px 10px; max-width: 110px; }
  .topright .btn { display: none; }
  /* Three pills and a logo do not fit a phone. The icon alone was never the problem
     at this width: with the nav links gone it sits right next to the brand. */
  .themebtn { padding: 8px; }
  .themebtn-label { display: none; }
}

/* ---------- hero ---------- */
.hero {
  position: relative; overflow: hidden;
  padding: clamp(48px, 7vw, 88px) 0 clamp(40px, 6vw, 72px);
  background:
    radial-gradient(900px 480px at 78% -10%, var(--accent-soft), transparent 62%),
    radial-gradient(700px 420px at 4% 8%, var(--accent-2-soft), transparent 58%),
    var(--surface-primary);
}
.hero-in {
  display: grid; grid-template-columns: 1.05fr .95fr; gap: 42px; align-items: center;
}
.eyebrow {
  text-transform: uppercase; letter-spacing: .12em; font-size: .76rem; font-weight: 800;
  color: var(--accent); margin-bottom: 14px;
}
.lead { font-size: clamp(1.02rem, 1.6vw, 1.18rem); color: var(--fg-2); max-width: 54ch; }
.cta-row { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin: 26px 0 12px; }
.cta-row.center { justify-content: center; }
.soon {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--fg-2); font-size: .92rem; font-weight: 600;
}
.soon::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent-2);
}
.soon-invert { color: rgba(255, 255, 255, .88); }
.soon-invert::before { background: rgba(255, 255, 255, .8); }
.fineprint { font-size: .88rem; color: var(--fg-muted); margin: 0; }

.hero-art { position: relative; min-height: 440px; display: flex; justify-content: center; }
.phone {
  width: min(258px, 44vw); border-radius: 26px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-high);
  background: var(--surface-card);
}
.phone-front { position: relative; z-index: 2; transform: rotate(-3deg); }
.phone-back {
  position: absolute; left: 50%; top: 24px; z-index: 1;
  transform: translateX(-18%) rotate(7deg); opacity: .96;
}

@media (max-width: 900px) {
  .hero-in { grid-template-columns: 1fr; }
  .hero-art { min-height: 0; margin-top: 8px; }
  .phone-back { display: none; }
  .phone-front { transform: none; }
  .phone { width: min(290px, 64vw); }
}

/* ---------- sections ---------- */
.section { padding: clamp(52px, 7vw, 88px) 0; }
.section-alt { background: var(--surface-secondary); }
.sec-head { max-width: 62ch; margin-bottom: 26px; }

.card {
  background: var(--surface-card);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-low);
}

.grid-feat {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
}
.feat { padding: 26px 24px 20px; transition: transform .15s ease, box-shadow .15s ease; }
.feat:hover { transform: translateY(-3px); box-shadow: var(--shadow-mid); }
.feat p { color: var(--fg-2); font-size: .97rem; margin: 0; }
.ico {
  display: grid; place-items: center; width: 46px; height: 46px;
  border-radius: 14px; font-size: 22px; margin-bottom: 15px;
}
.ico-orange { background: var(--accent-soft); }
.ico-purple { background: var(--accent-2-soft); }
.ico-blue   { background: color-mix(in srgb, var(--easy) 16%, transparent); }
.ico-green  { background: color-mix(in srgb, var(--good) 16%, transparent); }
.ico-pink   { background: color-mix(in srgb, var(--again) 14%, transparent); }
.ico-amber  { background: color-mix(in srgb, var(--hard) 18%, transparent); }

.uses { margin-top: 42px; }
.uses h3 { color: var(--fg-2); font-size: 1rem; font-weight: 700; margin-bottom: 14px; }
.pillrow { list-style: none; display: flex; flex-wrap: wrap; gap: 9px; padding: 0; margin: 0; }
.pillrow li {
  background: var(--surface-card); border: 1px solid var(--border);
  color: var(--fg-2); border-radius: var(--r-pill);
  padding: 7px 15px; font-size: .88rem; font-weight: 600;
}

/* ---------- discover ---------- */
.disc-controls { display: grid; gap: 16px; margin-bottom: 22px; }
/* Grid items default to min-width: auto, which lets a wide child push the page
   wider instead of shrinking. This is what the chip row fell into. */
.disc-controls > * { min-width: 0; }
.searchbox {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface-card); border: 1.5px solid var(--border);
  border-radius: var(--r-pill); padding: 0 18px;
  max-width: 460px; color: var(--fg-muted);
}
.searchbox:focus-within { border-color: var(--accent-2); }
.searchbox input {
  flex: 1; border: 0; background: transparent; color: var(--fg);
  font: inherit; font-size: .98rem; padding: 13px 0; min-width: 0;
}
.searchbox input:focus { outline: none; }
.searchbox input::-webkit-search-cancel-button { filter: grayscale(1) opacity(.5); }

/* Chips wrap. They used to be a horizontal rail, which is what the app draws, but
   a rail has to be a scroll container and this one sat in a grid: a grid item's
   min-width is auto, so the row sized itself to all fifteen chips, stretched to
   1679px at every viewport, and took the whole page's width with it. Wrapping has
   no overflow to contain and no scrollbar to hide, and every topic is visible at
   once rather than behind a swipe. */
.chips {
  display: flex; flex-wrap: wrap; gap: 9px;
  min-width: 0;
  padding: 2px 0;
}

.chip {
  flex: 0 0 auto; border: 0; cursor: pointer; font: inherit;
  background: var(--accent-2-soft); color: var(--accent-2);
  border-radius: var(--r-sm); padding: 10px 17px;
  font-size: .93rem; font-weight: 700; white-space: nowrap;
  transition: background .12s ease, color .12s ease;
}
.chip:hover { background: color-mix(in srgb, var(--accent-2) 22%, transparent); }
.chip[aria-pressed="true"] { background: var(--accent-2); color: #fff; }
.chip-clear { background: transparent; color: var(--fg-muted); text-decoration: underline; }
.chip-clear:hover { background: transparent; color: var(--fg); }

.disc-status { color: var(--fg-muted); font-size: .94rem; margin: 0 0 16px; }
.disc-status[hidden] { display: none; }

.deckgrid {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
}
.deck {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface-card); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-low);
  color: inherit; text-decoration: none;
  transition: transform .15s ease, box-shadow .15s ease;
}
.deck:hover { text-decoration: none; transform: translateY(-3px); box-shadow: var(--shadow-mid); }
.deck-cover {
  aspect-ratio: 16 / 11; width: 100%; object-fit: cover;
  background: var(--surface-secondary); display: block;
}
.deck-cover-emoji {
  aspect-ratio: 16 / 11; display: grid; place-items: center; font-size: 46px;
  background: linear-gradient(140deg, var(--tint-a, var(--accent-soft)), var(--tint-b, var(--accent-2-soft)));
}

/* A deck published without a web cover has no picture anywhere a browser can
   reach, so the emoji is the cover. Six tints off the app's palette, picked from
   the deck's own address, so a grid of them reads as a design and not as a row of
   images that failed. */
.tint-0 { --tint-a: var(--accent-soft); --tint-b: var(--accent-2-soft); }
.tint-1 { --tint-a: var(--accent-2-soft); --tint-b: color-mix(in srgb, var(--easy) 18%, transparent); }
.tint-2 { --tint-a: color-mix(in srgb, var(--good) 20%, transparent); --tint-b: var(--accent-soft); }
.tint-3 { --tint-a: color-mix(in srgb, var(--hard) 22%, transparent); --tint-b: var(--accent-2-soft); }
.tint-4 { --tint-a: color-mix(in srgb, var(--again) 16%, transparent); --tint-b: color-mix(in srgb, var(--hard) 18%, transparent); }
.tint-5 { --tint-a: color-mix(in srgb, var(--easy) 18%, transparent); --tint-b: color-mix(in srgb, var(--good) 18%, transparent); }

/* Holds the card's shape while the picture is on its way, instead of a white gap. */
.deck-cover { background: var(--surface-secondary); }
.deck-body { padding: 15px 16px 17px; display: flex; flex-direction: column; gap: 7px; flex: 1; }
.deck-title {
  font-weight: 700; font-size: 1rem; line-height: 1.3; margin: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.deck-meta { font-size: .85rem; color: var(--fg-muted); margin: 0; }
.deck-meta b { color: var(--accent-2); font-weight: 700; }
/* Straight under the subtitle, not pushed to the floor of the card. Tags belong to
   the deck, and a title that wraps to two lines should move them down with it rather
   than leave a gap. */
.deck-tags { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 2px; }
.deck-tag {
  background: var(--accent-2-soft); color: var(--accent-2);
  border-radius: var(--r-pill); padding: 3px 9px; font-size: .74rem; font-weight: 700;
}

.skel { pointer-events: none; }
.skel .deck-cover-emoji, .skel .bar {
  background: var(--surface-secondary);
  animation: pulse 1.4s ease-in-out infinite;
}
.skel .bar { height: 12px; border-radius: 6px; }
.skel .bar.w70 { width: 70%; }
.skel .bar.w45 { width: 45%; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }
@media (prefers-reduced-motion: reduce) { .skel * { animation: none; } }

.disc-foot { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; margin-top: 28px; }

/* Two columns on a phone, the same grid the app draws at compact width. */
@media (max-width: 640px) {
  .deckgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .deck-body { padding: 12px 12px 14px; gap: 5px; }
  .deck-title { font-size: .92rem; }
  .deck-meta { font-size: .78rem; }
  .deck-cover-emoji { font-size: 36px; }
  .deck-tag { font-size: .68rem; padding: 2px 7px; }
  .disc-foot .btn { flex: 1 1 100%; }
}

/* ---------- cli ---------- */
.cli-in { display: grid; grid-template-columns: 1fr 1.1fr; gap: 40px; align-items: start; }
.cli-copy h2 { margin-bottom: .4em; }
.ticks { list-style: none; padding: 0; margin: 20px 0; display: grid; gap: 11px; }
.ticks li { position: relative; padding-left: 30px; color: var(--fg-2); font-size: .97rem; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: .42em;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--good) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' d='m4 8.4 2.6 2.6L12 5.4'/%3E%3C/svg%3E") center/13px no-repeat;
}
.cli-box {
  background: var(--navbar); border-radius: var(--r-md);
  box-shadow: var(--shadow-high); overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .08);
}
.cli-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px 12px 18px;
  background: rgba(255, 255, 255, .05);
  color: rgba(255, 255, 255, .72);
  font-size: .82rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
}
.cli-box pre {
  margin: 0; padding: 18px; max-height: 420px; overflow: auto;
  color: #EDEBF1;
  font: 400 13px/1.62 ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  white-space: pre-wrap; word-break: break-word;
}
@media (max-width: 900px) { .cli-in { grid-template-columns: 1fr; } }

/* ---------- steps ---------- */
.steps {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  counter-reset: s;
}
.steps li { padding-top: 6px; }
.steps p { color: var(--fg-2); font-size: .97rem; margin: 0; }
.num {
  display: grid; place-items: center; width: 40px; height: 40px; margin-bottom: 14px;
  border-radius: 50%; background: var(--accent); color: #fff; font-weight: 800; font-size: 1.05rem;
}

/* ---------- cta band ---------- */
.cta-band {
  background: linear-gradient(135deg, #FF5C00, #FF8A3D 55%, #7A4CFF);
  color: #fff; text-align: center;
}
.cta-in h2 { color: #fff; margin-bottom: .3em; }
.cta-in > p { color: rgba(255, 255, 255, .9); font-size: 1.08rem; }

/* ---------- footer ---------- */
.footer { background: var(--navbar); color: rgba(255, 255, 255, .7); padding: 34px 0; }
.footer-in { display: flex; align-items: center; gap: 18px 28px; flex-wrap: wrap; }
.foot-brand {
  display: flex; align-items: center; gap: 9px; margin: 0;
  color: #fff; font-weight: 800; letter-spacing: -.02em;
}
.foot-brand img { border-radius: 6px; }
.footlinks { display: flex; gap: 20px; flex-wrap: wrap; margin-left: auto; }
.footlinks a { color: rgba(255, 255, 255, .72); font-size: .9rem; }
.footlinks a:hover { color: #fff; }
.foot-note { width: 100%; margin: 0; font-size: .82rem; color: rgba(255, 255, 255, .45); }

/* ---------- the prompt box's scrollbar ---------- */

/* The one bar worth keeping: a code block you scroll through wants to say how far
   down it goes. It is dark in both themes, so it cannot follow the page tokens.
   Standard properties first, because Chrome ignores the -webkit- pseudo-elements
   entirely once it sees `scrollbar-width` — which is what made an earlier attempt
   at styling the chip rail do nothing at all. The pseudo-elements are left for the
   engines that have only those. */
.cli-box pre {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .24) transparent;
}
@supports not (scrollbar-width: thin) {
  .cli-box pre::-webkit-scrollbar { width: 9px; height: 9px; }
  .cli-box pre::-webkit-scrollbar-track { background: transparent; }
  .cli-box pre::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .24);
    border-radius: var(--r-pill);
    /* A transparent border clipped to the padding box reads as an inset thumb. */
    border: 2px solid transparent;
    background-clip: padding-box;
  }
  .cli-box pre:hover::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .4); }
}
