/* Grukous homepage.
   Implemented from "Grukous Homepage.dc.html" (Claude Design project
   53426a27-d4a7-4b71-826a-93b4db40856a). Everything below resolves the design
   file's props at their committed defaults:
     contentMaxWidth 1597 · heroVisual "Geometric graphic" · bandBg #E2E4EB
     keySize 102 · keyGap 55 · keyShadow 8 · keyBorderColor / keyPressedColor
     #005CFF · keyFaceColor #FFFFFF · blobDuoShape "Pebble craggy"
     studioFrame "Rules only" · studioDivider "None"

   The design file's applyResponsive() measured the card with a ResizeObserver
   and wrote breakpoint values into custom properties. That is container-query
   work, so it lives in @container rules here — same 900px / 620px thresholds,
   same values, but correct before JS runs and free of resize thrash. The one
   piece that genuinely needs script is the band's baseline anchor, which has to
   measure real glyph metrics; see scripts/site.js.

   Type comes from the design system: every value below is var(--token), so a
   face or tracking change in the system lands here with no edit. --font-mono is
   deliberately NOT redeclared — the page and the system use the same property
   name, so var(--font-mono) would be a self-reference (an invalid cycle); it
   inherits from :root instead. */

body {
  margin: 0;
  background: var(--surface-alt);
  font-family: var(--font-sans);
}

a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-hover); }

.page {
  min-height: 100vh;
  box-sizing: border-box;
  background: var(--surface-card);

  --font-head: var(--font-heading);
  --font-body: var(--font-sans);
  --head-weight: var(--weight-bold);
  --track-lg: var(--tracking-display);
  --track: var(--tracking-heading);
  --lh-1: var(--leading-display);
  --mono-track: var(--tracking-label);
  --mono-weight: var(--weight-medium);

  /* The one page-owned value with no token behind it. The eyebrow labels are
     uppercase stamps where the system's .08em is the point; the mixed-case mono
     link in the contact block is not, and .08em visibly over-tracks it. One
     value on one element — not worth a system round-trip, but don't "fix" it
     to --tracking-label. */
  --mono-track-2: .06em;

  /* Section rhythm — decided "More open". Both values stay on the φ scale
     (123 = 89+34, 76 = 55+21) and the slope reaches its maximum at the same
     container width the old 89/63 pair did, so the change is in how much air
     there is, not when it arrives.

     ⚠ --gap-lg is load-bearing: the hero graphic anchors to the studio column's
     edge, which is derived from the gutter and this gap. Changing the rhythm
     without also feeding --col1 desyncs the anchor from the column. */
  --section-pad: clamp(55px, 8.85cqw, 123px);
  --gap-lg: clamp(21px, 4.76cqw, 76px);
  --gx: clamp(21px, 3.95cqw, 63px);
  --pad-y-sm: clamp(13px, 1.5cqw, 21px);

  /* ⚠ The heading ladder is shared and must never be clamped per-rung. */
  --h1: clamp(37px, calc(18.02px + 5.259cqw), 102px);
  --h2: clamp(29px, calc(19.8px + 2.705cqw), 63px);
  --h3: clamp(23px, calc(19.58px + 1.216cqw), 39px);
  --link-lg: clamp(21px, calc(18.72px + 0.33cqw), 24px);

  /* Pressed-keys grid, derived from keySize 102 / keyGap 55 / keyShadow 8.
     The band's height and the keys' overhang are both proportions of the grid's
     own width, so the whole assembly scales as one object. */
  --key-size: clamp(42px, 7.29cqw, 102px);
  --key-gap: clamp(15px, 3.93cqw, 55px);
  --key-shadow: clamp(4px, .57cqw, 8px);
  --keys-w: calc(3 * var(--key-size) + 2 * var(--key-gap));
  --keys-top: calc(var(--keys-w) * -0.13942);
  --band-h: calc(var(--keys-w) * 0.77404);

  /* Width of the studio grid's first column: 1.272 / (1.272 + 1). */
  --col1: calc((100cqw - 2 * var(--gx) - 1px - 2 * var(--gap-lg)) * 0.559859);
}

