/* ==================================================================
   CAMERA SHUTTER COUNT — Production site styles
   Rand · Rams · Ive · Carmack · Jobs · Bass · Cooper
   ------------------------------------------------------------------
   Tokens. 8px grid. Major-third type scale. Three border weights.
   Motion ≤ 500ms. Self-hosted fonts (with system fallback).
   ================================================================== */

/* -- Self-hosted fonts (paths point to app/assets/fonts in production) -- */
@font-face {
  font-family: Satoshi;
  font-style: normal;
  font-weight: 300;
  src: url("/assets/satoshi-300-6cb0ed23.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: Satoshi;
  font-style: normal;
  font-weight: 400;
  src: url("/assets/satoshi-400-203be3c2.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: Satoshi;
  font-style: normal;
  font-weight: 500;
  src: url("/assets/satoshi-500-9b05096e.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: Satoshi;
  font-style: normal;
  font-weight: 700;
  src: url("/assets/satoshi-700-33f48a21.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: Satoshi;
  font-style: normal;
  font-weight: 900;
  src: url("/assets/satoshi-900-3352500b.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  src: url("/assets/jetbrains-mono-400-ed40b09e.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  src: url("/assets/jetbrains-mono-500-1bc99771.woff2") format("woff2");
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 700;
  src: url("/assets/jetbrains-mono-700-1a8f0f6c.woff2") format("woff2");
  font-display: swap;
}

/* ==================================================================
   TOKENS
   ================================================================== */
:root {
  /* — Palette ————————————————————— */
  --yellow: #ffd600;
  --yellow-2: #f0c800;
  --ink-0: #0b0b0b;
  --ink: #111;
  --ink-2: #1a1a1a;
  --ink-3: #232323;
  --surface-dark: #0e0e0e; /* full-bleed dark band (e.g. /buy Limited, home privacy) */
  --paper: #f2ede2;
  --paper-2: #e6e0d2;
  --orange: #e07c1a;
  --red: #e0413a;
  --red-strong: #c0352e; /* deeper danger red: 4.77:1 with --paper text (--red is 3.6:1) */
  --green: #2cb67d;

  /* — Semantic status accents ————————————
     Fixed across every theme on purpose: a "fix" tag or an "important"
     chip must keep its meaning whatever the active theme is, so these do
     NOT follow --accent. Brand accents must use --accent / --accent-pop;
     these two exist so the few genuinely-fixed category chips don't reach
     for raw --yellow / --orange (which the lint guard forbids). */
  --caution: var(--yellow);
  --emphasis: var(--orange);

  /* — 8px spacing scale ————————————— */
  --s-1: 4px; /* optical nudge only */
  --s-2: 8px;
  --s-3: 16px;
  --s-4: 24px;
  --s-5: 32px;
  --s-6: 40px;
  --s-7: 48px;
  --s-8: 56px;
  --s-9: 64px;
  --s-10: 80px;
  --s-11: 96px;
  --s-12: 128px;
  --s-13: 160px;

  /* — Type scale (Major Third, 1.25, root 16px) ——— */
  --t-50: 0.625rem; /* 10  small mono */
  --t-75: 0.75rem; /* 12  mono */
  --t-100: 0.875rem; /* 14  mono lg / small body */
  --t-200: 1rem; /* 16  body */
  --t-300: 1.25rem; /* 20 */
  --t-400: 1.5625rem; /* 25 */
  --t-500: 1.953rem; /* 31 */
  --t-600: 2.441rem; /* 39 */
  --t-700: 3.052rem; /* 49 */
  --t-800: 3.815rem; /* 61 */
  --t-900: 4.768rem; /* 76 */
  --t-1000: 5.96rem; /* 95 */
  --t-1100: 7.451rem; /* 119 */
  --t-1200: 9.313rem; /* 149 */

  /* — Border weights (three tiers, no 2px) —————— */
  --bw-1: 1px; /* hairline */
  --bw-2: 1.5px; /* instrument-panel */
  --bw-3: 3px; /* heavy rule */

  /* — Motion timings ——————————————— */
  --t100: 100ms;
  --t150: 150ms;
  --t200: 200ms;
  --t300: 300ms;
  --t400: 400ms;
  --t500: 500ms;
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);

  /* — Fonts ————————————————————— */
  --font-display: "Satoshi", "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* — Page chrome ——————————————— */
  --pad: clamp(24px, 4vw, 64px);
  --gutter: var(--s-4);
  --container-max: 1440px;

  /* — Walkthrough "desk" surface ————————————————
     The surface the app-window screenshots rest on. The CSC window is
     itself yellow, so on the yellow page it has no edge. A near-black
     ink desk (not a foreign blue) gives every theme's window a quiet,
     on-palette screen to sit on, and the bright app reads like a jewel
     on dark — the same dark that carries the privacy band + result
     card. A faint warm lift keeps it from going flat. */
  --desk-1: #26262a;
  --desk-2: #18181b;
  --desk-3: #0d0d0f;

  /* — Theme: CSC (default — yellow brand) ———————— */
  --bg: var(--yellow);
  --fg: var(--ink);
  --fg-mute: rgb(17, 17, 17, 0.62);
  --fg-mute-2: rgb(17, 17, 17, 0.36);
  --line: rgb(17, 17, 17, 0.18);
  --line-strong: rgb(17, 17, 17, 0.42);
  --accent: var(--orange);
  /* Bright "pop" for accents sitting on the dark bands (privacy promise,
     what's-new). The CSC brand IS yellow, so its bands keep popping
     yellow; every other theme pops its own accent. */
  --accent-pop: var(--yellow);
  --card-bg: var(--ink-2);
  --card-fg: var(--paper);
}

html[data-theme="analog"] {
  --bg: var(--paper);
  --fg: var(--ink);
  --fg-mute: rgb(17, 17, 17, 0.62);
  --fg-mute-2: rgb(17, 17, 17, 0.36);
  --line: rgb(17, 17, 17, 0.18);
  --line-strong: rgb(17, 17, 17, 0.42);
  --accent: var(--orange);
  --accent-pop: var(--accent);
}
html[data-theme="darkroom"] {
  --bg: #0e0e0e;
  --fg: var(--paper);
  --fg-mute: rgb(242, 237, 226, 0.6);
  --fg-mute-2: rgb(242, 237, 226, 0.36);
  --line: rgb(242, 237, 226, 0.16);
  --line-strong: rgb(242, 237, 226, 0.4);
  --accent: var(--red);
  --accent-pop: var(--accent);
  --card-bg: #1e1414;
}

/* ==================================================================
   RESET
   ================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html,
body {
  padding: 0;
  margin: 0;
}
.page-main {
  flex: 1 0 auto;
}
/* Visually hidden, still in the a11y tree (for screen-reader-only text such
   as an aria-describedby hint). The 1px box is the canonical sr-only
   technique; tokens/property-order don't apply to it. */
/* stylelint-disable scale-unlimited/declaration-strict-value, order/properties-order */
.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
  border: 0;
}
/* stylelint-enable scale-unlimited/declaration-strict-value, order/properties-order */

/* Skip-to-content link: first focusable on every page, off-screen until a
   keyboard user tabs to it, then it slides in over the nav. */
.skip-link {
  position: fixed;
  inset-inline-start: var(--s-2);
  top: var(--s-2);
  z-index: 1000;
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--bg);
  background: var(--fg);
  border-radius: 4px;
  transform: translateY(calc(-100% - var(--s-4)));
  transition: transform var(--t150) var(--ease);
}
.skip-link:focus {
  outline: var(--bw-2) solid var(--accent);
  outline-offset: 2px;
  transform: translateY(0);
}

/* Country-simulation badge: shown only while the secret-gated country override
   is active, so a previewed country's currency/VAT is never mistaken for ours. */
.sim-flag {
  position: fixed;
  inset-inline-start: var(--s-3);
  bottom: var(--s-3);
  z-index: 1000;
  padding: var(--s-1) var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-50);
  font-weight: 700;
  color: var(--paper);
  letter-spacing: 0.12em;
  pointer-events: none;
  background: var(--red-strong);
  border-radius: 4px;
}
/* Sticky footer: body is a full-height flex column so the footer always
   rests at the bottom, even on short pages. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  overflow-x: hidden;
  font-family: var(--font-display);
  font-feature-settings: "ss01", "ss02", "tnum";
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  background: var(--bg);
  transition:
    background-color var(--t300) var(--ease),
    color var(--t300) var(--ease);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img,
svg {
  display: block;
  max-width: 100%;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: none;
  border: 0;
}
hr {
  margin: 0;
  border: 0;
  border-top: var(--bw-1) solid var(--line);
}
::selection {
  color: var(--bg);
  background: var(--fg);
}

/* ==================================================================
   TYPE PRIMITIVES
   ================================================================== */
.mono {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.mono.sm {
  font-size: var(--t-50);
}
.mono.lg {
  font-size: var(--t-100);
}
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 600;
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}
.h-1 {
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.035em;
}
.h-2 {
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.025em;
}
.body {
  font-weight: 400;
  line-height: 1.5;
}
.lede {
  font-weight: 500;
  line-height: 1.42;
}

.accent {
  color: var(--accent);
}

/* ==================================================================
   LAYOUT
   ================================================================== */
.section {
  position: relative;
  padding: var(--s-12) var(--pad);
}
.section.tight {
  padding-top: var(--s-10);
  padding-bottom: var(--s-10);
}
.container {
  max-width: var(--container-max);
  margin: 0 auto;
}

/* ==================================================================
   NAV
   ================================================================== */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: var(--s-3) var(--pad);
  background: var(--bg);
  border-bottom: var(--bw-1) solid var(--line);
  transition: background-color var(--t300) var(--ease);
}
.nav__brand {
  display: flex;
  gap: var(--s-2);
  align-items: center;
}
.nav__mark {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  color: var(--fg);
}
.nav__name {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.nav__links {
  display: flex;
  gap: var(--s-4);
  justify-content: center;
}
.nav__links > a {
  position: relative;
  padding: var(--s-1) 0;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 500;
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  transition: color var(--t150) var(--ease);
}
.nav__links > a:hover,
.nav__links > a[aria-current="page"] {
  color: var(--fg);
}
.nav__links > a[aria-current="page"]::after {
  position: absolute;
  right: 0;
  bottom: -4px;
  left: 0;
  height: var(--bw-2);
  content: "";
  background: var(--fg);
}
.nav__right {
  display: flex;
  justify-content: flex-end;
}

/* Mobile menu trigger — hidden on desktop, shown ≤880px. The bread stroke
   morph (line → ✕) lives in the SVG <animate> pair; this is just the box. */
.nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--s-7);
  height: var(--s-7);
  padding: 0;
  margin-inline-end: calc(var(--s-2) * -1);
  color: var(--fg);
  cursor: pointer;
  background: none;
  border: 0;
}
.nav__toggle svg {
  display: block;
}
.nav__bread {
  stroke-width: var(--bw-2);
}
.nav__menu-cta {
  display: none;
}

@media (max-width: 880px) {
  .nav {
    grid-template-columns: 1fr auto;
  }
  .nav__brand {
    position: relative;
    z-index: 51;
  }
  .nav__toggle {
    position: relative;
    z-index: 51;
    display: inline-flex;
  }
  .nav__right {
    display: none;
  }

  /* Full-bleed overlay menu — Apple's curtain in CSC ink-on-yellow */
  .nav__links {
    position: fixed;
    inset: 0;
    z-index: 40;
    display: flex;
    visibility: hidden;
    flex-direction: column;
    gap: var(--s-2);
    align-items: flex-start;
    justify-content: flex-start;
    padding: var(--s-11) var(--pad) var(--s-9);
    margin: 0;
    overflow-y: auto;
    background: var(--bg);
    opacity: 0;
    transform: translateY(-6px);
    transition:
      opacity var(--t300) var(--ease),
      transform var(--t300) var(--ease),
      visibility 0s linear var(--t300);
  }
  .nav--open .nav__links {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition:
      opacity var(--t300) var(--ease),
      transform var(--t300) var(--ease);
  }
  .nav__links > a {
    padding: var(--s-2) 0;
    font-size: var(--t-500);
    color: var(--fg);
    letter-spacing: 0.02em;
  }
  .nav__links > a[aria-current="page"] {
    color: var(--accent);
  }
  .nav__links > a[aria-current="page"]::after {
    display: none;
  }
  .nav__menu-cta {
    display: block;
    margin-top: var(--s-4);
  }
  .nav__menu-cta .btn {
    font-size: var(--t-100);
  }

  /* Saul Bass stagger — rows rise in just behind the curtain */
  .nav--open .nav__links > * {
    animation: nav-rise var(--t400) var(--ease) both;
  }
  .nav--open .nav__links > *:nth-child(1) {
    animation-delay: 80ms;
  }
  .nav--open .nav__links > *:nth-child(2) {
    animation-delay: 116ms;
  }
  .nav--open .nav__links > *:nth-child(3) {
    animation-delay: 152ms;
  }
  .nav--open .nav__links > *:nth-child(4) {
    animation-delay: 188ms;
  }
  .nav--open .nav__links > *:nth-child(5) {
    animation-delay: 224ms;
  }
  .nav--open .nav__links > *:nth-child(6) {
    animation-delay: 260ms;
  }
}

