/*
 * Fitoutly — fitoutly.com
 *
 * Two references, deliberately mixed:
 *  - laszlodesign.hu supplies the ground: near-black, Playfair display type at a
 *    light weight over Inter, generous line height. Same house.
 *  - revolut.com supplies the rhythm: one idea per section, pill call-to-action,
 *    12px cards, long scroll.
 *
 * The accent is Fitoutly's emerald, not the studio's brass — the app's own
 * accent and logo gradient are built on it, so site and product match.
 */

:root {
  --bg: #0a0a0a;
  --bg-raised: #121212;
  --bg-card: #161616;
  --text: #ededed;
  --text-dim: #a1a1a1;
  --text-faint: #6b6b6b;

  --accent: #0d9488;
  --accent-bright: #14b8a6;
  --accent-pale: #5eead4;

  --line: rgba(255, 255, 255, 0.09);

  /* Two radii only — pill for actions, 12px for surfaces. */
  --r-pill: 9999px;
  --r-card: 12px;

  --measure: 62ch;
  --gutter: clamp(20px, 5vw, 64px);
  --section-y: clamp(72px, 12vh, 152px);

  --font-body: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
}

*,
*::before,
*::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* Fixed mesh backdrop, behind every section. Cards and media wells have their
   own solid grounds, so text never sits on a moving line. */
#meshCanvas {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a { color: inherit; }

.wrap {
  width: 100%;
  max-width: 1180px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---------- type ---------- */

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;      /* light display weight — the studio's signature */
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0;
}

h1 { font-size: clamp(2.6rem, 6.5vw, 4.6rem); }
h2 { font-size: clamp(2rem, 4.2vw, 3rem); }
h3 { font-size: 1.25rem; font-family: var(--font-body); font-weight: 600; letter-spacing: 0; }

p { margin: 0 0 1.1em; max-width: var(--measure); }

.lede { font-size: clamp(1.05rem, 1.8vw, 1.3rem); color: var(--text-dim); }

.eyebrow {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin: 0 0 1.1rem;
}

/* ---------- glass ----------
 *
 * Sparingly: the header, and panels that float over the hero. Glass over a flat
 * background is a grey box — it only reads as glass when something moves behind
 * it. See BRAND.md §5 for the rules that are not obvious from the code.
 */

.glass {
  background: rgba(18, 18, 18, 0.62);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--r-card);
  /* Bright inner hairline = a glass edge catching light from above; the outer
     shadow lifts the panel off the page. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 18px 46px rgba(0, 0, 0, 0.55);
}

.glass--emerald {
  background: rgba(13, 148, 136, 0.16);
  border-color: rgba(94, 234, 212, 0.22);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}

/* Firefox with backdrop-filter disabled, and older Androids, render the rule
   above as a 62%-transparent panel with no blur — text over text. Opaque
   fallback, not a nicety. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: rgba(18, 18, 18, 0.92); }
  .glass--emerald { background: rgba(11, 61, 56, 0.94); }
  .site-header { background: rgba(10, 10, 10, 0.96); }
}

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  background: rgba(10, 10, 10, 0.72);
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s ease;
}
.site-header[data-scrolled='true'] { border-bottom-color: var(--line); }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 68px;
}

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; }
/* Two drawn SVGs, not mark + font — heights tuned so the wordmark's x-height
   sits on the mark's optical centre. */
.brand__mark { height: 30px; width: auto; }
.brand__word { height: 16px; width: auto; }

.site-nav { display: flex; align-items: center; gap: 6px; }
/* Menu labels never wrap — "How it works" on two lines reads as a bug. */
.site-nav a { white-space: nowrap; }

/* Language picker + hamburger, grouped so both stay reachable on a phone while
   the nav itself collapses into the drawer. */
.site-header__tools { display: flex; align-items: center; gap: 10px; margin-left: 14px; }

/* Native <details> on purpose: keyboard and screen-reader behaviour for free.
   JS only adds closing on Escape and on an outside click. */
.lang { position: relative; }
.lang > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  transition: color 0.18s ease, border-color 0.18s ease;
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary::after {
  content: '';
  width: 5px;
  height: 5px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.18s ease;
}
.lang > summary:hover { color: var(--text); border-color: rgba(255, 255, 255, 0.2); }
.lang[open] > summary { color: var(--text); border-color: rgba(255, 255, 255, 0.2); }
.lang[open] > summary::after { transform: translateY(1px) rotate(-135deg); }