.card {
  width: 100%;
  max-width: 1597px;
  margin: 0 auto;
  background: var(--surface-card);
  container-type: inline-size;
}

/* ---------------------------------------------------------------- masthead */

.masthead {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--pad-y-sm) var(--gx);
}

.wordmark { display: block; width: 108px; height: auto; }

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

/* Design system Button, variant "primary", size "md". Its React source drives
   hover/active off component state; :hover / :active do the same job natively. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 42px;
  padding: 0 18px;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: var(--weight-medium);
  line-height: 1;
  white-space: nowrap;
  color: var(--text-inverse);
  background: var(--brand);
  border: 1px solid var(--brand);
  border-radius: var(--radius-0);
  cursor: pointer;
  text-decoration: none;
  user-select: none;
  transition:
    background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}
.btn:hover {
  color: var(--text-inverse);
  transform: translate(-2px, -2px);
  box-shadow: var(--shadow-block);
}
.btn:active {
  background: var(--brand-active);
  transform: none;
  box-shadow: none;
}

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

.hero {
  position: relative;
  z-index: 2;
  border-top: var(--rule-subtle);
  padding: clamp(21px, 3.9cqw, 55px) var(--gx) 0;
  /* Owned by applyBandAnchor() in scripts/site.js at >= 900. The fallback is
     the box-overlap value the script itself falls back to before the heading
     face has loaded, so a no-JS render is still deliberate rather than flat. */
  margin-bottom: var(--hero-mb, calc(0px - clamp(0px, 2.13cqw, 34px)));
}

.hero-title {
  margin: 0;
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: var(--h1);
  line-height: var(--lh-1);
  letter-spacing: var(--track-lg);
  color: var(--text-body);
  max-width: max(calc(var(--h1) * 7.4), calc(var(--col1) + var(--gap-lg)));
}

/* -------------------------------------------------------- band + key grid */

.band {
  position: relative;
  height: var(--band-h);
  background: var(--line); /* bandBg #E2E4EB — exactly the hairline token */
}

/* The keys ride up out of the band by --keys-top, so the band clips everything
   except that overhang. */
.band-clip {
  position: absolute;
  inset: 0;
  clip-path: inset(-400px 0 0 0);
}

.keys {
  position: absolute;
  top: var(--keys-top);
  /* Left edge of the studio grid's third column. */
  left: calc(var(--gx) + var(--col1) + 2 * var(--gap-lg) + 1px);
  right: auto;
  display: grid;
  grid-template-columns: repeat(3, var(--key-size));
  grid-auto-rows: var(--key-size);
  gap: var(--key-gap);
  transform-origin: top left;
}

.key {
  box-sizing: border-box;
  background: var(--white);
  border: var(--border-w-heavy) solid var(--brand);
  box-shadow: var(--key-shadow) var(--key-shadow) 0 var(--brand);
}

/* One key is down: it sits where its own shadow would have been, and the fill
   goes solid so there is nothing left underneath it. */
.key--pressed {
  background: var(--brand);
  box-shadow: none;
  transform: translate(var(--key-shadow), var(--key-shadow));
}

/* ------------------------------------------------------------------ studio */

/* SECTION RULES — decided: no section fills, and the Tasks rule demoted from
   1px navy to the 1px hairline so it matches the studio rule directly above it.
   Navy was the strongest hairline in the system sitting on the one boundary
   with no tone change to back it up, and "More open" spacing made that worse
   rather than better — a dark hairline in ~246px of combined air reads as a
   stray mark. Shaded sections and an inverse navy contact block were both tried
   and dropped. Upward ownership throughout: a section owns the boundary above
   it, never below. */

.studio {
  display: grid;
  grid-template-columns: 1.272fr 1px 1fr;
  gap: var(--gap-lg);
  align-items: stretch;
  padding: var(--section-pad) var(--gx);
  border-top: var(--border-w) solid var(--line);
}

.studio-divider { position: relative; width: 1px; }

.studio-statement {
  margin: 0;
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: var(--h3);
  line-height: var(--leading-heading);
  letter-spacing: var(--track);
  color: var(--text-body);
}