@keyframes nav-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

html.nav-locked,
html.nav-locked body {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .nav__links,
  .nav--open .nav__links,
  .nav--open .nav__links > * {
    transition-duration: 1ms;
    animation: none;
  }
}

/* ==================================================================
   BUTTONS (4 variants — primary never flips bg)
   ================================================================== */
.btn {
  display: inline-flex;
  gap: var(--s-2);
  align-items: center;
  min-height: 40px;
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 600;
  color: var(--bg);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  white-space: nowrap;
  background: var(--fg);
  border: var(--bw-2) solid var(--fg);
  border-radius: 2px;
  transition: transform var(--t150) var(--ease);
}
.btn:hover {
  transform: translateY(-1px);
}
.btn:active {
  transform: translateY(0);
}
.btn[disabled],
.btn.is-disabled {
  pointer-events: none;
  opacity: 0.5;
}
.btn--secondary {
  color: var(--fg);
  background: transparent;
  border-color: var(--fg);
}
.btn--secondary:hover {
  color: var(--accent);
  border-color: var(--accent);
}
.btn--danger {
  color: var(--paper);
  background: var(--red-strong);
  border-color: var(--red-strong);
}
.btn--utility {
  padding: var(--s-1) 0;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  background: transparent;
  border: 0;
}
.btn--utility:hover {
  color: var(--fg);
  transform: none;
}

.btn--lg {
  min-height: 56px;
  padding: var(--s-3) var(--s-4);
}

.btn .arr {
  display: inline-flex;
  align-items: center;
  transition: transform var(--t150) var(--ease);
}

/* Phosphor inline SVG defaults — match the surrounding text colour
   (fill: currentColor is set on the SVG itself), sit on the baseline,
   and stay rigid against external transforms. The .arr wrapper above
   gives us a flex container that aligns the icon optically with caps
   text without depending on intrinsic SVG baseline maths. */
.ph-icon {
  display: inline-block;
  flex-shrink: 0;
  vertical-align: -0.125em;
}
.arr .ph-icon {
  vertical-align: 0;
}
.btn:hover .arr {
  transform: translateX(3px);
}

/* ==================================================================
   HERO
   ================================================================== */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 56px);
  padding: var(--s-10) var(--pad) 0;
}
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  align-items: center;
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-8);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  border-bottom: var(--bw-1) solid var(--line);
}
.hero__meta .dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-inline-end: var(--s-1);
  vertical-align: 2px;
  background: var(--accent);
  border-radius: 50%;
}
.hero__meta .right {
  margin-inline-start: auto;
}

/* ==================================================================
   SHOWCASE (black band)
   ================================================================== */
.showcase {
  color: var(--paper);
  background: var(--ink-2);
}

/* Light intro variant — for secondary pages (download, preview).
   Specificity raised to .intro.intro--light to win against later .intro rules. */
.intro.intro--light {
  color: var(--fg);
  background: var(--bg);
}
.intro.intro--light .intro__eyebrow {
  color: var(--accent);
}
.intro.intro--light .intro__wordmark,
.intro.intro--light .intro__wordmark--stacked {
  color: var(--fg);
}
.intro.intro--light .intro__sentence {
  color: var(--fg-mute);
}
/* Hero pricing line on the light hero (the /cameras pages). The base
   .intro__price colour is tuned for the dark hero, so it needs the same
   light-mode override as .intro__sentence or it renders near-invisible.
   It also sits tighter to the lede here (--s-3, not the base --s-5): the
   cameras hero stacks more elements, so the default breath felt loose. */
.intro.intro--light .intro__price {
  margin-top: var(--s-3);
  color: var(--fg-mute);
}
.intro.intro--light .intro__sentence em {
  font-style: normal;
  font-weight: 600;
  color: var(--fg);
}
.intro.intro--light .intro__sub {
  color: var(--fg-mute);
}
.intro.intro--light .intro__actions-label {
  color: var(--fg-mute);
}

.intro.intro--light .intro__actions .btn {
  color: var(--bg);
  background: var(--fg);
  border-color: var(--fg);
}
.intro.intro--light .intro__actions .btn:hover {
  color: var(--fg);
  background: var(--accent);
  border-color: var(--accent);
}
.intro.intro--light .intro__actions .btn--secondary {
  color: var(--fg);
  background: transparent;
  border-color: var(--fg);
}
.intro.intro--light .intro__actions .btn--secondary:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.intro.intro--light .preview-form__label {
  color: var(--fg-mute);
}
.intro.intro--light .preview-form input[type="email"] {
  color: var(--fg);
  border-bottom-color: var(--line-strong);
}
.intro.intro--light .preview-form input[type="email"]::placeholder {
  color: var(--fg-mute);
}
.intro.intro--light .preview-form input[type="email"]:focus {
  border-bottom-color: var(--accent);
}
.intro.intro--light .preview-form button {
  color: var(--bg);
  background: var(--fg);
  border-color: var(--fg);
}
.intro.intro--light .preview-form button:hover {
  color: var(--fg);
  background: var(--accent);
  border-color: var(--accent);
}

/* ==================================================================
   PRICE BLOCK — black band to alternate against the yellow.
   ================================================================== */
.price-block {
  color: var(--paper);
  background: var(--ink-2);
}
/* § 07 reduced to one oversized CTA. Price lives on the buy page. */
.price-cta {
  display: inline-flex;
  gap: clamp(16px, 3vw, 40px);
  align-items: center;
  font-family: var(--font-display);
  font-size: clamp(48px, 10vw, 144px);
  font-weight: 900;
  line-height: 0.9;
  color: var(--paper);
  letter-spacing: -0.04em;
  transition: color var(--t150) var(--ease);
}
.price-cta:hover {
  color: var(--accent);
}
.price-cta__arr {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--accent);
}
.price-block .btn {
  color: var(--ink);
  background: var(--accent-pop);
  border-color: var(--accent-pop);
}
.price-block .btn:hover {
  color: var(--ink);
  background: var(--paper);
  border-color: var(--paper);
}
.price-block .btn--secondary {
  color: var(--paper);
  background: transparent;
  border-color: rgb(242, 237, 226, 0.4);
}
.price-block .btn--secondary:hover {
  color: var(--accent-pop);
  border-color: var(--accent-pop);
}
/* Ticket sits on the dark band — the cutouts need to match the band, not the page. */
.price-block .ticket::before,
.price-block .ticket::after {
  background: var(--ink-2);
}

/* ==================================================================
   MAJOR SECTIONS — one app screen per section.
   Title big, screenshot bigger. The cut is yellow on yellow.
   ================================================================== */
.major {
  position: relative;
  padding: var(--s-13) var(--pad) var(--s-12);
}
/* Sections separate by space, not rules (the generous --s-13/--s-12
   padding does the work). The only structural rule on the page is the
   one deliberate heavy cut from the dark hero into the first section. */
.intro + .major {
  border-top: var(--bw-3) solid var(--fg);
}

.major__rule {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--s-4);
  align-items: baseline;
  padding-top: var(--s-3);
  margin-bottom: var(--s-7);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  border-top: var(--bw-1) solid var(--line);
}
.major__rule .num {
  color: var(--fg);
}

.major__head {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: clamp(32px, 6vw, 96px);
  align-items: end;
  margin-bottom: var(--s-9);
}
.major__head--centered {
  grid-template-columns: 1fr;
  max-width: 1100px;
  text-align: start;
}
.major__head--centered .major__desc {
  justify-self: start;
  max-width: 56ch;
  margin-top: var(--s-3);
}
.major__head--reverse {
  direction: rtl;
}
.major__head--reverse > * {
  direction: ltr;
}

.major__title {
  margin: 0;
  /* Sub-hero scale — deliberately below the main hero wordmark
     (max 144px) so section titles read as secondary, on /download
     and the homepage feature sections alike. */
  font-size: clamp(40px, 7vw, 96px);
  font-weight: 900;
  line-height: 0.9;
  letter-spacing: -0.045em;
  text-wrap: balance;
}
.major__title .accent {
  color: var(--accent);
}
.major__desc {
  justify-self: end;
  max-width: 40ch;
  margin: 0;
  font-size: clamp(17px, 1.5vw, 22px);
  line-height: 1.42;
  color: var(--fg-mute);
}
.major__desc em {
  font-style: normal;
  font-weight: 500;
  color: var(--fg);
}

.major__shots {
  position: relative;
}
.major__shots--pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter);
}

.major__shot {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--ink-2);
  border-radius: 12px;
  box-shadow:
    0 32px 80px -32px rgb(0, 0, 0, 0.45),
    0 0 0 1px rgb(17, 17, 17, 0.06);
}
.major__shot img {
  display: block;
  width: 100%;
  height: auto;
}
.major__shot > figcaption {
  position: absolute;
  inset-inline-start: var(--s-2);
  bottom: var(--s-2);
  display: inline-flex;
  gap: var(--s-2);
  align-items: center;
  padding: var(--s-1) var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--paper);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  background: rgb(0, 0, 0, 0.62);
  border: var(--bw-1) solid rgb(255, 255, 255, 0.08);
  border-radius: 2px;
  backdrop-filter: blur(6px);
}

/* ==================================================================
   § 01 WALKTHROUGH — guided tour: Check → Result → Compare → Saved.
   Alternating copy/media rows. Media is either a self-framed app
   window (the transparent Check PNG) or a themed "stage" holding the
   live result-card port until the real app PNGs are generated.
   ================================================================== */
/* The section eyebrow: just the accent kicker, no rule line and no
   "§ NN" number. A label, set in space, rather than a boxed-in header. */
.major__rule--eyebrow {
  grid-template-columns: 1fr;
  padding-top: 0;
  margin-bottom: var(--s-5);
  color: var(--accent);
  border-top: 0;
}
.walk__head {
  display: grid;
  gap: var(--s-4);
  max-width: 72ch;
  margin-bottom: var(--s-11);
}
.walk__lead {
  max-width: 62ch;
  margin: 0;
  font-size: clamp(17px, 1.6vw, 22px);
  line-height: 1.5;
  color: var(--fg-mute);
}
.walk__lead em {
  font-style: normal;
  font-weight: 500;
  color: var(--fg);
}
.walk__link {
  color: var(--accent);
  text-decoration: none;
  border-bottom: var(--bw-2) solid var(--accent);
  transition: opacity var(--t150) var(--ease);
}
.walk__link:hover {
  opacity: 0.7;
}

.walk {
  display: grid;
  gap: var(--s-13);
  padding: 0;
  margin: 0;
  list-style: none;
}
/* §02 sub-beats (per camera, date filter) sit beneath the big
   scrollable dashboard, so they're tighter and pushed down from it. */
.walk--compact {
  gap: var(--s-11);
  margin-top: var(--s-12);
}
/* Support's closing line — an open invitation for ideas. */
.sup-ideas {
  max-width: 56ch;
  margin: var(--s-11) auto 0;
  font-size: clamp(var(--t-300), 2.4vw, var(--t-500));
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.sup-ideas em {
  font-style: normal;
  color: var(--accent);
}

/* "Also in here" — a designed feature index at the foot of a section,
   naming what doesn't get its own screenshot. Set as a numbered
   contents list (accent mono index + display-type name) on a full-bleed
   dark band: it stands apart from the section's yellow body and gives a
   deliberate break between sections. The band is flush to the section
   foot (negative bottom margin cancels .major's --s-12 bottom padding),
   so it butts straight against the next section. Assumes .more is the
   last child of its .major. */
.more {
  display: grid;
  gap: var(--s-6);
  width: 100vw;
  padding: clamp(48px, 6vw, 88px) var(--pad);
  margin-inline: calc(50% - 50vw);
  margin-top: var(--s-13);
  margin-bottom: calc(-1 * var(--s-12));
  background: var(--surface-dark);
}
.more__label {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.2em;
}
.more__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: var(--s-3) var(--s-8);
  padding: 0;
  margin: 0;
  list-style: none;
}
.more__list li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-3);
  align-items: baseline;
  padding-block: var(--s-2);
  font-size: clamp(var(--t-200), 1.5vw, var(--t-300));
  font-weight: 600;
  line-height: 1.2;
  color: var(--paper);
  letter-spacing: -0.02em;
}
.more__list li::before {
  font-size: 1em;
  line-height: 1;
  color: var(--accent);
  content: "\2022";
}
.walk__step {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(32px, 5vw, 88px);
  align-items: center;
}
/* Zigzag: even steps put the media on the right. The rtl flip swaps
   the two columns without reordering the DOM (copy stays first for
   screen readers); children are flipped back to ltr. */