.lang__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 170px;
  padding: 6px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.55);
  z-index: 30;
}
.lang__menu a {
  display: block;
  padding: 9px 12px;
  border-radius: 8px;
  text-decoration: none;
  font-size: 0.95rem;
  color: var(--text-dim);
  white-space: nowrap;
}
.lang__menu a:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }
.lang__menu a[aria-current='page'] { color: var(--accent-pale); font-weight: 600; }

/* ---------- mobile menu ----------
 * Below the breakpoint the links become a drawer under the header. The old rule
 * simply hid them, which left a phone with no way to reach any page but the one
 * it landed on. */

.nav-toggle {
  display: none;
  position: relative;
  width: 44px;
  height: 44px;           /* 44px: the smallest comfortable touch target */
  padding: 0;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
}
/* Three bars from one element: the middle is the span, the outer two are its
   pseudo-elements — so the X animation has nothing extra to keep in sync. */
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  position: absolute;
  left: 50%;
  width: 18px;
  height: 2px;
  margin-left: -9px;
  background: var(--text);
  border-radius: 2px;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle span { top: 50%; margin-top: -1px; }
.nav-toggle span::before { content: ''; left: 0; margin-left: 0; transform: translateY(-6px); }
.nav-toggle span::after  { content: ''; left: 0; margin-left: 0; transform: translateY(6px); }

.nav-toggle[aria-expanded='true'] span { opacity: 0; }
.nav-toggle[aria-expanded='true'] span::before { transform: rotate(45deg); opacity: 1; }
.nav-toggle[aria-expanded='true'] span::after  { transform: rotate(-45deg); opacity: 1; }

@media (max-width: 900px) {
  .nav-toggle { display: block; }
  /* The picker keeps its place beside the hamburger; only the nav collapses. */
  .site-header__tools { margin-left: auto; }

  .site-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 10px clamp(20px, 5vw, 64px) 20px;
    background: rgba(10, 10, 10, 0.98);
    border-bottom: 1px solid var(--line);
    /* Collapsed by default, and unreachable by keyboard while collapsed. */
    display: none;
  }
  .site-nav[data-open='true'] { display: flex; }

  .site-nav a:not(.btn) {
    display: block;
    font-size: 1.02rem;
    padding: 13px 4px;
    border-radius: 8px;
    color: var(--text);
  }
  .site-nav a:not(.btn)[aria-current='page'] { color: var(--accent-pale); }
  .site-nav .btn { margin-top: 10px; width: 100%; }
}

/* `:not(.btn)` matters: without it this rule outranks .btn--primary on
   specificity and repaints the header's call-to-action in dim grey on emerald,
   which measures 1.45:1 — unreadable. */
.site-nav a:not(.btn) {
  text-decoration: none;
  color: var(--text-dim);
  font-size: 0.95rem;
  padding: 8px 12px;
  border-radius: var(--r-pill);
  transition: color 0.18s ease, background 0.18s ease;
}
.site-nav a:not(.btn):hover,
.site-nav a:not(.btn):focus-visible { color: var(--text); background: rgba(255, 255, 255, 0.06); }

/* The rule that used to live here hid the nav links outright below 720px. It is
   gone: the drawer above replaces it, and it would have overridden the drawer's
   `display: block` at that width anyway. */

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 26px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  /* .btn started life on <a> only; a native <button> brings the UA's white
     buttonface with it, which lit the cookie bar's Decline up like a bulb. */
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.98rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease;
}
.btn:active { transform: translateY(1px); }

.btn--primary {
  background: linear-gradient(180deg, var(--accent-bright), var(--accent));
  color: #04211e;
  font-weight: 600;
}
.btn--primary:hover { background: linear-gradient(180deg, var(--accent-pale), var(--accent-bright)); }

.btn--ghost { border-color: var(--line); color: var(--text); }
.btn--ghost:hover { background: rgba(255, 255, 255, 0.06); border-color: rgba(255, 255, 255, 0.2); }

/* ---------- hero ---------- */

.hero { padding-block: 0 var(--section-y); }
.hero h1 { margin-bottom: 0.55em; }
.hero .lede { margin-bottom: 2rem; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 3.5rem; }
.hero__note { font-size: 0.86rem; color: var(--text-faint); margin: 0.9rem 0 0; }

/* ---------- hero backdrop ----------
 *
 * `.hero__top` is the band: full-bleed sideways, but only as tall as the copy
 * inside it. Height by content, not a fixed value — the band then cannot reach
 * the product screenshot no matter how the type reflows. */

