/* CrocApp landing page. Loaded after tokens.css, which supplies every value
   here. No raw hex, px or ms below the reset block: a missing value is a
   missing token — add it to design/*.md and design/tokens.css first (ADR 0015).

   Page fill is --color-surface-base, not the app's grouped fill, because
   --color-text-link is 4.94:1 on base and only 4.42:1 on grouped and this page
   runs links through its prose. Cards carry the tonal step instead. */

/* 1. Reset + a11y utilities.
   The one block allowed literals: 0, 100%, and .u-visually-hidden's 1px clip. */

h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

/* ---- Icons ----
   iconography.md's render rules live here, not on each element: a <use>
   instance cannot inherit them from the symbol. The size default matters —
   an <svg> with a viewBox and no dimensions falls back to 300x150. */
svg {
  width: var(--icon-size-md);
  height: var(--icon-size-md);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Sprite itself renders nothing. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/* Author styles beat the UA sheet, so any class setting `display` defeats the
   hidden attribute — the JS-gated copy button would render visible and inert. */
[hidden] {
  display: none !important;
}

/* Screen-reader-only: still focusable, still announced, zero visual box. */
.u-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 2. Page + layout */

body {
  background: var(--color-surface-base);
}

.container {
  width: 100%;
  max-width: var(--content-max-width-web);
  margin-inline: auto;
  padding-inline: var(--gutter-web);
}

.container--wide {
  max-width: var(--content-max-width-wide);
}

/* Caps the *content*, not the container: max-width on the container itself
   re-centres it and gives the page a third left edge. */
.container--prose > * {
  max-width: var(--content-max-width-prose);
}

.section {
  padding-block: var(--section-pad-web);
}

/* Successive sections would otherwise stack two full pads against one
   hairline. The rule reads as one section boundary, not two. */
.section + .section {
  padding-block-start: 0;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--stack-web);
}

.stack--tight {
  gap: var(--space-5);
}

/* min() keeps the floor from overflowing a 375px viewport, where
   --grid-min-card alone would exceed the available column. */
.grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min-card), 100%), 1fr));
}

.section__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: var(--content-max-width-prose);
  margin-block-end: var(--stack-web);
}

.section__head p {
  color: var(--color-text-secondary);
}

/* WCAG 1.4.1: a link inside a paragraph cannot be colour alone. tokens.css
   strips underlines globally — right for nav and buttons, wrong for prose. A
   link that is a whole heading or control is not "within a block of text". */
.prose a,
.card__body a,
.disclosure__body a,
.footer__text a,
.section__head a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* 3. Skip link — first in tab order, invisible until focused */

.skip-link {
  position: fixed;
  z-index: 3;
  inset-block-start: var(--space-3);
  inset-inline-start: var(--space-3);
  padding: var(--space-3) var(--space-5);
  color: var(--color-on-accent);
  background: var(--color-accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  transform: translateY(-200%);
  transition: transform var(--dur-fast) var(--ease-out);
}

/* Ring restated: .skip-link's own box-shadow would beat tokens.css's
   :focus-visible on source order at equal specificity. */
.skip-link:focus-visible {
  transform: translateY(0);
  box-shadow: var(--shadow-md), var(--shadow-focus-ring);
}

/* 4. Sticky glass nav.
   Glass needs something to blur; over a flat page it reads as a tinted bar,
   which is the expected look here. Fallback below for no backdrop-filter. */

.nav {
  position: sticky;
  z-index: 2;
  inset-block-start: 0;
  background: var(--color-surface-card);
  border-block-end: var(--border-hairline) solid var(--color-separator);
}

@supports (backdrop-filter: none) or (-webkit-backdrop-filter: none) {
  .nav {
    background: var(--color-surface-glass);
    backdrop-filter: blur(var(--blur-regular)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--blur-regular)) saturate(var(--glass-saturate));
    border-block-end-color: var(--color-glass-border);
  }
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: var(--nav-height-web);
}