.walk__step--reverse {
  direction: rtl;
}
.walk__step--reverse > * {
  direction: ltr;
}

.walk__say {
  display: grid;
  gap: var(--s-3);
  align-content: center;
}
.walk__label {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.2em;
}
.walk__h {
  margin: 0;
  font-size: clamp(28px, 3.4vw, 49px);
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: -0.035em;
}
.walk__p {
  max-width: 42ch;
  margin: 0;
  font-size: clamp(16px, 1.3vw, 20px);
  line-height: 1.5;
  color: var(--fg-mute);
}
.walk__p em {
  font-style: normal;
  font-weight: 600;
  color: var(--fg);
}

/* Each step's media is a transparent app-window PNG (with its own
   native macOS drop shadow) sitting on a "desktop": a cool gradient
   panel so a same-colour theme window (the yellow CSC window on the
   yellow page) has a screen to sit on instead of blending away. */
.walk__media {
  margin: 0;
}
.walk__media--window {
  padding: clamp(16px, 2.4vw, 40px);
  overflow: hidden;
  background-color: var(--desk-2); /* fill before the wallpaper paints */
  /* Orange "desk" wallpaper. Plain webp first (every gated browser supports it)
     so non-image-set browsers still get the wallpaper; image-set() upgrades to
     AVIF where supported. Propshaft fingerprints each file (immutable, auto-busted). */
  background-image: url("/assets/desk-wallpaper-e1902daa.webp");
  background-image: image-set(
    url("/assets/desk-wallpaper-0eb00b95.avif") type("image/avif"),
    url("/assets/desk-wallpaper-e1902daa.webp") type("image/webp")
  );
  background-position: center;
  background-size: cover;
  border-radius: 18px;
  box-shadow: 0 36px 80px -48px rgb(0, 0, 0, 0.5);
}
.walk__media--window .walk__img {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 980px) {
  .walk {
    gap: var(--s-11);
  }
  .walk__step {
    grid-template-columns: 1fr;
    gap: var(--s-6);
  }
  .walk__step--reverse {
    direction: ltr;
  }
}

/* §01 coda — the shareable result card (the SAVE IMAGE export). */
.share-card {
  display: grid;
  grid-template-columns: 1fr 0.8fr;
  gap: clamp(32px, 5vw, 88px);
  align-items: center;
  margin-top: var(--s-13);
}
.share-card__say {
  display: grid;
  gap: var(--s-3);
  align-content: center;
}
.share-card__title {
  margin: 0;
  font-size: clamp(28px, 3.4vw, 49px);
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: -0.035em;
}
.share-card__title em {
  font-style: normal;
  color: var(--accent);
}
.share-card__body {
  max-width: 46ch;
  margin: 0;
  font-size: clamp(16px, 1.3vw, 20px);
  line-height: 1.5;
  color: var(--fg-mute);
}
.share-card__fig {
  justify-self: center;
  margin: 0;
}
.share-card__img {
  display: block;
  width: 100%;
  max-width: 380px;
  height: auto;
  border-radius: 4px;
  box-shadow: 0 40px 80px -40px rgb(0, 0, 0, 0.45);
}
@media (max-width: 980px) {
  .share-card {
    grid-template-columns: 1fr;
    gap: var(--s-6);
    margin-top: var(--s-11);
  }
}

/* The Statistics dashboard preview — a manually-scrollable panel at beat
   size, so it sits beside its copy instead of dominating the page. A
   visible accent scrollbar signals it's there to be explored; no edge
   fades, no auto-pan — the reader scrolls it. */
.long-screen {
  height: clamp(360px, 52vh, 540px);
  overflow-y: auto;
  scrollbar-color: var(--accent) rgb(255, 255, 255, 0.12);
  scrollbar-width: thin;
  background: var(--ink-2);
  border-radius: 14px;
  box-shadow: 0 32px 80px -32px rgb(0, 0, 0, 0.45);
}
.long-screen:focus-visible {
  outline: var(--bw-2) solid var(--accent);
  outline-offset: 3px;
}
.long-screen::-webkit-scrollbar {
  width: 10px;
}
.long-screen::-webkit-scrollbar-thumb {
  background: var(--accent);
  border: 3px solid var(--ink-2);
  border-radius: 999px;
}
.long-screen::-webkit-scrollbar-track {
  background: transparent;
}
.long-screen__img {
  display: block;
  width: 100%;
  height: auto;
}

/* The dashboard sits on a full-bleed dark band: the capture is the CSC
   (yellow) theme, so against the yellow page it would blend; the dark
   ground makes it stand out and breaks the section. The inner content
   is the standard two-column walk step, re-coloured for the dark. */
.dashband {
  width: 100vw;
  padding: clamp(56px, 7vw, 104px) var(--pad);
  margin-block: var(--s-13);
  margin-inline: calc(50% - 50vw);
  background: var(--surface-dark);
}
.dashband .long-screen {
  box-shadow: 0 0 0 var(--bw-1) rgb(255, 255, 255, 0.1);
}
.dashband .walk__h {
  color: var(--paper);
}
.dashband .walk__p {
  color: rgb(242, 237, 226, 0.7);
}
.dashband .walk__p em {
  color: var(--paper);
}

/* Scroll affordance over the dashboard panel: a mouse-scroll glyph and a
   gently bobbing double caret in a dark pill at the panel foot, so the
   (yellow) capture clearly reads as scrollable. Pinned to the figure,
   not the scroller, so it stays put while the panel scrolls under it. */
.dashband .walk__media {
  position: relative;
}
.scroll-hint {
  position: absolute;
  bottom: var(--s-4);
  left: 50%;
  display: inline-flex;
  gap: var(--s-1);
  align-items: center;
  padding: var(--s-2) var(--s-3);
  color: var(--accent);
  pointer-events: none;
  background: var(--surface-dark);
  border: var(--bw-1) solid rgb(255, 255, 255, 0.14);
  border-radius: 999px;
  box-shadow: 0 10px 28px -10px rgb(0, 0, 0, 0.6);
  transform: translateX(-50%);
}
.scroll-hint__mouse,
.scroll-hint__caret {
  display: block;
}
@media (prefers-reduced-motion: no-preference) {
  .scroll-hint__caret {
    animation: scroll-bob 1.6s var(--ease) infinite;
  }
}
@keyframes scroll-bob {
  0%,
  100% {
    transform: translateY(-2px);
  }
  50% {
    transform: translateY(2px);
  }
}

@media (max-width: 980px) {
  .major__head {
    grid-template-columns: 1fr;
    gap: var(--s-4);
  }
  .major__head--reverse {
    direction: ltr;
  }
  .major__desc {
    justify-self: start;
  }
  .major__shots--pair {
    grid-template-columns: 1fr;
  }
}

/* ==================================================================
   BODIES BANNER
   ================================================================== */
.bodies {
  padding: var(--s-11) var(--pad);
  color: var(--paper);
  background: var(--ink-2);
}
.bodies__big {
  margin: 0 0 var(--s-3);
  font-size: clamp(64px, 13vw, 180px);
  font-weight: 900;
  line-height: 0.85;
  letter-spacing: -0.06em;
}
.bodies__big .accent {
  color: var(--accent-pop);
}
.bodies__brands {
  margin: 0 0 var(--s-5);
  font-family: var(--font-display);
  font-size: clamp(18px, 2.2vw, 34px);
  font-weight: 700;
  line-height: 1.2;
  color: rgb(242, 237, 226, 0.7);
  letter-spacing: -0.015em;
}
.bodies__brands .sep {
  margin: 0 var(--s-2);
  color: var(--accent);
}
.bodies__link {
  display: inline-flex;
  gap: var(--s-2);
  align-items: center;
  padding-bottom: 4px;
  font-family: var(--font-mono);
  font-size: var(--t-100);
  color: var(--paper);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  border-bottom: var(--bw-2) solid var(--accent);
  transition:
    color var(--t150) var(--ease),
    border-color var(--t150) var(--ease);
}
.bodies__link:hover {
  color: var(--accent);
}

/* ==================================================================
   ORIGIN / ABOUT
   ================================================================== */
.origin {
  padding: var(--s-12) var(--pad);
}
.origin__inner {
  max-width: 880px;
  margin: 0 auto;
}
.origin__title {
  margin: 0 0 var(--s-6);
  font-size: clamp(36px, 5.6vw, 88px);
  font-weight: 800;
  line-height: 0.96;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.origin__body {
  max-width: 60ch;
  margin: 0 0 var(--s-4);
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.55;
}
.origin__body em {
  font-style: normal;
  font-weight: 700;
}

/* ==================================================================
   WEAR BAR (replacing 'X of Y' text)
   ================================================================== */
.wear {
  display: grid;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  letter-spacing: 0.08em;
}
.chapter {
  position: relative;
  display: grid;
  grid-template-columns: 72px 120px 1fr 120px;
  align-items: stretch;
  overflow: hidden;
  cursor: pointer;
  background: var(--ink-0);
  transition: background-color var(--t200) var(--ease);
}
.chapter:hover {
  background: var(--ink);
}
.chapter > * {
  padding: var(--s-5) var(--s-3);
}
@media (max-width: 880px) {
  .chapter {
    grid-template-columns: 56px 1fr;
  }
}

.ticket {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 200px;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  overflow: hidden;
  color: var(--ink);
  background: var(--paper);
  border-radius: 6px;
  box-shadow: 0 24px 48px -24px rgb(0, 0, 0, 0.35);
}
.ticket::before,
.ticket::after {
  position: absolute;
  top: 50%;
  width: 22px;
  height: 22px;
  content: "";
  background: var(--bg);
  border-radius: 50%;
  transform: translateY(-50%);
}
.ticket::before {
  left: -11px;
}
.ticket::after {
  right: -11px;
}
@media (max-width: 880px) {
  .ticket {
    grid-template-columns: 1fr;
  }
}

/* ==================================================================
   CTA strip
   ================================================================== */
.cta {
  color: var(--paper);
  background: var(--ink-2);
}
.cta .btn {
  color: var(--ink);
  background: var(--accent-pop);
  border-color: var(--accent-pop);
}
.cta .btn--secondary {
  color: var(--paper);
  background: transparent;
  border-color: rgb(242, 237, 226, 0.4);
}
.cta .btn--secondary:hover {
  color: var(--accent-pop);
  border-color: var(--accent-pop);
}

/* ==================================================================
   FOOTER
   ================================================================== */
.footer {
  padding: var(--s-8) var(--pad) var(--s-4);
  color: var(--fg);
  background: var(--bg);
  border-top: var(--bw-1) solid var(--line);
}
.footer__top {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
  gap: var(--s-5);
  padding-bottom: var(--s-7);
  border-bottom: var(--bw-1) solid var(--line);
}
.footer__brand .top {
  display: flex;
  gap: var(--s-2);
  align-items: center;
}
.footer h2 {
  margin: 0 0 var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 600;
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.footer ul {
  display: grid;
  gap: var(--s-1);
  padding: 0;
  margin: 0;
  list-style: none;
}
.footer ul a {
  font-size: var(--t-100);
  line-height: 1.5;
  color: var(--fg);
  transition: color var(--t150) var(--ease);
}
.footer ul a:hover {
  color: var(--accent);
}
.footer__bot {
  display: flex;
  gap: var(--s-3);
  justify-content: space-between;
  margin-top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.footer__legal {
  display: flex;
  gap: var(--s-4);
}
.footer__legal a {
  color: var(--fg-mute);
  transition: color var(--t150) var(--ease);
}
.footer__legal a:hover {
  color: var(--accent);
}
@media (max-width: 760px) {
  .footer__top {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-6) var(--s-4);
  }
  /* Brand leads as a full-width header; the four link groups sit in a tidy
     2-up grid beneath it instead of being stranded in the first cell. */
  .footer__brand {
    grid-column: 1 / -1;
  }
  /* Copyright over legal links, left-aligned, instead of a cramped row. */
  .footer__bot {
    flex-direction: column;
    gap: var(--s-3);
    align-items: flex-start;
  }
}

/* ==================================================================
   PAGE HERO (interior pages — slimmer than home)
   ================================================================== */
.phero {
  padding: var(--s-10) var(--pad) var(--s-8);
  border-bottom: var(--bw-1) solid var(--line);
}
.phero__crumbs {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  margin-bottom: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
}
.phero__crumbs .sep {
  color: var(--accent);
}
/* The current-page crumb reads as the orange hero eyebrow, matching
   .intro__eyebrow (/preview, /download) exactly in size, weight and
   tracking so the eyebrow doesn't jump when navigating the top nav. */
.phero__crumbs .here,
.cam-d-hero__crumbs .here {
  font-size: var(--t-100);
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.4em;
}
.phero h1 {
  margin: 0;
  font-size: clamp(var(--t-700), 8vw, var(--t-1000));
  font-weight: 900;
  line-height: 0.88;
  letter-spacing: -0.04em;
  text-wrap: balance;
}
.phero__sub {
  max-width: 58ch;
  margin: var(--s-3) 0 0;
  font-size: clamp(var(--t-200), 1.4vw, var(--t-300));
  line-height: 1.42;
  color: var(--fg-mute);
}

/* ==================================================================
   CAMERA INDEX
   ================================================================== */
.cam-filter {
  display: flex;
  gap: var(--s-1);
  width: max-content;
  padding: 4px;
  margin-bottom: var(--s-5);
  border: var(--bw-1) solid var(--line);
  border-radius: 4px;
}
.cam-filter button {
  padding: var(--s-1) var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  border-radius: 2px;
  transition:
    color var(--t150) var(--ease),
    background-color var(--t150) var(--ease);
}
.cam-filter button[aria-pressed="true"] {
  color: var(--bg);
  background: var(--fg);
}
.cam-filter button:hover {
  color: var(--fg);
}
.cam-filter button[aria-pressed="true"]:hover {
  color: var(--bg);
}

.cam-make {
  padding-top: var(--s-4);
  margin-bottom: var(--s-6);
  border-top: var(--bw-1) solid var(--line);
}
.cam-make__head {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  margin-bottom: var(--s-3);
}
.cam-make__name {
  font-size: var(--t-600);
  font-weight: 800;
  letter-spacing: -0.025em;
}
.cam-make__count {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  letter-spacing: 0.14em;
}

.cam-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
.cam-row {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-3) 0;
  border-top: var(--bw-1) solid var(--line);
  transition: background-color var(--t150) var(--ease);
}
.cam-row:last-child {
  border-bottom: var(--bw-1) solid var(--line);
}
.cam-row:hover {
  background: rgb(17, 17, 17, 0.04);
}
html[data-theme="darkroom"] .cam-row:hover {
  background: rgb(242, 237, 226, 0.04);
}
.cam-row__model {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
}
.cam-row__model .name {
  font-size: var(--t-300);
  font-weight: 700;
  letter-spacing: -0.015em;
}
.cam-row__model .slug {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  letter-spacing: 0.04em;
}
.cam-row__life {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-align: end;
  letter-spacing: 0.06em;
}
.cam-row__life .v {
  /* Reserve the width of the widest rated value ("500,000") so a body with
     fewer digits (e.g. 50,000) doesn't shrink the life column. Otherwise the
     narrower cell lets the 1fr model column grow and slides the method badge
     out of alignment. Sizing the number (not the whole cell) keeps this
     locale-proof: the "Rated" label varies per language but is constant
     within a page. NB: a `ch` unit can't be used here because it measures the
     bare glyph and ignores the 0.06em letter-spacing, so 7 chars render ~5px
     wider than 7ch; var(--s-8) (56px) covers the widest 7-char value. */
  display: inline-block;
  min-width: var(--s-8);
  color: var(--fg);
  text-align: end;
}
.cam-row__open {
  display: flex;
  gap: var(--s-1);
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  transition: color var(--t150) var(--ease);
}
.cam-row:hover .cam-row__open {
  color: var(--fg);
}
.cam-row:hover .cam-row__open .arr {
  transform: translateX(3px);
}
.cam-row__open .arr {
  display: inline-block;
  transition: transform var(--t150) var(--ease);
}
@media (max-width: 760px) {
  .cam-row {
    grid-template-columns: 1fr;
    gap: var(--s-2);
  }
  .cam-row__life {
    text-align: start;
  }
  /* Method badge is a grid child; stop it stretching to the full 1fr
     column on mobile so it hugs its label. */
  .cam-row .badge {
    justify-self: start;
  }
}

/* Method badges */
.badge {
  display: inline-flex;
  gap: var(--s-1);
  align-items: center;
  /* Centre the label and give every single-method badge the same footprint,
     so the shorter "USB" (3) and the wider "EXIF" (4) read as one size.
     5em (= 50px at --t-50) clears the widest single label; the multi-method
     "both" badge has more text and grows past this floor on its own. */
  justify-content: center;
  min-width: 5em;
  padding: var(--s-1) var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-50);
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  border: var(--bw-1) solid var(--fg);
  border-radius: 2px;
}
.badge--usb {
  color: var(--ink);
  background: var(--green);
  border-color: var(--ink);
}
.badge--exif {
  color: var(--ink);
  background: var(--caution);
  border-color: var(--ink);
}
.badge--both {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}
html[data-theme="darkroom"] .badge--usb,
html[data-theme="darkroom"] .badge--exif {
  border-color: var(--paper);
}
html[data-theme="darkroom"] .badge--both {
  color: var(--ink);
  background: var(--paper);
}