/* Padding kept tight on purpose: the band's height is copy + padding, and the
   clip is encoded at the band's aspect (1280×528 ≈ 2.42:1). Loose padding makes
   the band taller than that ratio, and `cover` answers by scaling the video up —
   which is exactly what made the first version look soft. */
.hero__top {
  position: relative;
  overflow: hidden;
  padding-block: clamp(22px, 3vh, 34px);
  margin-bottom: clamp(36px, 6vh, 64px);
}

/* Pinning. Only where the clip is actually scrubbed: on touch it loops, and
   200vh of pinned emptiness on a phone would be a bug, not an effect. */
@media (min-width: 901px) and (prefers-reduced-motion: no-preference) {
  .hero__pin { min-height: 210vh; }
  .hero__top {
    position: sticky;
    /* Clears the sticky header (min-height 68px). */
    top: 68px;
    margin-bottom: 0;
  }
}
.hero__top > .wrap { position: relative; z-index: 1; }

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  /* The poster carries the frame before the file arrives, and stays if it never
     does — the band is never an empty black box. */
  background: #0d0f10 center / cover no-repeat url('/assets/hero-still.webp');
}
.hero__bg video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.hero__bg video.is-ready { opacity: 1; }

/* Layer one: darkens the whole clip. The footage is bright — sunlit concrete and
   sky — and the veil is what lets it sit under a dark page without shouting. */
.hero__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(10, 10, 10, 0.9) 0%, rgba(10, 10, 10, 0.35) 22%, rgba(10, 10, 10, 0.4) 70%, var(--bg) 100%),
    rgba(10, 10, 10, 0.42);
}

/* Layer two: the scrim behind the words. 70% black — at 30% the lede measures
   1.8:1 against white concrete, which is unreadable. With the veil beneath it
   this clears 4.5:1 on the brightest frame. */