.nav__brand {
  margin-inline-end: auto;
  font-weight: var(--weight-bold);
  color: var(--color-text-primary);
  text-decoration: none;
  white-space: nowrap;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.nav__link {
  color: var(--color-text-secondary);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-standard);
}

.nav__link:hover,
.nav__link[aria-current="true"] {
  color: var(--color-text-primary);
  text-decoration: none;
}

/* Four links do not fit beside a wordmark, toggle and star count on a phone.
   Hidden rather than collapsed: everything is still reachable by scrolling,
   and a hamburger for four in-page anchors is more JS and more a11y surface
   than the problem deserves. The breakpoint is a literal by necessity —
   custom properties do not resolve inside a media condition. */
@media (width < 48rem) {
  .nav__links {
    display: none;
  }
}

/* 5. Buttons — components.md measurements */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap-lg);
  height: var(--control-height-lg);
  padding-inline: var(--btn-pad-x-lg);
  font-size: var(--type-headline-size);
  font-weight: var(--weight-semibold);
  line-height: 1;
  letter-spacing: var(--tracking-headline);
  text-decoration: none;
  white-space: nowrap;
  border-radius: var(--radius-capsule);
  transition:
    background-color var(--dur-fast) var(--ease-standard),
    transform var(--dur-fast) var(--ease-out);
}

.btn:hover {
  text-decoration: none;
}

.btn:active {
  opacity: 1;
  transform: scale(var(--press-scale));
}

.btn__icon {
  flex: none;
  width: var(--btn-icon-lg);
  height: var(--btn-icon-lg);
}

.btn--md {
  gap: var(--btn-gap-md);
  height: var(--control-height-md);
  padding-inline: var(--btn-pad-x-md);
  font-size: var(--type-callout-size);
}

.btn--md .btn__icon {
  width: var(--btn-icon-md);
  height: var(--btn-icon-md);
}

.btn--sm {
  gap: var(--btn-gap-sm);
  height: var(--control-height-sm);
  padding-inline: var(--btn-pad-x-sm);
  font-size: var(--type-footnote-size);
}

.btn--sm .btn__icon {
  width: var(--btn-icon-sm);
  height: var(--btn-icon-sm);
}

.btn--prominent {
  color: var(--color-on-accent);
  background: var(--color-accent);
  box-shadow: var(--shadow-sm);
}

.btn--prominent:hover {
  color: var(--color-on-accent);
  background: var(--color-accent-pressed);
}

.btn--secondary {
  /* On its own tint --green-700 is 4.31:1, so this needs the darker step. */
  color: var(--color-accent-text-on-tint);
  background: var(--color-accent-tint);
}

.btn--secondary:hover {
  color: var(--color-accent-text-on-tint);
}

.btn--glass {
  color: var(--color-accent-text);
  background: var(--color-surface-glass);
  border: var(--border-hairline) solid var(--color-glass-border);
  box-shadow: var(--shadow-sm);
  backdrop-filter: blur(var(--blur-regular)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--blur-regular)) saturate(var(--glass-saturate));
}

.btn--glass:hover {
  color: var(--color-accent-text);
  background: var(--color-surface-glass-thick);
}

.btn--plain {
  color: var(--color-accent-text);
  background: transparent;
}

.btn--plain:hover {
  color: var(--color-accent-text);
  background: var(--color-fill-tertiary);
}

/* Focus swaps the variant shadow for the ring rather than stacking both. */
.btn:focus-visible {
  box-shadow: var(--shadow-focus-ring);
}

.btn[aria-disabled="true"] {
  pointer-events: none;
  opacity: 0.4;
}

/* Square icon-only control: the hit target, not the glyph, is what has to
   clear --hit-target-min. */
.icon-btn {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--hit-target-min);
  height: var(--hit-target-min);
  color: var(--color-text-secondary);
  border-radius: var(--radius-capsule);
  transition:
    color var(--dur-fast) var(--ease-standard),
    background-color var(--dur-fast) var(--ease-standard);
}