.callout {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-3) var(--s-4);
  margin-top: var(--s-6);
  border: var(--bw-2) solid var(--line-strong);
  border-radius: 2px;
}
.callout p {
  margin: 0;
  font-size: var(--t-200);
  line-height: 1.42;
}
.callout .mono {
  color: var(--fg-mute);
}

.warn {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: rgb(224, 65, 58, 0.06);
  border: var(--bw-2) solid var(--red);
  border-radius: 2px;
}

/* ==================================================================
   TRIAL FLOW
   ================================================================== */
.austere {
  display: flex;
  align-items: center;
  min-height: calc(100vh - 56px);
  padding: var(--s-7) var(--pad);
}
.austere__inner {
  width: 100%;
  max-width: 800px;
}
.austere h1 {
  margin: 0;
  font-size: clamp(var(--t-600), 4vw, var(--t-800));
  font-weight: 900;
  line-height: 0.94;
  letter-spacing: -0.04em;
}
/* Architectural display heading — opt-in (sign-in only). Sets two
   short words on one line for a Bass-style title-card moment; pair with
   one child span carrying .austere__display-accent to flip its colour. */
.austere__display {
  margin: 0;
  font-size: clamp(var(--t-900), 12vw, var(--t-1100));
  font-weight: 900;
  line-height: 0.86;
  letter-spacing: -0.045em;
}
.austere__display > span {
  display: inline;
}
.austere__eyebrow {
  display: block;
  margin-bottom: var(--s-4);
  color: var(--accent);
}
.austere .lede {
  max-width: 36ch;
  margin: var(--s-5) 0 var(--s-6);
  font-size: var(--t-300);
  line-height: 1.42;
  color: var(--fg);
}
.austere .alert {
  margin-bottom: var(--s-4);
}
.field {
  display: grid;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}
.field label {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.field input {
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-200);
  color: var(--fg);
  background: transparent;
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 2px;
  transition: border-color var(--t150) var(--ease);
}
.field input:focus {
  outline: none;
  border-color: var(--accent);
}
/* Password input + inline show/hide toggle (password-visibility
   controller). The input keeps its normal .field styling and flex-grows
   to fill the row; the toggle is a small mono button beside it. */
.password-field {
  display: flex;
  gap: var(--s-2);
  align-items: stretch;
}
.password-field__input {
  flex: 1 1 auto;
  min-width: 0;
}
.password-field__toggle {
  flex: 0 0 auto;
  padding: 0 var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  cursor: pointer;
  background: transparent;
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 2px;
  transition:
    color var(--t150) var(--ease),
    border-color var(--t150) var(--ease);
}
.password-field__toggle:hover {
  color: var(--fg);
  border-color: var(--accent);
}
/* Bare underline-only input treatment inside auth screens — drops the
   boxed border so the field sits on the yellow page like a credit line
   under the display heading. Focus thickens the underline to --bw-2
   and flips it accent. */
.austere .field {
  margin-bottom: var(--s-4);
}
.austere .field input,
.austere .field select {
  padding: var(--s-2) 0;
  font-family: var(--font-mono);
  font-size: var(--t-300);
  color: var(--fg);
  background: transparent;
  border: 0;
  border-bottom: var(--bw-1) solid var(--fg);
  border-radius: 0;
  transition:
    border-bottom-color var(--t150) var(--ease),
    border-bottom-width var(--t150) var(--ease);
}
.austere .field input::placeholder {
  color: var(--fg-mute);
}
.austere .field input:focus,
.austere .field select:focus {
  outline: none;
  border-bottom-color: var(--accent);
  border-bottom-width: var(--bw-2);
}

/* Native <select> styled to match the underline-only input. The
   phosphor caret sits over the right edge via .auth-select wrapper
   (appearance:none hides the platform arrow). */
.austere .field select {
  padding-inline-end: var(--s-5);
  appearance: none;
  cursor: pointer;
}
.auth-select {
  position: relative;
}
.auth-select__caret {
  position: absolute;
  inset-inline-end: 0;
  bottom: var(--s-2);
  display: inline-flex;
  color: var(--fg);
  pointer-events: none;
}

.austere__foot {
  padding-top: var(--s-3);
  margin-top: var(--s-5);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  line-height: 1.42;
  color: var(--fg-mute);
  letter-spacing: 0.04em;
}
.austere__foot ul {
  padding-inline-start: var(--s-3);
  margin: var(--s-2) 0 0;
  list-style: square;
}
.austere__foot li::marker {
  color: var(--accent);
}

/* Auth (sign-in / passkey) — stacked single-input form inside .austere */
.auth-form {
  display: grid;
  gap: var(--s-5);
  margin-top: var(--s-5);
}
.auth-submit {
  justify-self: start;
  margin-top: var(--s-4);
  border-radius: 0;
}
/* Generic <details> disclosure inside auth screens — used for the
   optional-password reveal on /signup, etc. Strip the platform marker
   and use a rotating phosphor caret as the affordance. */
.auth-disclosure {
  padding-top: var(--s-3);
  margin-top: var(--s-3);
}
.auth-disclosure summary {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  padding: var(--s-2) 0;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  cursor: pointer;
  list-style: none;
  transition: color var(--t150) var(--ease);
}
.auth-disclosure summary::-webkit-details-marker {
  display: none;
}
.auth-disclosure summary:hover,
.auth-disclosure[open] summary {
  color: var(--fg);
}
.auth-disclosure__caret {
  display: inline-flex;
  transition: transform var(--t150) var(--ease);
}
.auth-disclosure[open] .auth-disclosure__caret {
  transform: rotate(180deg);
}
.auth-disclosure__hint {
  margin: var(--s-3) 0 0;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  line-height: 1.5;
  color: var(--fg-mute);
}
.auth-disclosure .field {
  margin-top: var(--s-3);
}

/* Server-side form errors panel — sits between the lede and the form.
   Heavy --bw-3 red left rule so it reads as a stop sign without
   shouting in a coloured box. */
.auth-errors {
  padding: var(--s-2) var(--s-3);
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  line-height: 1.5;
  color: var(--fg);
  letter-spacing: 0.04em;
  border-inline-start: var(--bw-3) solid var(--red);
}
.auth-errors__head {
  display: block;
  color: var(--red);
}
.auth-errors ul {
  padding-inline-start: var(--s-3);
  margin: var(--s-2) 0 0;
  list-style: disc;
}
.auth-errors li::marker {
  color: var(--red);
}

/* ==================================================================
   DOWNLOAD — grid/cell rules live with the page template in
   app/views/downloads/index.html.erb (single source of truth).
   ================================================================== */

/* ==================================================================
   CHANGELOG
   ================================================================== */
.reel {
  border-top: var(--bw-1) solid var(--line);
}
.reel__entry {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: var(--s-6);
  padding: var(--s-6) 0;
  border-bottom: var(--bw-1) solid var(--line);
}
.reel__meta {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
}
.reel__meta .v {
  display: block;
  font-size: var(--t-300);
  font-weight: 700;
  color: var(--fg);
  letter-spacing: 0.04em;
}
.reel__meta .date {
  display: block;
  margin-top: var(--s-1);
}
/* Top-align the first release note (its rendered heading/paragraph carries a
   default top margin) with the version label in the meta column. */
.reel__notes > :first-child {
  margin-top: 0;
}
.reel__notes h3 {
  margin: 0 0 var(--s-2);
  font-size: var(--t-500);
  font-weight: 700;
  letter-spacing: -0.025em;
}
.reel__notes ul {
  display: grid;
  gap: 4px;
  padding-inline-start: var(--s-3);
  margin: 0;
}
.reel__notes li {
  font-size: var(--t-200);
  line-height: 1.5;
}
.reel__notes li::marker {
  color: var(--accent);
}
.reel__notes .tag {
  display: inline-flex;
  padding: 2px var(--s-2);
  margin-inline-end: var(--s-1);
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 2px;
}
.reel__notes .tag.new {
  color: var(--ink);
  background: var(--green);
  border-color: var(--ink);
}
.reel__notes .tag.fix {
  color: var(--ink);
  background: var(--caution);
  border-color: var(--ink);
}
.reel__notes .tag.imp {
  color: var(--ink);
  background: var(--emphasis);
  border-color: var(--ink);
}
@media (max-width: 760px) {
  .reel__entry {
    grid-template-columns: 1fr;
  }
}