.studio-body {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--weight-regular);
  line-height: var(--leading-body);
  color: var(--text-secondary);
  text-wrap: pretty;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--mono-weight);
  letter-spacing: var(--mono-track);
  text-transform: uppercase;
  color: var(--ink);
}
.studio .eyebrow { margin-bottom: var(--space-4); }
.eyebrow--brand { color: var(--brand); }

/* ------------------------------------------------------------- coming soon */

.coming-soon {
  border-top: var(--border-w) solid var(--line);
  scroll-margin-top: 20px;
}

.duo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.618fr);
  gap: clamp(21px, 3cqw, 34px);
  align-items: center;
  padding: var(--section-pad) var(--gx);
  /* An extra inset on the figure side, on top of the gutter. Kept as a sum
     rather than folded into one clamp — the two clamps saturate at different
     container widths, so a merged clamp is not the same curve. */
  padding-left: calc(var(--gx) + clamp(0px, 3cqw, 34px));
}

.duo-figure { display: flex; justify-content: center; }

.blob { display: block; width: 100%; max-width: 377px; height: auto; }

.duo-title {
  margin: 0 0 var(--space-3);
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: var(--h2);
  line-height: 1.05;
  letter-spacing: var(--track);
  color: var(--text-body);
  max-width: 843px;
}

/* Hand-drawn highlight behind two words. The blob radius and the 13% brand wash
   are page-owned: the system has no "marker" primitive to reach for. */
.highlight {
  position: relative;
  display: inline-block;
  padding: 0 .1em;
  margin-right: -.1em;
  color: var(--brand);
}
.highlight-mark {
  position: absolute;
  left: 0;
  right: 0;
  top: 8%;
  bottom: 6%;
  background: rgba(0, 92, 255, .13);
  border-radius: 48% 52% 42% 58% / 62% 38% 60% 40%;
  z-index: 0;
}
.highlight-text { position: relative; z-index: 1; }

.duo-body {
  margin: 0 0 var(--space-5);
  font-family: var(--font-body);
  font-size: clamp(18px, calc(14.19px + 0.614cqw), 24px);
  line-height: var(--leading-body);
  color: var(--text-secondary);
  max-width: 610px;
}

/* ----------------------------------------------------------------- contact */

.contact {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--section-pad) var(--gx);
  background-color: var(--paper);
  scroll-margin-top: 20px;
}

.contact-title {
  margin: 0;
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: var(--h3);
  line-height: 1.05;
  letter-spacing: var(--track);
  color: var(--text-body);
}

.contact-body {
  margin: 0;
  max-width: 610px;
  font-family: var(--font-body);
  font-size: var(--text-lg);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}

.contact-email {
  margin-top: var(--space-4);
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: var(--link-lg);
  letter-spacing: -.01em;
  color: var(--text-body);
  border-bottom: var(--border-w-heavy) solid var(--brand);
  padding-bottom: 2px;
}
.contact-email:hover { color: var(--brand); }

.contact-social {
  margin-top: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--mono-track-2);
  color: var(--text-secondary);
}
.contact-social:hover { color: var(--brand); }

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

.site-footer {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  gap: 0 var(--space-5);
  padding: var(--pad-y-sm) var(--gx);
  border-top: var(--border-w) solid var(--line);
}

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

.foot-mono {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink);
}
a.foot-mono:hover { color: var(--brand); }

/* ------------------------------------------------------------ breakpoints */

/* Below 900 the page is single-column: the studio divider goes, and the keys
   swing to the right edge of the card with a -89px optical offset (-6.36cqw)
   so they bleed past the gutter the way they do at full width. */
@container (width < 900px) {
  .studio { grid-template-columns: 1fr; }
  .studio-divider { display: none; }
  .duo { grid-template-columns: 1fr; }

  .keys {
    left: auto;
    right: calc(var(--gx) + 6.36cqw);
    transform-origin: top right;
  }

  /* The hero no longer overlaps the band; it clears it. */
  .hero { margin-bottom: calc(var(--keys-w) * 0.13942 + 34px); }

  .hero-title {
    max-width: max(
      calc(var(--h1) * 7.6),
      calc(100cqw - var(--gx) - 6.36cqw - var(--keys-w) - var(--gap-lg))
    );
  }
}