.icon-btn:hover {
  color: var(--color-text-primary);
  background: var(--color-fill-tertiary);
}

.icon-btn svg {
  width: var(--icon-size-md);
  height: var(--icon-size-md);
}

/* 6. Cards */

.card {
  padding: var(--space-6);
  background: var(--color-surface-card);
  border: var(--border-hairline) solid var(--color-separator);
  border-radius: var(--radius-lg);
}

.card--elevated {
  border-color: transparent;
  box-shadow: var(--shadow-md);
}

/* The one card that reads as "this is the answer", per components.md.
   Decoration is not a reason to use it. */
.card--tinted {
  background: var(--color-accent-tint);
  border-color: transparent;
}

.card__title {
  margin-block-end: var(--space-3);
}

.card__body {
  color: var(--color-text-secondary);
}

.card__icon {
  width: var(--icon-size-lg);
  height: var(--icon-size-lg);
  margin-block-end: var(--space-4);
  color: var(--color-accent);
}

/* 7. Pills — TrustBadge pill geometry */

.pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--pill-pad-block);
  padding-inline: var(--pill-pad-inline-start) var(--pill-pad-inline-end);
  font-size: var(--type-footnote-size);
  font-weight: var(--weight-semibold);
  line-height: var(--type-footnote-lh);
  /* Primary: secondary on --color-fill-tertiary is 3.24:1, a fail at 13px. */
  color: var(--color-text-primary);
  white-space: nowrap;
  background: var(--color-fill-tertiary);
  border-radius: var(--radius-capsule);
}

/* The E2E badge. Success-on-success-tint is 1.98:1, so the tint carries the
   signal and the label stays primary — colors.md rule 2. */
.pill--trust {
  background: var(--color-status-success-tint);
}

.pill__icon {
  flex: none;
  width: var(--pill-icon-size);
  height: var(--pill-icon-size);
}

/* 8. Disclosure — <details>, works with JS off */

.disclosure {
  padding: var(--space-5) var(--space-6);
  background: var(--color-surface-card);
  border: var(--border-hairline) solid var(--color-separator);
  border-radius: var(--radius-md);
}

.disclosure + .disclosure {
  margin-block-start: var(--space-3);
}

.disclosure__summary {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  font-size: var(--type-headline-size);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-headline);
  cursor: pointer;
  list-style: none;
}

.disclosure__summary::-webkit-details-marker {
  display: none;
}

.disclosure__summary:focus-visible {
  border-radius: var(--radius-xs);
  box-shadow: var(--shadow-focus-ring);
}

.disclosure__chevron {
  flex: none;
  width: var(--icon-size-sm);
  height: var(--icon-size-sm);
  margin-inline-start: auto;
  /* Secondary: tertiary is 1.74:1 on white, not a visible affordance. */
  color: var(--color-text-secondary);
  transition: transform var(--dur-base) var(--ease-out);
}

.disclosure[open] .disclosure__chevron {
  transform: rotate(90deg);
}

.disclosure__body {
  margin-block-start: var(--space-4);
  color: var(--color-text-secondary);
}

.disclosure__body > * + * {
  margin-block-start: var(--space-3);
}

/* 9. Nav extras — GitHub link, theme toggle */

.nav__github {
  flex: none;
}

.nav__stars {
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}

/* The glyph shows the theme you would switch *to*, so light shows a moon.
   This is a display swap, not a colour, so light-dark() cannot carry it and
   the prefers-color-scheme mirror below is still required. */
.theme-toggle__sun {
  display: none;
}

[data-theme="dark"] .theme-toggle__moon {
  display: none;
}

[data-theme="dark"] .theme-toggle__sun {
  display: block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle__moon {
    display: none;
  }

  :root:not([data-theme="light"]) .theme-toggle__sun {
    display: block;
  }
}

/* The star glyph and count still say "GitHub", and the row has to fit a
   wordmark, a link and a toggle inside --nav-height-web. */