/* ==================================================================
   LEGAL (editorial)
   ================================================================== */
.editorial {
  max-width: 720px;
  margin: 0 auto;
}
.editorial h2 {
  margin: var(--s-7) 0 var(--s-3);
  font-size: var(--t-500);
  font-weight: 700;
  letter-spacing: -0.02em;
}
.editorial h3 {
  margin: var(--s-5) 0 var(--s-2);
  font-size: var(--t-300);
  font-weight: 700;
  letter-spacing: -0.015em;
}
.editorial p {
  margin: 0 0 var(--s-3);
  font-size: var(--t-200);
  line-height: 1.65;
}
.editorial ul {
  padding-inline-start: var(--s-3);
  margin: 0 0 var(--s-3);
}
.editorial li {
  margin-bottom: var(--s-1);
  font-size: var(--t-200);
  line-height: 1.65;
}
.editorial li::marker {
  color: var(--accent);
}
.editorial blockquote {
  padding: var(--s-3) var(--s-4);
  margin: var(--s-5) 0;
  font-size: var(--t-300);
  font-weight: 500;
  line-height: 1.42;
  color: var(--fg);
  border-inline-start: var(--bw-3) solid var(--accent);
}

.editorial__chapter {
  display: flex;
  gap: var(--s-2);
  align-items: baseline;
  margin-top: var(--s-6);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.editorial__chapter .frame {
  color: var(--accent);
}

/* ==================================================================
   ACCOUNT (instrument-panel calm)
   ================================================================== */
.dash {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: var(--s-7);
  align-items: start;
}
.dash__side {
  position: sticky;
  top: var(--s-9);
  padding-inline-end: var(--s-4);
  border-inline-end: var(--bw-1) solid var(--line);
}
.dash__side .dash__side-h {
  margin: 0 0 var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.dash__nav {
  display: grid;
  gap: var(--s-1);
  padding: 0;
  margin: 0 0 var(--s-5);
  list-style: none;
}
.dash__nav a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-1) var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  border-radius: 2px;
  transition:
    color var(--t150) var(--ease),
    background-color var(--t150) var(--ease);
}
.dash__nav a:hover {
  color: var(--fg);
}
.dash__nav a[aria-current="page"] {
  color: var(--bg);
  background: var(--fg);
}

.panel {
  padding: var(--s-5);
  margin-bottom: var(--s-4);
  background: color-mix(in srgb, var(--ink) 2%, transparent);
  border: var(--bw-1) solid var(--line);
  border-radius: 4px;
}
/* A tidy minimum width so panel action buttons line up regardless of
   label length. Compact (table), utility (text) and full-width download
   buttons opt out. */
.panel .btn {
  justify-content: center;
  min-width: 11rem;
}
.panel .btn--sm,
.panel .btn--utility,
.dl-mini-col__btns .btn {
  min-width: 0;
}
html[data-theme="darkroom"] .panel {
  background: color-mix(in srgb, var(--paper) 2%, transparent);
}
/* One panel header everywhere: title, then subtitle, then the action —
   stacked and left-aligned, never floated right, and separated from the
   body by space rather than a rule (some panels had a rule, some didn't).
   Consistent across every account page. */
.panel__head {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  align-items: flex-start;
  margin-bottom: var(--s-4);
}
.panel__head > :first-child {
  align-self: stretch;
}
.panel__head:only-child {
  margin-bottom: 0;
}
.panel__title {
  font-size: var(--t-400);
  font-weight: 700;
  letter-spacing: -0.02em;
}
/* Panel subtitle / description. Prose, so it's set in the body sans —
   mono is reserved for actual data (column labels, licence keys). */
.panel__meta {
  font-size: var(--t-100);
  line-height: 1.5;
  color: var(--fg-mute);
}

/* Purchase summary grid — one precise instrument row of key/value pairs
   (product · date · amount · licence key). Shared by the Billing tab's
   purchase list and the refund-request form so both read identically:
   consistent value sizing, top-aligned columns, mono for the
   machine-readable fields. */
.acct-purchase__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.7fr);
  gap: var(--s-3) var(--s-5);
  align-items: start;
  margin: 0 0 var(--s-4);
}
.acct-kv {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-width: 0;
  margin: 0;
}
.acct-kv__k {
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  white-space: nowrap;
}
.acct-kv__v {
  margin: 0;
  font-size: var(--t-200);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
  color: var(--fg);
  letter-spacing: -0.005em;
  overflow-wrap: anywhere;
}
.acct-kv__v--mono {
  font-family: var(--font-mono);
  font-weight: 500;
  letter-spacing: 0.02em;
}
@media (max-width: 720px) {
  .acct-purchase__grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 440px) {
  .acct-purchase__grid {
    grid-template-columns: 1fr;
  }
}

/* Form placeholders: faint muted ink so they read as a hint, not real
   typed text (the browser default also reads blue-grey on the brand bg). */
::placeholder {
  color: var(--fg-mute-2);
  opacity: 1;
}
/* Account form focus: a theme accent ring, not the browser's blue glow. */
.field input:focus-visible,
.field textarea:focus-visible {
  outline: var(--bw-2) solid var(--accent);
  outline-offset: 2px;
}

/* Device "ticket" — each activated install is a self-contained card: its
   identity (name / id + revoke) on top, a labelled instrument-panel readout
   beneath, rather than a cramped multi-column table. Shared by the devices
   and licence pages. */
.device-list {
  display: grid;
  gap: var(--s-3);
}
.device {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 2px;
}
.device--revoked {
  opacity: 0.55;
}
.device__top {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  align-items: center;
  justify-content: space-between;
}
.device__id {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-width: 0;
}
.device__name {
  font-size: var(--t-300);
  font-weight: 700;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}
.device__uuid {
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute-2);
  letter-spacing: 0.04em;
  overflow-wrap: anywhere;
}
.device__rename {
  display: flex;
  gap: var(--s-2);
  align-items: center;
}
.device__rename-input {
  width: 12rem;
  max-width: 100%;
  padding: var(--s-1) var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-100);
  color: var(--fg);
  background: transparent;
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 2px;
  transition: border-color var(--t150) var(--ease);
}
.device__rename-input:focus-visible {
  outline: none;
  border-color: var(--accent);
}
.device__meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--s-3) var(--s-4);
  padding-top: var(--s-4);
  margin: 0;
  border-top: var(--bw-1) solid var(--line);
}
.device__meta > div {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
.device__meta dt {
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.device__meta dd {
  margin: 0;
  font-size: var(--t-100);
}

/* ── Licence-key reveal ──────────────────────────────────────────────
   The key is blurred until the eye is toggled, so it's safe to leave on
   screen while streaming. Pure CSS (a visually-hidden checkbox drives the
   blur): works without JS and never flashes the key un-blurred on load. */
.secret-key {
  display: inline-flex;
  gap: var(--s-2);
  align-items: center;
}
.secret-key__cb {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.secret-key__mask {
  letter-spacing: 0.1em;
}
.secret-key__value {
  display: none;
}
.secret-key__cb:checked ~ .secret-key__mask {
  display: none;
}
.secret-key__cb:checked ~ .secret-key__value {
  display: inline;
}
.secret-key__toggle {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  padding: var(--s-1);
  color: var(--fg-mute);
  cursor: pointer;
  border-radius: 2px;
  transition: color var(--t150) var(--ease);
}
.secret-key__toggle:hover {
  color: var(--fg);
}
.secret-key__cb:focus-visible ~ .secret-key__toggle {
  outline: var(--bw-2) solid var(--accent);
  outline-offset: 2px;
}
.secret-key__i {
  display: inline-flex;
}
.secret-key__i--hide {
  display: none;
}
.secret-key__cb:checked ~ .secret-key__toggle .secret-key__i--show {
  display: none;
}
.secret-key__cb:checked ~ .secret-key__toggle .secret-key__i--hide {
  display: inline-flex;
}

/* ── Licence ticket ──────────────────────────────────────────────────
   A licence rendered as a tear-off ticket: a main body (plan, status, the
   key as a masked serial, a facts readout), a dashed perforation with
   punched notches, and a stub holding the actions. Shared by the licences
   list and the licence detail. */
.lic-ticket-list {
  display: grid;
  gap: var(--s-4);
}
.lic-ticket {
  position: relative;
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  border: var(--bw-2) solid var(--line-strong);
  border-radius: 3px;
}
.lic-ticket--inactive {
  opacity: 0.6;
}
.lic-ticket__main {
  display: grid;
  gap: var(--s-5);
  padding: var(--s-5);
}
.lic-ticket__head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  align-items: center;
  justify-content: space-between;
}
.lic-ticket__plan {
  font-family: var(--font-display);
  font-size: var(--t-600);
  font-weight: 800;
  letter-spacing: -0.02em;
}
.lic-ticket__serial {
  display: grid;
  gap: var(--s-2);
}
.lic-ticket__label {
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.lic-ticket .secret-key__value,
.lic-ticket .secret-key__mask {
  font-size: clamp(var(--t-200), 2.4vw, var(--t-400));
  font-weight: 700;
  letter-spacing: 0.08em;
  overflow-wrap: anywhere;
}
.lic-ticket__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--s-3) var(--s-5);
  margin: 0;
}
.lic-ticket__facts > div {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
.lic-ticket__facts dt {
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.lic-ticket__facts dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--t-200);
  letter-spacing: 0.02em;
}
.lic-ticket__perf {
  position: relative;
  height: 0;
  border-top: var(--bw-1) dashed var(--line-strong);
}
.lic-ticket__perf::before,
.lic-ticket__perf::after {
  position: absolute;
  top: 0;
  width: var(--s-3);
  height: var(--s-3);
  content: "";
  background: var(--bg);
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 50%;
}
.lic-ticket__perf::before {
  left: 0;
  transform: translate(-50%, -50%);
}
.lic-ticket__perf::after {
  right: 0;
  transform: translate(50%, -50%);
}
.lic-ticket__stub {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  align-items: center;
  padding: var(--s-4) var(--s-5);
}
.lic-ticket__stub:empty {
  display: none;
}
.lic-rule {
  margin: 0 0 var(--s-4);
  font-size: var(--t-75);
  line-height: 1.5;
  color: var(--fg-mute);
  letter-spacing: 0.04em;
}
.lic-notice {
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: var(--bw-2) solid var(--accent);
  border-radius: 2px;
}
.lic-notice__label {
  color: var(--accent);
}
.lic-notice__body {
  margin: var(--s-1) 0 0;
  font-size: var(--t-100);
  line-height: 1.5;
}
.lic-empty {
  margin: 0;
  color: var(--fg-mute);
}
.lic-revoked {
  margin-top: var(--s-4);
}

.kv-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-3);
}
.kv .k {
  font-family: var(--font-mono);
  font-size: var(--t-50);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.16em;
}
.kv .v {
  margin-top: var(--s-1);
  font-family: var(--font-mono);
  font-size: var(--t-200);
  font-weight: 500;
  letter-spacing: 0.02em;
}
.kv .v.lg {
  font-family: var(--font-display);
  font-size: var(--t-500);
  font-weight: 700;
  letter-spacing: -0.015em;
}
@media (max-width: 760px) {
  .kv-grid {
    grid-template-columns: 1fr 1fr;
  }
  .dash {
    grid-template-columns: 1fr;
  }
  .dash__side {
    position: static;
    padding-inline-end: 0;
    padding-bottom: var(--s-3);
    border-inline-end: 0;
    border-bottom: var(--bw-1) solid var(--line);
  }
}

.pill {
  display: inline-flex;
  gap: var(--s-1);
  align-items: center;
  padding: var(--s-1) var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-50);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  border: var(--bw-1) solid var(--line-strong);
  border-radius: 2px;
}
.pill--active {
  color: var(--ink);
  background: var(--green);
  border-color: var(--ink);
}
.pill--warn {
  color: var(--ink);
  background: var(--caution);
  border-color: var(--ink);
}
.pill--revoked {
  color: var(--paper);
  background: var(--red);
  border-color: var(--ink);
}

/* ==================================================================
   INTRO HERO — borrows the app's onboarding chrome
   Two full-viewport frames on black, progress dashes top-left,
   skip top-right, camera-button motif bottom-right.
   ================================================================== */