.hero__copy {
  position: relative;
  max-width: 46rem;
  padding: clamp(24px, 3.5vw, 38px) clamp(20px, 3.5vw, 36px);
  background: rgba(0, 0, 0, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: var(--r-card);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.hero__copy .lede { color: #d6d6d6; }
.hero__copy .hero__actions { margin-bottom: 0; }

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero__copy { background: rgba(0, 0, 0, 0.82); }
}

.hero__media {
  position: relative;
  border-radius: var(--r-card);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--bg-raised);
  aspect-ratio: 16 / 9;
}
.hero__media picture,
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* The looping app clip. `contain` rather than `cover`: this is a screen
   recording, and cropping a UI cuts off the very controls it is demonstrating.
   The well is already 16:9 and so is the clip, so nothing letterboxes. */
.hero__media--clip { background: #0d0f10; }
.hero__clip {
  position: static;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 1;
}
/* The `.hero__media video { opacity: 0 }` pair that used to live here belonged
   to the CDN hero video, which no longer exists — nothing sets `.is-playing`
   any more. Left in place it beat `.hero__clip` on specificity and rendered the
   app clip completely invisible. */

/* ---------- sections ---------- */

section { padding-block: var(--section-y); }
section + section { border-top: 1px solid var(--line); }
section + .section--photo,
.section--photo + section { border-top: none; }

.section-head { margin-bottom: clamp(32px, 5vh, 56px); }
.section-head--flush { margin-bottom: 0; }

/* Photography behind a glass heading panel. Body copy stays on a solid surface
   (BRAND §5: never body on glass; max two glass layers with the sticky header). */
.section--photo {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.section-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.section-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.section-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(10, 10, 10, 0.55) 0%,
    rgba(10, 10, 10, 0.72) 45%,
    rgba(10, 10, 10, 0.92) 100%
  );
}
.section--photo > .wrap {
  position: relative;
  z-index: 1;
}
.section-panel {
  display: inline-block;
  max-width: min(100%, 52rem);
  padding: 22px 26px;
  margin-bottom: clamp(24px, 4vh, 40px);
}
.section-panel .section-head { margin-bottom: 0; }
.section-panel h2 { max-width: 22ch; }
.section-copy {
  max-width: var(--measure);
  padding: 22px 26px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
.section-copy .lede:last-child { margin-bottom: 0; }

/* Real product screenshots — solid frames, not glass. */
.shot {
  margin: 0 0 clamp(28px, 4vh, 48px);
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  background: var(--bg-raised);
  overflow: hidden;
}
.shot img { width: 100%; height: auto; }
.shot figcaption {
  padding: 14px 18px 16px;
  font-size: 0.92rem;
  color: var(--text-dim);
  border-top: 1px solid var(--line);
  background: var(--bg-card);
}

.notice-panel {
  margin-top: clamp(28px, 4vh, 48px);
  padding: 26px;
  border-radius: var(--r-card);
  background: var(--bg-card);
  border: 1px solid rgba(20, 184, 166, 0.45);
}
.notice-panel h3 {
  margin: 0 0 0.7rem;
  font-size: 1.15rem;
}
.notice-panel p {
  color: var(--text-dim);
  max-width: var(--measure);
}
.notice-panel p:last-child { margin-bottom: 0; }

/* Comparison — solid surface, not glass (same rule as pricing). */
.compare {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
}
.compare__row {
  display: grid;
  grid-template-columns: minmax(8rem, 1.2fr) 1fr 1fr;
  gap: 12px 20px;
  padding: 1.15rem 1.5rem;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.compare__row:last-child { border-bottom: none; }
.compare__row--head {
  font-weight: 600;
  border-bottom-color: rgba(255, 255, 255, 0.2);
}
.compare__fitoutly { color: var(--accent-pale); }
.compare__label { color: var(--text-dim); font-size: 0.95rem; }
.compare__alt { color: var(--text-faint); font-size: 0.95rem; }

/* Four columns for the plan table: label + three plans. */
.compare__row--3 { grid-template-columns: minmax(8rem, 1.3fr) 1fr 1fr 1fr; }

@media (max-width: 720px) {
  .compare__row {
    grid-template-columns: 1fr;
    gap: 4px;
    padding: 1rem 1.15rem;
  }
  .compare__row--head { display: none; }
  .compare__label {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent-bright);
    margin-bottom: 0.2rem;
  }
  .compare__alt::before {
    content: 'vs ';
    color: var(--text-faint);
  }

  /* The two-column table collapses fine — with three plans there is no way to
     tell the cells apart once the header is gone, so this one keeps its header
     and scrolls sideways instead. Wide content scrolls in its own container;
     the page body never does. */
  .compare--plans { overflow-x: auto; }
  .compare--plans .compare__row--head { display: grid; }
  .compare--plans .compare__row {
    grid-template-columns: minmax(7rem, 1.2fr) repeat(3, minmax(5rem, 1fr));
    gap: 12px;
    min-width: 32rem;
  }
  .compare--plans .compare__label {
    font-size: 0.9rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--text-dim);
    margin-bottom: 0;
  }
  .compare--plans .compare__alt::before { content: none; }
}

/* ---------- product screenshots ---------- */

.shot {
  margin: clamp(28px, 5vh, 48px) 0 0;
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--bg-raised);
}
.shot img { width: 100%; height: auto; }
.shot figcaption {
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 0.92rem;
  max-width: var(--measure);
}

/* Section sub-heading — Inter, not the display serif: it labels a block, it
   does not open one. */
.subhead {
  margin: clamp(40px, 6vh, 64px) 0 20px;
  font-family: var(--font-body);
  font-size: 1.15rem;
  font-weight: 600;
}

/* Emerald aside for the one explanation that has to land. */
.notice-panel {
  margin-top: clamp(28px, 5vh, 48px);
  padding: 26px 30px;
  border-radius: var(--r-card);
  border: 1px solid rgba(94, 234, 212, 0.22);
}
.notice-panel h3 { margin-bottom: 0.6rem; }
.notice-panel p { color: var(--text-dim); }
.notice-panel p:last-child { margin-bottom: 0; }

.grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

/* Fixed column counts where `auto-fit` would leave an orphan. With four cards it
   fits three and drops the fourth onto its own row; with five it leaves two.
   Both read as a mistake rather than a layout. */
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1080px) { .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .grid--4 { grid-template-columns: 1fr; } }

/* Five platforms: two columns, and the last one takes the full width so the
   final row is filled on purpose instead of half-empty by accident. */
.grid--platforms { grid-template-columns: repeat(2, 1fr); }
.grid--platforms > :last-child { grid-column: 1 / -1; }
@media (max-width: 560px) {
  .grid--platforms { grid-template-columns: 1fr; }
  .grid--platforms > :last-child { grid-column: auto; }
}

