/* 3c418.com — values come from docs/DESIGN.md (Figma LT2p3uTLIXXDCbbNChORlX); tokens are the only source of numbers */
@layer tokens, fonts, base, layout, components, motion;

@layer tokens {
  :root {
    color-scheme: light dark;

    --bg:    light-dark(#eaeaea, #151515);
    --bar:   light-dark(#e1e1e1, #1e1e1e);
    --fg:    light-dark(#090909, #f6f6f6);
    --fg-2:  light-dark(#424242, #bdbdbd);
    --muted: light-dark(#646464, #858585);
    --line:  light-dark(rgb(0 0 0 / 8%), rgb(255 255 255 / 8%));

    --font-s: "GT Standard S", system-ui, -apple-system, "Segoe UI", sans-serif;
    --font-m: "GT Standard M", system-ui, -apple-system, "Segoe UI", sans-serif;

    --text-xs:   12px;
    --text-body: 14px;
    --text-h3:   17px;
    --text-h2:   32px;
    --text-h1:   80px;

    --leading-tight: 1.16;
    --leading-body:  24px;

    --space-1:  4px;
    --space-2:  8px;
    --space-3:  12px;
    --space-6:  24px;
    --space-12: 48px;
    --space-15: 60px;
    --space-30: 120px;

    --bar-h:     32px;
    --row-h:     32px;
    --col-left:  280px;
    --gutter:    280px;
    --content-w: 880px;
    --card-w:    320px;
    --glyph:     8px;
    --line-w:    1px;
    --target:    24px;

    /* Motion — one curve family (Emil Kowalski trio, DESIGN.md «Движение»); durations by intent */
    --ease-out:     cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out:  cubic-bezier(0.77, 0, 0.175, 1);
    --motion-quick: 150ms;  /* pointer feedback: underline sweep, colour, «Coming soon» fade, toggle */
    --motion-enter: 300ms;  /* page entrance of content blocks and the active underline */
    --stagger:      80ms;   /* step between content blocks on entrance */
    --hover-dim:    0.7;    /* theme toggle on hover (reference value, mannay.art) */
  }

  html[data-theme="dark"]  { color-scheme: dark; }
  html[data-theme="light"] { color-scheme: light; }

  @media (max-width: 1200px) {
    :root { --gutter: var(--space-6); }
  }
}

@layer fonts {
  /* Retail GT Standard: add url("fonts/…woff2") sources here once licensed. Trial files are never shipped (EULA).
     local() names = name-table full name / PostScript name of the installed trial files
     (GT-Standard-S-Standard-Light-Trial.otf → "GT Standard Trial S Lt" / "GTStandardTrial-SLt", verified 22-08 via the OTF name table and CDP CSS.getPlatformFontsForNode). */
  @font-face { font-family: "GT Standard S"; font-weight: 300; src: local("GT Standard Trial S Lt"),   local("GTStandardTrial-SLt"); }
  @font-face { font-family: "GT Standard S"; font-weight: 500; src: local("GT Standard Trial S Md"),   local("GTStandardTrial-SMd"); }
  @font-face { font-family: "GT Standard S"; font-weight: 600; src: local("GT Standard Trial S Smbd"), local("GTStandardTrial-SSmbd"); }
  @font-face { font-family: "GT Standard M"; font-weight: 300; src: local("GT Standard Trial M Lt"),   local("GTStandardTrial-MLt"); }
}

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

  html {
    background: var(--bg);
    color: var(--fg);
    font-family: var(--font-m);
    font-size: var(--text-body);
    line-height: var(--leading-body);
    -webkit-text-size-adjust: 100%;
  }

  body { margin: 0; min-height: 100dvh; }

  h1, h2, h3, p, dl { margin: 0; }
  a { color: inherit; text-decoration: none; }
  button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

  /* Every text node in the mockup is trimmed to cap height (leadingTrim: CAP_HEIGHT) */
  h1, h2, h3, p, a, button, dt, dd { text-box: trim-both cap alphabetic; }

  :focus-visible { outline: var(--line-w) solid var(--fg); outline-offset: var(--space-1); }
}

@layer layout {
  body {
    display: grid;
    grid-template-rows: auto 1fr auto;
  }

  .bar {
    display: grid;
    grid-template-columns: var(--col-left) 1fr;
    height: calc(var(--bar-h) + var(--line-w));
    background: var(--bar);
    font-family: var(--font-s);
    font-size: var(--text-xs);
    font-weight: 300;
    line-height: var(--leading-tight);
  }
  .bar-top    { border-bottom: var(--line-w) solid var(--line); }
  .bar-bottom { border-top: var(--line-w) solid var(--line); }

  .cell {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    padding: 0 var(--space-3);
    min-width: 0;
  }
  .cell-right { justify-content: space-between; }
  .cell-right > nav, .cell-right > div { display: flex; gap: var(--space-6); }

  main {
    padding: var(--space-30) var(--gutter);
    display: flex;
    flex-direction: column;
    gap: var(--space-15);
  }

  h1 {
    font-family: var(--font-s);
    font-size: var(--text-h1);
    font-weight: 300;
    line-height: var(--leading-tight);
    overflow-wrap: anywhere;
  }
}

@layer components {
  .wordmark { font-weight: 600; }

  /* Underline of text links: 1px line 4px under the cap box (mockup node 1:192); drawn by the motion layer (sweep) */
  .bar a, .row dd a { position: relative; }
  .bar a::after, .row dd a::after {
    content: "";
    position: absolute;
    left: 0; right: 0;
    top: calc(100% + var(--space-1));
    height: var(--line-w);
    background: currentColor;
    transform: scaleX(0);
  }
  .bar a[aria-current="page"]::after { transform: scaleX(1); }

  .copyright { color: var(--muted); }

  /* Theme toggle: 8×8 square — outline on dark, filled on light; 24×24 hit area around it */
  .theme-toggle {
    width: var(--target);
    height: var(--target);
    margin-right: calc((var(--target) - var(--glyph)) / -2);
    display: grid;
    place-items: center;
    text-box: normal;
  }
  .theme-toggle::before {
    content: "";
    width: var(--glyph);
    height: var(--glyph);
    border: var(--line-w) solid var(--fg);
    background: light-dark(var(--fg), transparent);
  }

  /* Bordered panel (ABOUT, policies) */
  .panel {
    max-width: var(--content-w);
    border: var(--line-w) solid var(--line);
    padding: var(--space-12);
    display: flex;
    flex-direction: column;
    gap: var(--space-12);
  }
  .group { display: flex; flex-direction: column; gap: var(--space-6); }
  .group h2 { font-family: var(--font-s); font-size: var(--text-h2); font-weight: 500; line-height: var(--leading-tight); }
  .group h3, .group .sub { font-family: var(--font-s); font-size: var(--text-h3); font-weight: 500; line-height: var(--leading-tight); }
  .group p { font-weight: 300; }
  .group .secondary { color: var(--fg-2); }
  .group .emphasis { color: var(--fg); }
  .group p a { text-decoration: underline; text-underline-offset: var(--space-1); }

  /* Product cards: 320-wide tracks, as many per row as the column holds (two in the 880 column at 1440 — the third card starts
     a second row, DAN-43 decision A); every row takes the height of the tallest card, so the spec and the WEBSITE row sit on the
     same lines in all three cards */
  .cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, min(var(--card-w), 100%));
    grid-auto-rows: 1fr;
    gap: var(--space-15);
  }
  .card {
    width: var(--card-w);
    border: var(--line-w) solid var(--line);
    padding: var(--space-6);
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
  }
  .card h2 { font-family: var(--font-s); font-size: var(--text-h3); font-weight: 500; line-height: var(--leading-tight); }
  /* Description takes the slack: cards in a row stretch to one height, so the spec and the WEBSITE row sit on the same lines in every card and stay at the bottom */
  .card .description { color: var(--fg-2); font-weight: 300; flex-grow: 1; }
  .spec {
    margin: 0 calc(var(--space-6) * -1);
    font-family: var(--font-s);
    font-size: var(--text-xs);
    font-weight: 300;
    line-height: var(--leading-tight);
  }
  /* Row pitch is exactly 32 (mockup rounds the 12px cap height to 8; the font gives 8.45) */
  .spec > div {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    height: calc(var(--row-h) + var(--line-w));
    padding: var(--space-3) var(--space-6);
    border-bottom: var(--line-w) solid var(--line);
    margin-bottom: calc(var(--line-w) * -1);
  }
  .spec dt { color: var(--muted); }
  .spec dd { margin: 0; font-family: var(--font-m); color: var(--fg-2); }
  .card .links {
    display: flex;
    align-items: flex-end; /* button (font S) and note (font M) meet on the baseline, as dt/dd do in the spec rows */
    gap: var(--space-6);
    font-family: var(--font-s);
    font-size: var(--text-xs);
    font-weight: 300;
    line-height: var(--leading-tight);
  }
  /* WEBSITE has no destination yet (DAN-43): a non-navigating button that stays focusable — aria-disabled, not disabled
     (base: Rauno Freiberg — disabled controls leave the tab order). «Coming soon» is its value in the spec's label → value voice
     (font M, --fg-2): shown on hover/focus where hover exists, always shown on touch (base: Kowalski/Freiberg — hover effects
     ungated by the hover media feature break on touch). */
  .card .links .site { cursor: default; }
  .card .links .soon { font-family: var(--font-m); color: var(--fg-2); text-box: trim-both cap alphabetic; opacity: 0; }
  .card .links .site:focus-visible + .soon { opacity: 1; }
  @media (hover: hover) { .card .links .site:hover + .soon { opacity: 1; } }
  @media (hover: none)  { .card .links .soon { opacity: 1; } }

  /* Contact rows */
  .rows { display: flex; flex-direction: column; gap: var(--space-6); }
  .row {
    width: var(--card-w);
    border: var(--line-w) solid var(--line);
    padding: var(--space-6);
    display: flex;
    justify-content: space-between;
    gap: var(--space-6);
    font-size: var(--text-xs);
    font-weight: 300;
    line-height: var(--leading-tight);
  }
  .row dt { font-family: var(--font-s); color: var(--muted); }
  .row dd { margin: 0; }

  @media (max-width: 1200px) {
    .bar { grid-template-columns: auto 1fr; }
    .card, .row { width: min(var(--card-w), 100%); }
  }

  /* Narrower than the mockup's content column (880): the footer keeps its two cells as two rows — copyright, then the
     policies in a column with the theme toggle at the right edge — and the h1 steps down one size on the scale (80 → 32).
     Values are the bar's own 12px padding, the type scale and the toggle's glyph offset; no new numbers (DAN-43: at 390 the
     policies wrapped into three lines and the toggle sat outside the viewport). Placed after the 1200 rule so the one-column bar wins. */
  @media (max-width: 880px) {
    h1 { font-size: var(--text-h2); }
    .bar-bottom { height: auto; grid-template-columns: 1fr; }
    .bar-bottom .cell { padding: var(--space-3); align-items: flex-start; }
    .bar-bottom nav { flex-direction: column; gap: var(--space-3); }
    .bar-bottom .theme-toggle { margin-top: calc((var(--target) - var(--glyph)) / -2); } /* glyph on the first link's cap line */
  }
}

/* Motion — phases and numbers in docs/DESIGN.md «Движение»; only transform/opacity/color animate */
@layer motion {
  /* Phase «блоки входят стаггером»: h1 first, then each bordered block, 80ms apart */
  @keyframes enter { from { opacity: 0; transform: translateY(var(--space-3)); } }
  @keyframes fade  { from { opacity: 0; } }
  /* Phase «подчёркивание активного пункта растёт» */
  @keyframes grow  { from { transform: scaleX(0); } }

  main > h1, .panel, .card, .row {
    animation: enter var(--motion-enter) var(--ease-out) calc(var(--i, 0) * var(--stagger)) backwards;
  }
  .panel, .card:nth-child(1), .row:nth-child(1) { --i: 1; }
  .card:nth-child(2), .row:nth-child(2) { --i: 2; }
  .card:nth-child(3) { --i: 3; } /* third card: delay 240, sum of delays stays under the 500 cap */

  .bar a[aria-current="page"]::after {
    transform-origin: 0 50%;
    animation: grow var(--motion-enter) var(--ease-out) backwards;
  }

  /* Sweep (reference class mannay.art): grows from the left on hover, retracts to the right on leave; focus-visible = hover */
  .bar a::after, .row dd a::after {
    transform-origin: 100% 50%;
    transition: transform var(--motion-quick) var(--ease-out);
  }
  .bar a:hover::after, .bar a:focus-visible::after,
  .row dd a:hover::after, .row dd a:focus-visible::after {
    transform: scaleX(1);
    transform-origin: 0 50%;
  }

  /* WEBSITE → «Coming soon»: the note fades in — opacity only, the quick pointer-feedback timing */
  .card .links .soon { transition: opacity var(--motion-quick) var(--ease-out); }

  /* Inline links in running text: colour lifts from the paragraph grey to --fg */
  .group p a { transition: color var(--motion-quick) var(--ease-out); }
  .group p a:hover, .group p a:focus-visible { color: var(--fg); }

  /* Theme toggle: dims on hover */
  .theme-toggle::before { transition: opacity var(--motion-quick) var(--ease-out); }
  .theme-toggle:hover::before, .theme-toggle:focus-visible::before { opacity: var(--hover-dim); }

  /* Theme swap: transitions muted for the swap frame (theme.js adds .theme-swap for two frames) */
  .theme-swap *, .theme-swap *::before, .theme-swap *::after { transition: none !important; }

  @media (prefers-reduced-motion: reduce) {
    /* Level 1: no displacement anywhere — entrance is a fade, the active underline is static */
    main > h1, .panel, .card, .row { animation-name: fade; }
    .bar a[aria-current="page"]::after { animation: none; }
    /* Level 2: hover feedback stays, as opacity instead of movement */
    .bar a::after, .row dd a::after {
      transform: scaleX(1);
      opacity: 0;
      transition-property: opacity;
    }
    .bar a[aria-current="page"]::after,
    .bar a:hover::after, .bar a:focus-visible::after,
    .row dd a:hover::after, .row dd a:focus-visible::after { opacity: 1; }
    /* «Coming soon» moves nothing already: its opacity fade stays (reduced ≠ none) */
  }
}