.intro {
  color: var(--paper);
  background: var(--ink-0);
}
/* ── HERO CONVENTION ─────────────────────────────────────────────────
   Every hero on the marketing site (/, /download, /buy, /preview …)
   uses this same skeleton so the pages read as a family rather than
   four bespoke layouts.

   STRUCTURE
     .intro                       ← theme wrapper (--light or default)
       .intro__frame              ← padding + horizontal page-gutter
         .intro__left             ← solo hero
       OR
         .intro__frame--split
           .intro__split          ← 2-col container
             .intro__left         ← content stack (~1.05fr)
             .intro__right        ← single visual (~0.95fr)

   CONTENT STACK (.intro__left, in order, all optional except CTA)
     1. eyebrow         (.intro__eyebrow,         orange/accent, mono caps small)
     2. wordmark        (.intro__wordmark,        bold sans, hero scale, 1–3 lines)
     3. sentence        (.intro__sentence,        body copy, ~38ch max)
     4. action label    (.intro__actions-label,   mono caps small, optional)
     5. PRIMARY CTA     (.intro__actions .btn,    one button, full-width column)
     6. data line       (.intro__sub,             mono caps tiny, real-data meta)
     7. alt link        (.intro__actions-alt,     mono caps tiny, escape hatch)

   VISUAL (.intro__right)
     One element only — brand mark, result card, screencast. Caps at
     ~480–560px wide. The page bg is the same yellow as the desktop
     app icon's tile, so a mark renders without its own background.

   SIZING RULES
   - NO min-height. The hero sizes to its content. We tried 100vh and
     it left empty space below short heroes; viewport-fill should be
     a per-design opt-in, not a default.
   - Vertical padding: var(--s-7) (64px), generous breathing room.
   - Horizontal padding: var(--pad), the page-standard gutter.
   - Solo left-column max-width: 720px so reading width stays sane on
     wide displays.
   - Split is 1.05fr / 0.95fr with clamp(32px, 5vw, 96px) gap.

   WHAT'S NOT A HERO
   - Progress pips (.intro__chrome / .intro__progress)
   - Skip link (.intro__skip)
   - Bottom strip with back-arrow + tagline + shutter icon
     (.intro__bottom / .intro__back / .intro__shutter)
     These were vestigial from an earlier 100vh-band layout. New heroes
     don't ship them; existing pages have them removed as we touch them.

   Reach for this convention on every new top-of-page section. If a
   page wants a non-hero band on top (compact ink strip, photo
   marquee, etc.), use that pattern instead of bending .intro__frame.
   ──────────────────────────────────────────────────────────────────── */
.intro__frame {
  position: relative;
  display: grid;
  grid-auto-rows: auto;
  gap: var(--s-5);
  padding: var(--s-7) var(--pad);
  /* The /buy hero's license ticket is a fixed 1100px canvas that bleeds
     off the right edge by design. `body { overflow-x: hidden }` clips that
     on desktop, but iPad/iOS Safari doesn't honour the body-level clip, so
     the ticket widens the page and pushes the layout. Clip at the
     full-width frame instead (x only, y stays visible) — same bleed-to-
     viewport-edge look everywhere, no horizontal page overflow. */
  overflow-x: clip;
}

/* Split layout: wordmark+actions on the left, result card on the right */
.intro__split {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(32px, 5vw, 96px);
  align-items: center;
  padding: var(--s-5) 0;
}
/* Big brand mark on the right of /download's hero. Iris fill in ink,
   accent dot inherits var(--accent) from the partial. The page is
   already yellow, so the mark floats on the same ground as the
   desktop app icon — no background tile required. */
.intro__brand-mark {
  display: block;
  width: 100%;
  max-width: 480px;
  height: auto;
  color: var(--ink);
}
.intro__left {
  display: grid;
  gap: var(--s-4);
}
.intro__right {
  display: grid;
  place-items: center;
}

.intro__wordmark--stacked {
  display: grid;
  gap: 0;
  margin: 0;
  font-size: clamp(48px, 10vw, 144px);
  font-weight: 900;
  line-height: 0.88;
  color: var(--paper);
  text-transform: uppercase;
  letter-spacing: -0.04em;
}
.intro__wordmark--stacked span {
  display: block;
}
.intro__money {
  white-space: nowrap;
}
.intro__points {
  display: grid;
  gap: var(--s-2);
  padding: 0;
  margin: var(--s-3) 0 0;
  list-style: none;
}
.intro__points li {
  position: relative;
  padding-inline-start: var(--s-4);
  font-size: var(--t-200);
  line-height: 1.4;
  color: var(--fg-mute);
}
.intro__points li::before {
  position: absolute;
  inset-inline-start: 0;
  top: 0.55em;
  width: 7px;
  height: 7px;
  content: "";
  background: var(--accent);
  transform: rotate(45deg);
}

.intro__sentence {
  max-width: 38ch;
  margin: var(--s-2) 0 0;
  font-size: clamp(17px, 1.4vw, 21px);
  font-weight: 500;
  line-height: 1.42;
  color: rgb(242, 237, 226, 0.78);
}
/* Hero pricing line. */
.intro__price {
  max-width: 46ch;
  margin: var(--s-5) 0 0;
  font-size: var(--t-200);
  font-weight: 500;
  line-height: 1.6;
  color: color-mix(in srgb, var(--paper) 72%, transparent);
}
.intro__actions-label {
  margin-top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: rgb(242, 237, 226, 0.55);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.intro__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2);
  max-width: 38ch;
  margin-top: var(--s-2);
}
/* /download hero has one CTA, not two — the secondary "Different
   computer?" link sits below the data line as quiet meta, not a
   competing button. Single-button variant takes the full max-width
   row so the primary doesn't shrink to half-width awkwardly. */
.intro__actions--single {
  grid-template-columns: 1fr;
}
.intro__actions .btn {
  justify-content: center;
  color: var(--ink);
  background: var(--paper);
  border-color: var(--paper);
}
.intro__actions .btn:hover {
  color: var(--ink);
  background: var(--accent-pop);
  border-color: var(--accent-pop);
}
.intro__actions .btn--secondary {
  color: var(--paper);
  background: transparent;
  border-color: rgb(242, 237, 226, 0.4);
}
.intro__actions .btn--secondary:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* Quiet escape-hatch link beneath the data line. Mono caps in the
   same micro register as the data labels — reads as supporting
   meta, not a CTA. Anchored to #all-builds so users land on the
   four-up grid lower on the page. */
.intro__actions-alt {
  display: inline-flex;
  gap: var(--s-1);
  align-items: center;
  margin-top: var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 700;
  color: rgb(242, 237, 226, 0.55);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  transition: color var(--t150) var(--ease);
}
.intro__actions-alt:hover {
  color: var(--paper);
}
.intro.intro--light .intro__actions-alt {
  color: var(--fg-mute);
}
.intro.intro--light .intro__actions-alt:hover {
  color: var(--fg);
}

.intro__left .intro__sub {
  margin-top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: rgb(242, 237, 226, 0.45);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}