.card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 26px;
}
.card h3 { margin-bottom: 0.5rem; }
.card p { color: var(--text-dim); margin-bottom: 0; font-size: 0.97rem; }

.step__n {
  font-family: var(--font-display);
  font-size: 2.4rem;
  line-height: 1;
  color: var(--accent);
  margin-bottom: 0.6rem;
}

/* ---------- pricing ---------- */

.price-card { display: flex; flex-direction: column; }
.price-card--featured { border-color: rgba(20, 184, 166, 0.45); }

/* Scoped for the same reason as the amount below: `.card p` (0,1,1) outranks a
   bare class and repainted the badge label dim-grey on emerald — unreadable. */
.price-card .price-card__badge {
  align-self: flex-start;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #04211e;
  background: var(--accent-bright);
  padding: 4px 10px;
  border-radius: var(--r-pill);
  margin-bottom: 14px;
}

/* `.card p` (0,1,1) outranks a bare `.price-card__amount` (0,1,0) and was
   rendering the price at 15.5px in dim grey — the same size as the caption
   under it. Matched specificity, so the number reads as a number. */
.price-card .price-card__amount {
  font-family: var(--font-display);
  font-size: 3rem;
  line-height: 1;
  color: var(--text);
  margin: 0.35rem 0 0.15rem;
}
.price-card .price-card__period { color: var(--text-faint); font-size: 0.92rem; }

.price-card ul { list-style: none; padding: 0; margin: 1.4rem 0; display: grid; gap: 9px; }
.price-card li { position: relative; padding-left: 26px; color: var(--text-dim); font-size: 0.95rem; }

/* Free-tier limits: same list, but a dash instead of a tick. A green tick
   against "6 items per room" would read as a feature rather than a ceiling.
   Selector deliberately carries two classes: at equal specificity the tick rule
   below would win on source order alone. */
.price-card ul.price-card__limits { margin-bottom: 0.7rem; }
.price-card ul.price-card__limits li { color: var(--text-faint); }
.price-card ul.price-card__limits li::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 0.78em;
  width: 11px;
  height: 0;
  border: 0;
  border-top: 2px solid var(--text-faint);
  transform: none;
}

/* The one line that sells the card, under the list rather than inside it. */
.price-card__foot {
  margin: 0 0 1.2rem;
  font-size: 0.88rem;
  color: var(--text-faint);
}
.price-card li::before {
  content: '';
  position: absolute;
  left: 4px; top: 0.62em;
  width: 11px; height: 6px;
  border-left: 2px solid var(--accent-bright);
  border-bottom: 2px solid var(--accent-bright);
  transform: rotate(-45deg);
}
.price-card .btn { margin-top: auto; }

.price-note {
  margin-top: 28px;
  font-size: 0.88rem;
  color: var(--text-faint);
  max-width: var(--measure);
}

/* Footnote marker. Superscript so it does not sit on the baseline pretending to
   be punctuation, and it stays a real link so keyboard users reach the note. */
.fnref {
  font-size: 0.72em;
  vertical-align: super;
  line-height: 0;
  margin-left: 2px;
  color: var(--accent-bright);
  text-decoration: none;
}
.fnref:hover { text-decoration: underline; }

/* ---------- downloads ---------- */

.platform {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--bg-card);
}
.platform__name { font-weight: 600; }
.platform__meta { color: var(--text-faint); font-size: 0.86rem; }

/* ---------- legal / prose pages ---------- */

.legal { padding-block: clamp(48px, 8vh, 88px) var(--section-y); }
.legal .wrap { max-width: 780px; }

.legal h1 { font-size: clamp(2rem, 4.5vw, 3rem); margin-bottom: 0.5rem; }
.legal h2 { font-size: 1.35rem; font-family: var(--font-body); font-weight: 600; letter-spacing: 0; margin: 2.6rem 0 0.7rem; }
.legal h3 { font-size: 1.05rem; margin: 1.8rem 0 0.5rem; }
.legal p, .legal li { color: var(--text-dim); }
.legal ul, .legal ol { padding-left: 22px; margin: 0 0 1.1em; display: grid; gap: 7px; }
.legal a { color: var(--accent-pale); }

.legal__updated { color: var(--text-faint); font-size: 0.9rem; margin-bottom: 2.4rem; }

/* About page: text beside the portrait. A 4:5 crop with the studio background
   left in, on the card radius — a photograph, not an avatar. */
