/* Angler — 20 · formats.
   The #demo block mirrored. Same wrap width, same 694x657 panel, same corner notches
   and the same .72fr/1fr ratio — only the order is swapped, so the two sections read
   as a matched pair rather than two different layouts that happen to sit together.
   Values are deliberately duplicated from 15-demo.css rather than shared: the two
   sections are free to drift apart later, and a shared base class would make that a
   refactor instead of an edit. */

.fmt {
  background: var(--paper);
  /* Matches the bottom of #demo above. These two are a mirrored pair and must sit
     closer together than the page's ordinary section rhythm puts them. */
  padding-top: clamp(40px, 5vw, 72px);
  /* same notch size as the panel above */
  --cut: clamp(11px, 1.5vw, 20px);
  /* ring geometry, in one place */
  --tile: 86px;
  /* Ring radius as a LENGTH, not a percentage: translateY resolves % against the
     element's own height (the 86px tile), not the panel, which would have made the
     radius depend on the tile size. */
  --ring: clamp(112px, 14vw, 192px);
}

.fmt__wrap {
  /* Byte-for-byte the sizing of .dev__wrap in 15-demo.css. Using --gutter padding
     instead cost 64px of content and the panel came out 657 wide against #demo's 694. */
  margin-inline: auto;
  width: calc(100% - 2 * clamp(16px, 3vw, 44px));
  max-width: 1280px;
  display: grid;
  /* mirrored: plate first at 1fr, copy second at .72fr */
  grid-template-columns: minmax(0, 1fr) minmax(0, .72fr);
  gap: clamp(36px, 6vw, 86px);
  align-items: center;
}

/* ---------------------------------------------------------------- the plate */

.fmt__panel {
  position: relative;
  /* 694 x 657 is what #demo's .dev__panel measures at 1440 — matched on purpose. */
  aspect-ratio: 694 / 657;
  border-radius: var(--r-card);
  /* Four page-ground squares painted over the corners. They also cover the 6px radius
     underneath, which is what makes the corners read genuinely square. NOT
     overflow:hidden — clipping would round them straight back. */
  background:
    linear-gradient(var(--paper), var(--paper)) 0    0    / var(--cut) var(--cut) no-repeat,
    linear-gradient(var(--paper), var(--paper)) 100% 0    / var(--cut) var(--cut) no-repeat,
    linear-gradient(var(--paper), var(--paper)) 0    100% / var(--cut) var(--cut) no-repeat,
    linear-gradient(var(--paper), var(--paper)) 100% 100% / var(--cut) var(--cut) no-repeat,
    url("../assets/img/formats-bg.webp") center / cover no-repeat;
}

/* ---------------------------------------------------------------- the rod */

/* Sized off --ring rather than the panel, so it keeps its clearance inside the circle
   at every breakpoint: at this multiple the rod's half-diagonal stays well under the
   ring's inner edge (radius minus half a tile) on all three tile sizes.
   Behind the icons on purpose — it is the ground of the composition, not a sixth mark. */
.fmt__core {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  height: var(--ring);
  width: auto;
  transform: translate(-50%, -50%);
  /* White line art at ~9% ink coverage over a picture whose luminance runs the full
     range — without its own shadow the strokes vanish wherever the dither goes pale. */
  filter: drop-shadow(0 1px 2px rgb(14 54 62 / .45)) drop-shadow(0 6px 20px rgb(14 54 62 / .35));
}