@media (max-width: 980px) {
  .intro__split {
    grid-template-columns: 1fr;
    gap: var(--s-7);
  }
  .intro__right {
    order: -1;
  }
}
.intro__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-100);
  font-weight: 600;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.4em;
}
.intro__wordmark {
  margin: 0;
  /* Fits the viewport width — "CAMERA SHUTTER COUNT" at ~13 chars per row */
  font-size: clamp(48px, 10vw, 200px);
  font-weight: 900;
  line-height: 0.9;
  color: var(--paper);
  text-transform: uppercase;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.intro__sub {
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: rgb(242, 237, 226, 0.55);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}

.linkline {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  padding: var(--s-6) 0;
  font-family: var(--font-display);
  border-top: var(--bw-1) solid var(--line);
  border-bottom: var(--bw-1) solid var(--line);
}
.linkline .v {
  font-size: clamp(var(--t-500), 5vw, var(--t-800));
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.035em;
}
.linkline a {
  align-self: center;
  margin-inline-start: auto;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.linkline a:hover {
  color: var(--fg);
}
.linkline a .arr {
  display: inline-block;
  transition: transform var(--t150) var(--ease);
}
.linkline a:hover .arr {
  transform: translateX(3px);
}

/* Form column */
.preview-form {
  display: grid;
  gap: var(--s-4);
}
.preview-form__label {
  display: block;
  margin-bottom: var(--s-1);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: rgb(242, 237, 226, 0.55);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.preview-form input[type="email"] {
  width: 100%;
  padding: var(--s-3) 0;
  font-family: var(--font-mono);
  font-size: clamp(20px, 1.6vw, 24px);
  font-weight: 500;
  color: var(--paper);
  letter-spacing: 0.01em;
  background: transparent;
  border: 0;
  border-bottom: var(--bw-2) solid rgb(242, 237, 226, 0.32);
  border-radius: 0;
  transition: border-color var(--t150) var(--ease);
}
.preview-form input[type="email"]:focus {
  outline: none;
  border-bottom-color: var(--accent);
}
.preview-form input[type="email"]::placeholder {
  color: rgb(242, 237, 226, 0.32);
}
.preview-form button {
  justify-self: start;
  color: var(--ink);
  background: var(--paper);
  border-color: var(--paper);
}
.preview-form button:hover {
  color: var(--ink);
  background: var(--accent-pop);
  border-color: var(--accent-pop);
}

/* ==================================================================
   CAMERAS INDEX — brought in line with homepage
   ================================================================== */
.cam-index {
  padding: var(--s-7) var(--pad) var(--s-12);
  color: var(--fg);
  background: var(--bg);
}
.cam-index__hero {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: clamp(32px, 6vw, 80px);
  align-items: end;
  padding: var(--s-7) 0 var(--s-9);
}
.cam-index__title {
  margin: 0;
  font-size: clamp(80px, 16vw, 280px);
  font-weight: 900;
  line-height: 0.85;
  color: var(--fg);
  letter-spacing: -0.05em;
}
.cam-index__title .plus {
  color: var(--accent);
}
.cam-index__desc {
  max-width: 44ch;
  margin: 0;
  font-size: clamp(17px, 1.5vw, 22px);
  line-height: 1.42;
  color: var(--fg-mute);
}
.cam-index__desc em {
  font-style: normal;
  font-weight: 500;
  color: var(--fg);
}
@media (max-width: 880px) {
  .cam-index__hero {
    grid-template-columns: 1fr;
    align-items: start;
  }
}

.cam-index__filter-wrap {
  display: flex;
  gap: var(--s-4);
  align-items: center;
  justify-content: space-between;
  padding: var(--s-3) 0;
  margin-bottom: var(--s-7);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  border-top: var(--bw-1) solid var(--line);
  border-bottom: var(--bw-1) solid var(--line);
}
.cam-index__filter-wrap .meta {
  display: flex;
  gap: var(--s-4);
}
.cam-index .cam-filter {
  margin-bottom: 0;
  background: transparent;
  border-color: var(--line-strong);
}
.cam-index .cam-filter button {
  color: var(--fg-mute);
}
.cam-index .cam-filter button[aria-pressed="true"] {
  color: var(--bg);
  background: var(--fg);
}
.cam-index .cam-filter button:hover {
  color: var(--fg);
}
.cam-index .cam-filter button[aria-pressed="true"]:hover {
  color: var(--bg);
}

.cam-index .cam-make {
  border-top-color: var(--line);
}
.cam-index .cam-make__name {
  color: var(--fg);
}
.cam-index .cam-make__count {
  color: var(--fg-mute);
}
.cam-index .cam-row {
  border-top-color: var(--line);
}
.cam-index .cam-row:last-child {
  border-bottom-color: var(--line);
}
.cam-index .cam-row:hover {
  background: rgb(17, 17, 17, 0.05);
}
.cam-index .cam-row__model .name {
  color: var(--fg);
}
.cam-index .cam-row__model .slug {
  color: var(--fg-mute);
}
.cam-index .cam-row__life {
  color: var(--fg-mute);
}
.cam-index .cam-row__life .v {
  color: var(--fg);
}
.cam-index .cam-row__open {
  color: var(--fg-mute);
}
.cam-index .cam-row:hover .cam-row__open {
  color: var(--fg);
}

.cam-index .badge--both {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}
.cam-index .badge--usb {
  color: var(--ink);
  background: var(--green);
  border-color: var(--ink);
}
.cam-index .badge--exif {
  color: var(--ink);
  background: var(--paper);
  border-color: var(--ink);
}

/* ==================================================================
   CAMERA DETAIL
   ================================================================== */
.cam-d-hero {
  padding: var(--s-5) var(--pad) var(--s-10);
  color: var(--fg);
  background: var(--bg);
}
.cam-d-hero__crumbs {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  padding-top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.cam-d-hero__crumbs a {
  color: var(--fg);
  transition: color var(--t150) var(--ease);
}
.cam-d-hero__crumbs a:hover {
  color: var(--accent);
}
.cam-d-hero__crumbs .sep {
  color: var(--accent);
}
.cam-d-hero__meta {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  align-items: flex-start;
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  letter-spacing: 0.06em;
}
.cam-d-hero__meta strong {
  font-weight: 600;
  color: var(--fg);
}

.cam-d-methods {
  padding: var(--s-12) var(--pad);
  background: var(--bg);
}

/* ==================================================================
   THEME FEATURE — interactive picker that lives in § 04 on the home
   page (Settings section). Three big cards rendered in each theme's
   actual palette; clicking one reskins the entire site. The proof
   is the demonstration — visitors SEE the feature, they don't read
   about it. Mirrors the desktop app's settings → theme cards just
   adapted to the marketing page's scale and rhythm.
   ================================================================== */
.theme-feature {
  display: grid;
  gap: var(--s-9);
  justify-items: center;
  width: 100vw;
  padding: clamp(56px, 8vw, 112px) var(--pad);
  margin-block: var(--s-13);
  margin-inline: calc(50% - 50vw);
  text-align: center;
  background: var(--surface-dark);
}
.theme-feature__head {
  display: grid;
  gap: var(--s-3);
  max-width: 52ch;
}
.theme-feature__title {
  margin: 0;
  font-size: clamp(var(--t-500), 4vw, var(--t-800));
  font-weight: 900;
  line-height: 1.02;
  color: var(--paper);
  letter-spacing: -0.035em;
}
.theme-feature__title em {
  font-style: normal;
  color: var(--accent);
}
.theme-feature__hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 700;
  color: rgb(242, 237, 226, 0.55);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.theme-feature__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-5);
  width: 100%;
  max-width: 860px;
}
@media (max-width: 760px) {
  .theme-feature__grid {
    grid-template-columns: 1fr;
  }
}

/* One theme card — mirrors the desktop app's Appearance/onboarding
   card: a preview split into the theme's LIGHT field + accent bar +
   DARK field (an accent dot + mode label in each), name below. Field
   colours are passed inline (the app's own theme values). Click reskins
   the whole site (setTheme in csc_site.js). */
.theme-card {
  display: grid;
  gap: var(--s-3);
  padding: 0;
  text-align: center;
  cursor: pointer;
  background: transparent;
  border: 0;
  transition: transform var(--t150) var(--ease);
}
.theme-card:hover {
  transform: translateY(-3px);
}
.theme-card:active {
  transform: translateY(0);
}
.theme-card__preview {
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 10px;
  box-shadow: 0 0 0 var(--bw-1) rgb(255, 255, 255, 0.12);
  transition: box-shadow var(--t150) var(--ease);
}
.theme-card[aria-pressed="true"] .theme-card__preview {
  box-shadow: 0 0 0 var(--bw-3) var(--accent);
}
.theme-card__field {
  position: relative;
  display: flex;
  align-items: flex-end;
  padding: var(--s-3);
}
.theme-card__bar {
  height: 6px;
}
.theme-card__dot {
  position: absolute;
  inset-inline-end: var(--s-3);
  top: var(--s-3);
  width: 12px;
  height: 12px;
  border-radius: 50%;
}
.theme-card__mode {
  font-family: var(--font-mono);
  font-size: var(--t-50);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  opacity: 0.75;
}
.theme-card__name {
  font-family: var(--font-mono);
  font-size: var(--t-75);
  font-weight: 700;
  color: var(--paper);
  text-transform: uppercase;
  letter-spacing: 0.18em;
}

/* ==================================================================
   FLASH — instrument-panel banner, matches the system
   ================================================================== */
.flash {
  padding: var(--s-2) var(--pad);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-bottom: var(--bw-1) solid var(--line);
}
.flash-notice {
  color: var(--ink);
  background: var(--green);
}
.flash-alert {
  color: var(--paper);
  background: var(--red);
}

/* ==================================================================
   LICENSE TICKET — gold standard-tier ticket artefact ported from
   the desktop app's LicenseTicket.svelte (standard tier only).
   Fixed 1100×380 design canvas; csc_site.js#mountLicenseTickets
   scales the inner card via CSS transform: scale(--lt-scale) to fit
   whatever container it's dropped into. Shared partial drops a
   single ticket into /buy + the home page § 04.

   Standard-tier palette is baked in (cream paper + gold accent +
   triple-ring frame) — themes / page colours don't reach the ticket;
   it's always its own showroom. Mirrors the desktop app's tier
   tokens (--lt-paper / --lt-ink / --lt-muted / --lt-accent / --lt-frame).
   ================================================================== */
.lt-wrapper {
  position: relative;
  width: 100%;
  max-width: 1100px;
  /* Default before JS: assume 100% fit until ResizeObserver runs. */
  aspect-ratio: 1100 / 380;
  overflow: hidden;
  /* Printed-artefact artwork: fixed pixel composition (perforation,
     holo seal, serial edges) that must not mirror under RTL locales. */
  direction: ltr;
  /* Set by JS each layout pass; CSS fallback for no-JS. */
  --lt-scale: 1;
}
.lt-card {
  /* Tier-standard palette, baked in (don't follow page theme). */
  --lt-paper: #f4ecd2;
  --lt-ink: #16140c;
  --lt-muted: #8a7a44;
  --lt-accent: #c8961c;
  --lt-frame:
    inset 0 0 0 1px rgb(200 150 28 / 0.45), inset 0 0 0 6px var(--lt-paper),
    inset 0 0 0 7px rgb(200 150 28 / 0.4);

  position: relative;
  overflow: hidden;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", monospace;
  color: var(--lt-ink);
  background: var(--lt-paper);
  box-shadow: var(--lt-frame);
  isolation: isolate;
  transform: scale(var(--lt-scale, 1));
  transform-origin: top left;
}
@media (min-width: 881px) {
  /* Desktop hero: render the ticket full-size so it bleeds partially off the
     right edge. Mobile (the base rule) keeps overflow hidden so it fits. */
  .lt-wrapper {
    overflow: visible;
  }
  /* RTL: the "bleed off the right edge" flourish is an LTR composition. Under
     dir="rtl" the grid mirrors the ticket column to the left, but the ticket
     is a fixed LTR artefact (direction: ltr above) that must not flip, so it
     bleeds off the LEFT edge instead and clips the hero key. Keep the RTL
     ticket contained so the JS scaler fits the whole face into the column,
     matching the desktop app's scaled-to-fit ticket. */
  [dir="rtl"] .lt-wrapper {
    overflow: hidden;
  }
}

/* Overlays */
.lt-guilloche {
  position: absolute;
  inset: 0;
  color: var(--lt-accent);
  pointer-events: none;
  opacity: 0.06;
}
.lt-watermark {
  position: absolute;
  inset: 0;
  color: var(--lt-accent);
  pointer-events: none;
  mix-blend-mode: multiply;
  opacity: 0.08;
}
.lt-shimmer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    115deg,
    transparent 35%,
    rgb(255 235 170 / 0.45) 50%,
    transparent 65%
  );
  mix-blend-mode: overlay;
  animation: lt-shimmer 7000ms ease-in-out infinite;
}
@keyframes lt-shimmer {
  0% {
    opacity: 0;
    transform: translateX(-60%);
  }
  20% {
    opacity: 1;
  }
  80% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translateX(60%);
  }
}

/* Vertical edges (serial codes) */
.lt-edge {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  font-size: 10px;
  color: var(--lt-muted);
  letter-spacing: 0.32em;
}
.lt-edge-left {
  left: 0;
  border-right: 1px dashed color-mix(in srgb, var(--lt-muted) 67%, transparent);
}
.lt-edge-right {
  right: 0;
  border-left: 1px dashed color-mix(in srgb, var(--lt-muted) 67%, transparent);
}
.lt-edge-text {
  white-space: nowrap;
  transform: rotate(-90deg);
}
.lt-edge-right .lt-edge-text {
  transform: rotate(90deg);
}

/* Body */
.lt-body {
  position: absolute;
  inset: 0 320px 0 56px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--s-4) var(--s-4) var(--s-4) 0;
}
.lt-body-top {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  justify-content: space-between;
}
.lt-brand-line {
  font-size: 0.625rem;
  font-weight: 500;
  color: var(--lt-muted);
  letter-spacing: 0.28em;
}
.lt-brand-serial {
  margin-top: 4px;
  font-size: 0.625rem;
  color: var(--lt-muted);
  letter-spacing: 0.32em;
}
.lt-tier-badge {
  display: inline-flex;
  gap: var(--s-2);
  align-items: center;
  padding: var(--s-2) var(--s-3);
  font-size: 0.875rem;
  font-weight: 800;
  color: var(--lt-accent);
  letter-spacing: 0.32em;
  white-space: nowrap;
  background: var(--lt-ink);
}
.lt-tier-diamond {
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--lt-accent);
  transform: rotate(45deg);
}

/* Hero key */
.lt-key-zone {
  margin-top: -6px;
}
.lt-key-row {
  display: flex;
  align-items: center;
}
.lt-key-marquee {
  display: flex;
  align-items: center;
  height: 56px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 3.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--lt-ink);
  letter-spacing: 0.08em;
  white-space: nowrap;
}

/* Body bottom row */
.lt-body-bottom {
  display: flex;
  gap: var(--s-5);
  align-items: flex-end;
}
.lt-meta-col {
  min-width: 0;
}
.lt-meta-label {
  font-size: 0.5625rem;
  color: var(--lt-muted);
  letter-spacing: 0.3em;
}
.lt-meta-value {
  margin-top: 4px;
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--lt-ink);
  letter-spacing: 0.06em;
}
.lt-meta-spacer {
  flex: 1;
}
.lt-countdown {
  display: flex;
  gap: var(--s-3);
  align-items: flex-end;
}
.lt-countdown-num {
  font-family:
    "Big Shoulders Display", Oswald, "Helvetica Neue Condensed", "Arial Narrow", sans-serif;
  font-size: 6.875rem;
  font-weight: 800;
  line-height: 0.82;
  color: var(--lt-ink);
  letter-spacing: -0.04em;
}
.lt-countdown-num.is-perpetual {
  display: flex;
  align-items: flex-end;
  height: 90px;
  margin-bottom: -0.16em;
  overflow: visible;
  font-size: 12rem;
  line-height: 1;
  transform: translateY(0.16em);
}
.lt-countdown-side {
  padding-bottom: 8px;
  padding-left: 16px;
  border-left: 1px solid var(--lt-muted);
}
.lt-countdown-line {
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.22em;
}
.lt-countdown-sub {
  margin-top: 4px;
  font-size: 0.5625rem;
  color: var(--lt-muted);
  text-transform: uppercase;
  letter-spacing: 0.28em;
}

/* Holographic seal at the perforation. Three-layer foil patch:
   conic rainbow base + diagonal specular sweep + embossed CSC mark.
   The perforation runs through it so the brand reads as protected. */
.lt-holo {
  position: absolute;
  top: 188px;
  left: 744px;
  z-index: 2;
  width: 72px;
  height: 72px;
  overflow: hidden;
  background: linear-gradient(160deg, #e8e4d4 0%, #c7c3b6 100%);
  border-radius: 4px;
  box-shadow:
    0 0.5px 0 rgb(20 18 12 / 0.18),
    inset 0 1px 0 rgb(255 255 255 / 0.55),
    inset 0 -1px 0 rgb(20 18 12 / 0.18);
  isolation: isolate;
}
.lt-holo-rainbow {
  position: absolute;
  inset: 0;
  background: conic-gradient(
    from 35deg,
    #ffbe7e 0deg,
    #ffe39a 60deg,
    #f3d8a0 120deg,
    #c8e3ff 180deg,
    #e0c4ff 240deg,
    #ffbe7e 360deg
  );
  mix-blend-mode: multiply;
  filter: saturate(1.1) brightness(1.05);
}
.lt-holo-shimmer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    110deg,
    transparent 30%,
    rgb(255 255 255 / 0.35) 45%,
    rgb(255 255 255 / 0.55) 50%,
    rgb(255 255 255 / 0.35) 55%,
    transparent 70%
  );
  mix-blend-mode: overlay;
}
.lt-holo-mark {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 66%;
  height: 66%;
  color: rgb(255 255 255 / 0.55);
  mix-blend-mode: soft-light;
  filter: drop-shadow(0 -0.5px 0 rgb(255 255 255 / 0.5)) drop-shadow(0 0.5px 0 rgb(20 18 12 / 0.28));
  transform: translate(-50%, -50%);
}

/* Perforation — dashed vertical, notches at top + bottom */
.lt-perf {
  position: absolute;
  top: 8px;
  bottom: 8px;
  left: 780px;
  z-index: 3;
  width: 0;
  border-left: 1.5px dashed color-mix(in srgb, var(--lt-muted) 60%, transparent);
}
.lt-perf-notch {
  position: absolute;
  left: -5px;
  width: 10px;
  height: 10px;
  background: var(--bg);
  border-radius: 50%;
}
.lt-perf-notch-top {
  top: -10px;
}
.lt-perf-notch-bottom {
  bottom: -10px;
}