@media (width < 30rem) {
  .nav__github {
    padding-inline: var(--space-2);
    font-size: 0;
  }

  .nav__stars {
    font-size: var(--type-footnote-size);
  }
}

/* 10. Hero */

.hero__inner {
  display: grid;
  gap: var(--stack-web);
  align-items: center;
}

/* Two columns only when the mockup can hold its 480 cap beside a readable
   measure of copy. Below that they stack, copy first. */
@media (width >= 64rem) {
  .hero__inner {
    grid-template-columns: 1fr auto;
    gap: var(--space-11);
  }
}

.hero__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  max-width: var(--content-max-width-prose);
}

.hero__deck {
  color: var(--color-text-secondary);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.hero__pills {
  margin-block-start: var(--space-2);
}

/* 11. CSS app mockup — measurements from components.md.
   The app's Send screen drawn from the same tokens, so a token change moves
   both. Solid material is deliberate: glass over a flat page is a rectangle. */

.hero__mockup {
  display: flex;
  justify-content: center;
  margin: 0;
}

.mockup {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  width: 100%;
  max-width: var(--content-max-width);
  padding: var(--space-6);
  background: var(--color-surface-card);
  border: var(--border-hairline) solid var(--color-separator);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
}

.mockup__bar {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  justify-content: space-between;
}

.mockup__title {
  font-size: var(--type-headline-size);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-headline);
}

.mockup__badge {
  flex: none;
}

/* --- FileRow --- */

.mockup__rows {
  border-radius: var(--radius-md);
  background: var(--color-surface-grouped);
  overflow: hidden;
}

.filerow {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  min-height: var(--row-min-file);
  padding: var(--space-3) var(--space-4);
}

/* Half-pixel inset shadow rather than a border, so the row corners stay
   clean inside the rounded group. Last row omits it. */
.filerow:not(:last-child) {
  box-shadow: inset 0 calc(var(--border-hairline-half) * -1) 0 var(--color-separator);
}

.filerow__icon {
  flex: none;
  width: var(--btn-icon-lg);
  height: var(--btn-icon-lg);
  color: var(--color-accent);
}

/* Name and extension are one visual string, so they get their own flex box:
   the row's gap must not open a space in the middle of a filename. */
.filerow__label {
  display: flex;
  min-width: 0;
}

/* Middle truncation: the head ellipsises while the extension stays pinned,
   so a long filename never hides what kind of file it is. */
.filerow__name {
  overflow: hidden;
  font-size: var(--type-callout-size);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.filerow__tail {
  flex: none;
  font-size: var(--type-callout-size);
}

.filerow__size {
  flex: none;
  margin-inline-start: auto;
  font-size: var(--type-footnote-size);
  color: var(--color-text-secondary);
  font-variant-numeric: tabular-nums;
}

/* --- CodePhraseDisplay --- */

.mockup__code {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  align-items: center;
  text-align: center;
}

.mockup__eyebrow {
  font-size: var(--type-footnote-size);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  color: var(--color-text-secondary);
  text-transform: uppercase;
}

.mockup__phrase {
  font-family: var(--font-mono);
  font-size: var(--type-code-hero-size);
  line-height: var(--type-code-hero-lh);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-code);
  /* The phrase is the one string that must never be clipped: it wraps at the
     hyphens rather than shrinking or overflowing on a narrow phone. */
  overflow-wrap: anywhere;
}

.mockup__copy {
  pointer-events: none;
}

/* --- TransferProgress --- */