.js-ready .fmt__panel .fmt__core { opacity: 0; }
/* Lands before the apps (0.62s) — the rod arrives, then they gather around it. */
.fmt__panel.is-in .fmt__core {
  animation: fmt-core-in .8s var(--ease-house) .28s both;
}
@keyframes fmt-core-in {
  from { opacity: 0; transform: translate(-50%, -46%) scale(.96); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* ---------------------------------------------------------------- the ring */

.fmt__ring {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  z-index: 2;
}

/* Five tiles at 72° apart, first one at twelve o'clock. The double translate is the
   trick: rotate the item out to the ring radius, then counter-rotate the tile itself
   so every icon still sits square to the page instead of tipping with its angle. */
.fmt__app {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--tile);
  height: var(--tile);
  margin: calc(var(--tile) / -2) 0 0 calc(var(--tile) / -2);
  transform:
    rotate(calc(var(--i) * 72deg))
    translateY(calc(var(--ring) * -1))
    rotate(calc(var(--i) * -72deg));
}

/* The entrance hangs off .is-in, not page load. As a plain load animation it was over
   long before the section reached the viewport — the icons were simply always there.
   .js-ready gates the hidden state so a visitor without JS never loses them. */
.js-ready .fmt__panel .fmt__app { opacity: 0; }
.fmt__panel.is-in .fmt__app {
  /* `both`, and the keyframe states opacity at BOTH ends: the implicit to-state is the
     element's own computed style, which the .js-ready rule above pins at 0. */
  animation: fmt-app-in .72s var(--ease-open) both;
  /* long enough after the panel's own fade that the plate reads as empty first, then
     fills — the icons arriving are the point, so they must not be there on arrival */
  animation-delay: calc(.62s + var(--i) * .13s);
}
.fmt__app img {
  width: 100%;
  height: 100%;
  display: block;
  /* the icons carry their own squircle in the alpha, so shadow the alpha, never a box */
  filter: drop-shadow(0 2px 4px rgb(14 54 62 / .28)) drop-shadow(0 10px 22px rgb(14 54 62 / .3));
  transition: transform .18s var(--ease-nav);
}
@media (hover: hover) and (pointer: fine) {
  .fmt__app:hover img { transform: translateY(-4px) scale(1.06); }
}

@keyframes fmt-app-in {
  from { opacity: 0; transform:
    rotate(calc(var(--i) * 72deg))
    translateY(calc(var(--ring) * -0.82))
    rotate(calc(var(--i) * -72deg)); }
  to   { opacity: 1; transform:
    rotate(calc(var(--i) * 72deg))
    translateY(calc(var(--ring) * -1))
    rotate(calc(var(--i) * -72deg)); }
}

/* ---------------------------------------------------------------- the copy */

.fmt__copy { max-width: 46ch; }

/* Mirrors .dev__eyebrow, not base.css's .eyebrow. The base one is gold with a trailing
   hairline that runs to the edge of the column; this section is the visual pair of
   #demo directly above it, and that rule was the one thing breaking the match.
   Duplicated rather than shared, same as the rest of this file — the two sections are
   free to drift apart later without that becoming a refactor. */
.fmt__eyebrow {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Every value below is .dev__h / .dev__p verbatim. These two sections are a mirrored
   pair and were running two different type scales: at 1440 the headline was 44px
   against #demo's 40 and the body was 18px against 16, with different line-height
   ratios, tracking and leading on top. Read one after the other it looked like two
   design systems. #demo's numbers win because they are the measured ones — its clamp's
   vw term is sized to the copy column so both display lines keep the same slack at
   every width. */
.fmt__h {
  margin-top: 22px;
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.85rem, 2.95vw, 2.5rem);
  line-height: 1.12;
  letter-spacing: -.02em;
}
/* x.ai's two-tone display line, same as #demo */
.fmt__h--ink  { display: block; color: var(--ink); }
.fmt__h--soft { display: block; color: var(--muted); }

.fmt__p {
  margin-top: 21px;
  max-width: 46ch;
  font-size: 16px;
  line-height: 1.62;
  color: var(--ink-soft);
}


/* ---------------------------------------------------------------- responsive */

@media (max-width: 1180px) {
  /* Same breakpoint as #demo. Plate first on narrow, so the visual still leads. */
  .fmt__wrap { grid-template-columns: minmax(0, 1fr); }
  .fmt__copy { max-width: 62ch; }
}

@media (max-width: 720px) {
  .fmt { --tile: 64px; --ring: clamp(96px, 26vw, 150px); }
}

@media (max-width: 460px) {
  .fmt { --tile: 52px; --ring: clamp(78px, 27vw, 110px); }
}

@media (prefers-reduced-motion: reduce) {
  /* opacity back to 1 explicitly — killing the animation alone would leave the
     .js-ready hidden state in force and the ring would never appear at all */
  .js-ready .fmt__panel .fmt__app,
  .fmt__panel.is-in .fmt__app { opacity: 1; animation: none; }
  .js-ready .fmt__panel .fmt__core { opacity: 1; }
  .fmt__panel.is-in .fmt__core { animation: none; transform: translate(-50%, -50%); }
  .fmt__app:hover img { transform: none; }
}