/* Stub */
.lt-stub {
  position: absolute;
  inset: 0 38px 0 780px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--s-4) var(--s-4) var(--s-4) var(--s-5);
}
.lt-stub-label {
  font-size: 0.625rem;
  color: var(--lt-muted);
  letter-spacing: 0.28em;
}
.lt-stub-expires {
  margin-top: 4px;
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* VALID seal with curved text */
.lt-seal {
  position: relative;
  display: flex;
  align-items: center;
  align-self: center;
  justify-content: center;
  width: 130px;
  height: 130px;
}
.lt-seal-svg {
  position: absolute;
  inset: 0;
  color: var(--lt-accent);
}
.lt-seal-center {
  position: relative;
  z-index: 1;
  color: var(--lt-ink);
  text-align: center;
}
.lt-seal-label {
  font-family: "Big Shoulders Display", Oswald, "Helvetica Neue Condensed", sans-serif;
  font-size: 1.875rem;
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0.08em;
}
.lt-seal-sub {
  margin-top: 4px;
  font-size: 0.5625rem;
  color: var(--lt-muted);
  letter-spacing: 0.28em;
}

/* Devices column */
.lt-devices-header {
  padding-bottom: 4px;
  font-size: 0.5625rem;
  color: var(--lt-muted);
  letter-spacing: 0.28em;
  border-bottom: 1px dashed color-mix(in srgb, var(--lt-muted) 40%, transparent);
}
.lt-device-row {
  display: flex;
  gap: var(--s-2);
  align-items: baseline;
  padding-top: 4px;
  font-size: 0.625rem;
  letter-spacing: 0.14em;
}
.lt-device-marker {
  font-weight: 700;
  color: var(--lt-accent);
}
.lt-device-name {
  font-weight: 700;
  color: var(--lt-ink);
}
.lt-device-meta {
  margin-left: auto;
  color: var(--lt-muted);
}

@media (prefers-reduced-motion: reduce) {
  .lt-shimmer {
    animation: none;
  }
}

/* ==================================================================
   MOBILE HARDENING (≤620px) — phones, edge-to-edge correctness.
   Layered after the design system: the source layouts target desktop
   first; these rules guarantee no horizontal overflow on small screens
   (nav CTA, intro chrome, ticket) without altering desktop output.
   ================================================================== */
@media (max-width: 620px) {
  /* Nav: keep brand short + CTA fully on-screen */
  .nav {
    gap: var(--s-2);
  }
  .nav__name {
    font-size: var(--t-50);
    letter-spacing: 0.12em;
  }
  .nav .btn {
    padding: var(--s-2);
    font-size: var(--t-50);
  }

  /* Intro chrome: progress + skip wrap instead of pushing width */
  .intro__frame {
    padding-right: var(--s-3);
    padding-left: var(--s-3);
  }
  .intro__split {
    padding: var(--s-3) 0;
  }

  /* Ticket: never wider than the viewport */
  .intro__right {
    width: 100%;
    min-width: 0;
  }
  .ticket {
    width: 100%;
    max-width: 100% !important;
    padding: var(--s-4);
  }

  /* Origin headline holds a long unbreakable URL — let it wrap */
  .origin__title,
  .origin__title a {
    overflow-wrap: anywhere;
  }

  /* Cameras index: filter row (buttons + meta) wraps instead of overflowing */
  .cam-index__filter-wrap {
    flex-wrap: wrap;
    gap: var(--s-2);
  }
  .cam-index .cam-filter {
    flex-wrap: wrap;
  }
}

/* ==================================================================
   Section primitives + privacy band — promoted from /buy's inline
   style so the dark "Stays on your machine" band can also render on
   the home page. .b-section / .b-rule stay shared across both.
   ================================================================== */
.b-section {
  padding: clamp(64px, 9vw, 144px) var(--pad);
}
.b-rule {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--s-3);
  align-items: baseline;
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-7);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  border-bottom: var(--bw-1) solid var(--line);
}
.b-rule .num {
  color: var(--accent);
}
.b-rule--dark {
  color: rgb(242, 237, 226, 0.5);
  border-bottom-color: rgb(242, 237, 226, 0.18);
}
.b-rule--dark .num {
  color: var(--paper);
}
.b-inline-link {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  padding-bottom: 2px;
  font-weight: 600;
  color: var(--accent);
  border-bottom: var(--bw-2) solid var(--accent);
}
.b-inline-link--dark {
  color: var(--paper);
  border-bottom-color: var(--paper);
}
.b-privacy {
  color: var(--paper);
  background: var(--surface-dark);
}
.b-privacy__head {
  margin: 0 0 var(--s-7);
  font-size: clamp(48px, 8vw, 132px);
  font-weight: 900;
  line-height: 0.88;
  color: var(--paper);
  letter-spacing: -0.04em;
  text-wrap: balance;
}
.b-privacy__head .accent {
  color: var(--accent-pop);
}
/* Headline full-width, then copy beside the real Privacy settings
   screen. The transparent window's native shadow reads on the dark
   band, so no extra frame is needed. */
.b-privacy__grid {
  display: grid;
  grid-template-columns: 1.02fr 0.98fr;
  gap: clamp(32px, 5vw, 80px);
  align-items: center;
}
.b-privacy__cols {
  display: grid;
  gap: var(--s-5);
}
.b-privacy__cols p {
  margin: 0;
  font-size: var(--t-200);
  line-height: 1.55;
  color: rgb(242, 237, 226, 0.78);
}
.b-privacy__shot {
  margin: 0;
}
.b-privacy__img {
  display: block;
  width: 100%;
  height: auto;
}
@media (max-width: 880px) {
  .b-privacy__grid {
    grid-template-columns: 1fr;
  }
}

/* ==================================================================
   DEBUG CONSOLE — operator-only floating tool (admin@…). Rendered only
   when admin_debugger?. Deliberately dark + mono so it reads as
   instrumentation sitting on top of the site, never part of it.
   ================================================================== */
.dbgc__fab {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-4);
  z-index: 1100;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--s-7);
  height: var(--s-7);
  color: var(--paper);
  cursor: pointer;
  background: var(--ink);
  border: var(--bw-2) solid var(--accent);
  border-radius: 4px;
  box-shadow: 0 2px 12px rgb(17, 17, 17, 0.28);
  transition:
    color var(--t150) var(--ease),
    transform var(--t150) var(--ease);
}
.dbgc__fab:hover,
.dbgc__fab:focus-visible {
  color: var(--accent);
  outline: none;
  transform: translateY(-1px);
}
.dbgc--open .dbgc__fab {
  color: var(--accent);
}

.dbgc__panel {
  position: fixed;
  right: var(--s-4);
  bottom: calc(var(--s-4) + var(--s-7) + var(--s-2));
  z-index: 1100;
  width: min(360px, calc(100vw - var(--s-6)));
  max-height: min(78vh, 760px);
  overflow-y: auto;
  color: var(--paper);
  pointer-events: none;
  background: var(--ink-2);
  border: var(--bw-2) solid var(--accent);
  border-radius: 6px;
  box-shadow: 0 12px 40px rgb(0, 0, 0, 0.4);
  opacity: 0;
  transform: translateY(10px) scale(0.98);
  transform-origin: bottom right;
  transition:
    opacity var(--t150) var(--ease),
    transform var(--t150) var(--ease);
}
.dbgc--open .dbgc__panel {
  pointer-events: auto;
  opacity: 1;
  transform: translateY(0) scale(1);
}

.dbgc__head {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-2) var(--s-3);
  background: var(--ink-0);
  border-bottom: var(--bw-1) solid rgb(242, 237, 226, 0.16);
}
.dbgc__title {
  font-size: var(--t-75);
  color: var(--accent);
  letter-spacing: 0.22em;
}
.dbgc__x {
  padding: var(--s-1);
  font-size: var(--t-200);
  line-height: 1;
  color: var(--paper-2);
  cursor: pointer;
  background: none;
  border: 0;
}
.dbgc__x:hover {
  color: var(--accent);
}

.dbgc__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-3);
}

.dbgc__sec {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-bottom: var(--s-3);
  border-bottom: var(--bw-1) solid rgb(242, 237, 226, 0.12);
}
.dbgc__sec:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}
.dbgc__sec-h {
  font-size: var(--t-50);
  color: var(--paper-2);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  opacity: 0.7;
}
.dbgc__readout {
  padding: var(--s-2);
  font-size: var(--t-75);
  color: var(--paper);
  letter-spacing: 0.06em;
  background: var(--ink-0);
  border: var(--bw-1) solid rgb(242, 237, 226, 0.14);
  border-radius: 3px;
}
.dbgc__readout strong {
  color: var(--accent);
}

.dbgc__select {
  width: 100%;
  padding: var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--paper);
  cursor: pointer;
  background: var(--ink-0);
  border: var(--bw-1) solid rgb(242, 237, 226, 0.24);
  border-radius: 3px;
}
.dbgc__select:focus {
  outline: none;
  border-color: var(--accent);
}

.dbgc__btn {
  display: inline-block;
  width: 100%;
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-75);
  color: var(--ink);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  background: var(--accent);
  border: var(--bw-2) solid var(--accent);
  border-radius: 3px;
}
.dbgc__btn:hover {
  color: var(--ink);
  filter: brightness(1.08);
}

.dbgc__reset {
  font-size: var(--t-50);
  color: var(--paper-2);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.dbgc__reset:hover {
  color: var(--accent);
}

.dbgc__hint {
  font-size: var(--t-50);
  line-height: 1.5;
  color: var(--paper-2);
  letter-spacing: 0.04em;
  opacity: 0.7;
}
.dbgc__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1);
}
.dbgc__chip {
  padding: var(--s-1) var(--s-2);
  font-size: var(--t-50);
  color: var(--paper);
  letter-spacing: 0.04em;
  background: var(--ink-0);
  border: var(--bw-1) solid rgb(242, 237, 226, 0.2);
  border-radius: 999px;
}
.dbgc__chip:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.dbgc__form {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.dbgc__sec--info {
  gap: var(--s-1);
  font-size: var(--t-50);
}
.dbgc__sec--info > div {
  display: flex;
  gap: var(--s-2);
  justify-content: space-between;
}
.dbgc__sec--info span {
  color: var(--paper-2);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  opacity: 0.7;
}
.dbgc__sec--info strong {
  font-weight: 600;
  color: var(--paper);
  overflow-wrap: anywhere;
}

@media (max-width: 600px) {
  .dbgc__fab {
    right: var(--s-3);
    bottom: var(--s-3);
  }
  .dbgc__panel {
    right: var(--s-3);
    bottom: calc(var(--s-3) + var(--s-7) + var(--s-2));
  }
}

/* ==================================================================
   RTL (Arabic, Hebrew) — the layout flips via <html dir="rtl"> plus the
   logical properties used throughout. The rules here cover what logical
   properties can't express: directional glyphs and Arabic / Hebrew
   script typography. The license ticket (.lt-wrapper) and the debug
   console stay LTR on purpose — printed-artefact artwork and operator
   instrumentation keep their composition, mirroring the desktop app's
   "data instruments stay LTR" rule.
   ================================================================== */

/* Directional arrows and chevrons point with the reading direction. */
[dir="rtl"] .arr .ph-icon,
[dir="rtl"] .dl-cell__models-chevron {
  transform: scaleX(-1);
}
[dir="rtl"] .btn:hover .arr,
[dir="rtl"] .linkline a:hover .arr {
  transform: translateX(-3px);
}
[dir="rtl"] .cam-row:hover .cam-row__open .arr {
  transform: translateX(-3px);
}

/* Letterspacing is wrong for both RTL scripts the site ships: Arabic is
   cursive (tracking pulls joined letterforms apart) and tracked Hebrew
   disrupts word recognition (neither has uppercase, so the design
   system's letterspaced uppercase labels carry no meaning there). Reset
   tracking to normal for both. Latin tokens embedded in these pages lose
   their tracking too — a deliberate trade; the page must read natively first. */
html[lang="ar"] *,
html[lang="he"] * {
  letter-spacing: normal !important;
}

/* In the mono stack, Arabic falls through JetBrains Mono (no Arabic
   glyphs) to the generic monospace family, whose Arabic is fixed-pitch
   with DISCONNECTED letterforms — unreadable. Insert joining Arabic
   faces (macOS / Windows / Noto) ahead of the monospace fallback;
   Latin and digits still resolve to JetBrains Mono first. */
html[lang="ar"] {
  --font-mono:
    "JetBrains Mono", "Geeza Pro", "Segoe UI", "Noto Naskh Arabic", "Noto Sans Arabic",
    ui-monospace, "SFMono-Regular", Menlo, monospace;
}

/* JetBrains Mono carries no Hebrew glyphs, so Hebrew in a mono context
   falls to the generic monospace family. Hebrew is non-joining, so it
   stays legible there, but a real Hebrew face reads far better; insert
   system Hebrew faces ahead of the monospace fallback. Latin and digits
   (Hebrew uses Latin numerals) still resolve to JetBrains Mono first. */
html[lang="he"] {
  --font-mono:
    "JetBrains Mono", "Arial Hebrew", "Segoe UI", "Noto Sans Hebrew", ui-monospace,
    "SFMono-Regular", Menlo, monospace;
}