.mockup__progress {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.mockup__progress-head {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* Direction is never colour alone: the arrow and the word both change, and
   neither is optional. components.md → TransferProgress. */
.mockup__arrow {
  flex: none;
  width: var(--btn-icon-md);
  height: var(--btn-icon-md);
  color: var(--color-accent);
}

.mockup__direction {
  font-size: var(--type-headline-size);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-headline);
}

.mockup__speed {
  margin-inline-start: auto;
  font-size: var(--type-caption1-size);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}

.progressbar {
  height: var(--progress-height);
  background: var(--color-fill-tertiary);
  border-radius: var(--radius-capsule);
  overflow: hidden;
}

.progressbar__fill {
  display: block;
  width: 62%;
  height: 100%;
  background: var(--color-accent);
  border-radius: var(--radius-capsule);
}

.mockup__caption {
  display: flex;
  justify-content: space-between;
  font-size: var(--type-caption1-size);
  color: var(--color-text-secondary);
  font-variant-numeric: tabular-nums;
}

/* 12. Content sections.
   iconography.md: glyphs under 20px carry a heavier stroke so they hold
   weight against the text beside them. */

.pill__icon,
.btn--sm .btn__icon,
.featlist svg {
  stroke-width: 2.2;
}

.mockup__arrow,
.disclosure__chevron {
  stroke-width: 2.4;
}

/* --- Steps --- */

.steps {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min-card), 100%), 1fr));
}

.step {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
}

/* The number is decoration for a sighted reader; the ordered list already
   carries the sequence for everyone else, which is why it is aria-hidden. */
.step__num {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--space-8);
  height: var(--space-8);
  font-size: var(--type-footnote-size);
  font-weight: var(--weight-semibold);
  color: var(--color-accent-text-on-tint);
  background: var(--color-accent-tint);
  border-radius: var(--radius-capsule);
  font-variant-numeric: tabular-nums;
}

.step__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.step__body p {
  color: var(--color-text-secondary);
}

.how__more {
  margin-block-start: var(--stack-web);
  max-width: var(--content-max-width-prose);
}

/* --- Feature groups --- */

.featgroup {
  display: flex;
  flex-direction: column;
}

.featlist {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  color: var(--color-text-secondary);
}

.featlist li {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}

.featlist svg {
  flex: none;
  width: var(--btn-icon-sm);
  height: var(--btn-icon-sm);
  /* Optical alignment: a 15px glyph centred on a 21px line sits high
     otherwise. Half the difference between line box and glyph. */
  margin-block-start: var(--space-1);
  color: var(--color-accent);
}

/* --- Download --- */

.dlcard {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.dlcard .card__title {
  margin-block-end: 0;
}

.dlcard code {
  font-size: var(--type-footnote-size);
  overflow-wrap: anywhere;
}

/* Deliberately not dimmed. A pending channel still has to be readable —
   opacity here would fail contrast to say something a label already says. */
.dlcard__state {
  align-self: flex-start;
  margin-block-start: auto;
}

.download__req {
  margin-block-start: var(--stack-web);
  color: var(--color-text-secondary);
  text-align: center;
}

/* --- Prose blocks --- */

.prose > * + * {
  margin-block-start: var(--space-5);
}

.prose p {
  color: var(--color-text-secondary);
}

/* --- croc attribution --- */

.croc .card__body,
.support .card__body {
  color: var(--color-text-primary);
}

/* --- Inspirations --- */

.inspo {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min-card), 100%), 1fr));
}

/* --- Contribute / Support --- */

.contribute__actions,
.support__actions {
  margin-block-start: var(--stack-web);
}

.support__actions {
  margin-block-start: var(--space-6);
}

/* 13. Footer */

.footer {
  padding-block: var(--section-pad-web);
  border-block-start: var(--border-hairline) solid var(--color-separator);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  align-items: center;
}

.footer__mascot {
  flex: none;
  width: var(--space-11);
  height: auto;
}

.footer__text {
  flex: 1 1 var(--content-max-width-prose);
  color: var(--color-text-secondary);
}

.footer__text p + p {
  margin-block-start: var(--space-3);
}

.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin-inline-start: auto;
}

/* 14. Reduced motion.
   tokens.css already zeroes the duration tokens; this is the backstop for
   anything not token-driven. */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    /* --dur-fast is already 0ms inside this query, so this stays token-driven
       rather than hardcoding the usual 0.01ms. */
    transition-duration: var(--dur-fast) !important;
    animation-duration: var(--dur-fast) !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