.about-intro { display: flex; gap: 36px; align-items: flex-start; }
.about-intro > div { flex: 1; min-width: 0; }
.about-portrait { flex: 0 0 auto; margin: 6px 0 0; }
.about-portrait img {
  width: 216px;
  height: 270px;
  object-fit: cover;
  border-radius: var(--r-card);
  border: 1px solid var(--line);
}
@media (max-width: 560px) {
  .about-intro { flex-direction: column-reverse; align-items: center; }
  .about-portrait img { width: 180px; height: 225px; }
}

.legal table { width: 100%; border-collapse: collapse; margin: 0 0 1.4em; font-size: 0.95rem; }
.legal th, .legal td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
.legal th { color: var(--text); font-weight: 600; }
.legal td { color: var(--text-dim); }

/* Unfilled entity details. Loud on purpose — these must not reach production. */
.todo {
  background: rgba(234, 179, 8, 0.14);
  border-bottom: 1px dashed rgba(234, 179, 8, 0.6);
  color: #fde68a;
  padding: 0 4px;
  border-radius: 3px;
  font-family: var(--font-body);
  font-weight: 600;
}

.notice {
  border: 1px solid rgba(234, 179, 8, 0.35);
  background: rgba(234, 179, 8, 0.07);
  border-radius: var(--r-card);
  padding: 18px 22px;
  margin-bottom: 2.4rem;
}
.notice p { margin-bottom: 0; color: #fde68a; font-size: 0.92rem; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 44px;
  color: var(--text-faint);
  font-size: 0.9rem;
}
.site-footer__inner { display: flex; flex-wrap: wrap; gap: 18px 32px; justify-content: space-between; }
.site-footer a { color: var(--text-dim); text-decoration: none; }
.site-footer a:hover { color: var(--text); }

/* ---------- cookie consent ----------
 * Full-width bottom bar, generic copy, Customise panel — but every control in
 * the panel maps to a cookie that actually exists here. Reject carries the
 * same visual weight as Accept; a Reject that hides is the pattern regulators
 * fine. */

.cookie-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 28px;
  padding: 18px clamp(20px, 4vw, 48px);
  background: rgba(10, 10, 10, 0.97);
  border-top: 1px solid var(--line);
  box-shadow: 0 -18px 46px rgba(0, 0, 0, 0.45);
}
.cookie-bar__text {
  font-size: 0.92rem;
  color: var(--text-dim);
  max-width: 64ch;
}
.cookie-bar__text strong { color: var(--text); }
.cookie-bar a { color: var(--accent-pale); }
.cookie-bar__actions { display: flex; gap: 10px; flex-wrap: wrap; }
.cookie-bar__actions .btn { padding: 9px 20px; font-size: 0.92rem; }

/* Preferences panel */
.cookie-modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.6);
}
.cookie-modal__panel {
  width: 100%;
  max-width: 560px;
  max-height: min(80vh, 640px);
  overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 26px 28px;
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.55);
}
.cookie-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.cookie-modal__head h3 { margin: 0; }
.cookie-modal__close {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}
.cookie-modal__close:hover { color: var(--text); }
.cookie-modal__intro { font-size: 0.92rem; color: var(--text-dim); margin-bottom: 18px; }
.cookie-modal__intro a { color: var(--accent-pale); }

.cookie-modal__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 16px 0;
  border-top: 1px solid var(--line);
}
.cookie-modal__row p { margin: 4px 0 0; font-size: 0.88rem; color: var(--text-dim); }
.cookie-modal__always {
  color: var(--accent-bright);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}
.cookie-modal__actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-top: 20px;
}
.cookie-modal__actions .btn { padding: 9px 18px; font-size: 0.92rem; }

/* Toggle switch — a checkbox wearing a track. */
.switch { position: relative; display: inline-block; flex: 0 0 auto; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch__track {
  display: block;
  width: 44px;
  height: 24px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.18);
  transition: background 0.18s ease;
  pointer-events: none;
}
.switch__track::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s ease;
}
.switch input:checked + .switch__track { background: var(--accent-bright); }
.switch input:checked + .switch__track::after { transform: translateX(20px); }
.switch input:focus-visible + .switch__track { outline: 2px solid var(--accent-bright); outline-offset: 2px; }

@media (max-width: 640px) {
  .cookie-bar { flex-direction: column; align-items: stretch; }
  .cookie-bar__actions .btn { flex: 1; }
}

/* ---------- reveal on scroll ---------- */

.reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.6s ease, transform 0.6s ease; }
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

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