@container (width < 620px) {
  .hero-title { max-width: none; }

  .site-footer {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3) var(--space-5);
  }
}

@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
}

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

/* The legal pages keep the ORIGINAL section rhythm, not the homepage's "More
   open" pair. That is what Grukous Legal.dc.html declares, and it is right: the
   homepage is buying air around a handful of large statements, whereas these
   pages are a single long column where the same padding would just push the
   document further below the fold. */
.page--legal { --section-pad: clamp(34px, 6.4cqw, 89px); }

.legal {
  border-top: var(--border-w) solid var(--line);
  padding: var(--section-pad) var(--gx);
}

/* The title is in the DOM but NOT on screen by default — see .visually-hidden
   on the h1. Termly renders each document's own title inside the embed, so a
   visible one here reads as a duplicate ("Privacy Policy" directly above
   "PRIVACY POLICY").
   Termly can suppress its title per document, but only for the privacy policy,
   so fixing it on their side would leave the three pages inconsistent. Hiding
   ours instead keeps all three identical and costs nothing: the parent document
   still needs a heading, because iframe content does not participate in this
   page's outline and a cross-origin policy is not indexable as page content.
   These type styles are therefore inert until the class is removed — which
   scripts/legal.js does when the embed fails, since the fallback carries no
   title of its own, and which you would do permanently if you ever paste
   Termly's HTML export in as real DOM.
   Sized on the --h3 rung so it clears the prose h2 (39px vs 34px at full width)
   and heading ORDER holds at every width. */
.legal-title {
  margin: 0 0 var(--space-5);
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: var(--h3);
  line-height: var(--leading-heading);
  letter-spacing: var(--track);
  color: var(--text-body);
}

/* Out of the visual flow but still in the accessibility tree and the DOM.
   Declared after .legal-title so its margin reset wins. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ⚠ These prose rules are NOT dead code, and they do NOT reach the live policy.
   Termly renders a cross-origin iframe, so the host page cannot style it — a
   browser security rule, not a Termly limit. They style two things: the
   blocked-embed fallback below, and the path where Termly's copy-HTML export is
   pasted in as real DOM. Termly's own theme controls offer only system fonts,
   so the policy text will not be Archivo; that trade is deliberate, because
   auto-updating policies are worth more than matching type. */
.legal-prose {
  max-width: 754px;
  font-family: var(--font-body);
  font-size: var(--text-md);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}

.legal-prose h2 {
  margin: var(--space-6) 0 var(--space-4);
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: clamp(21px, calc(16.82px + 1.075cqw), 34px);
  line-height: var(--leading-heading);
  letter-spacing: var(--track);
  color: var(--text-body);
}
.legal-prose h2:first-of-type { margin-top: 0; }

.legal-prose h3 {
  margin: var(--space-5) 0 var(--space-3);
  font-family: var(--font-head);
  font-weight: var(--head-weight);
  font-size: clamp(18px, calc(17.03px + 0.2486cqw), 21px);
  line-height: 1.25;
  letter-spacing: var(--track);
  color: var(--text-body);
}

.legal-prose p { margin: 0 0 var(--space-4); }
.legal-prose ul,
.legal-prose ol { margin: 0 0 var(--space-4); padding-left: var(--space-4); }
.legal-prose li { margin: 0 0 var(--space-2); }
.legal-prose a { color: var(--brand); border-bottom: var(--border-w) solid var(--brand); }
.legal-prose strong { color: var(--text-body); font-weight: var(--weight-semibold); }

.legal-prose table { width: 100%; margin: 0 0 var(--space-4); border-collapse: collapse; }
.legal-prose th,
.legal-prose td {
  border-top: var(--border-w) solid var(--line);
  padding: var(--space-3) var(--space-3) var(--space-3) 0;
  text-align: left;
  vertical-align: top;
}
.legal-prose th {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--mono-weight);
  letter-spacing: var(--mono-track);
  text-transform: uppercase;
  color: var(--ink);
}
