/* ==========================================================================
   PONIC SYSTEMS — PonicTank

   Two worlds, each earned. WHITE is the object: the hero, the technical plate,
   the Czech documents. BLACK is the light: the poster grid and the film. The
   product is a lamp, and the brand colours only become legible as ink on the
   dark ground — #38b6ff measures 2.26:1 on white and 8.4:1 on near-black.

   Set entirely in the resident Apple system face. No webfont is declared and
   nothing is loaded. Hierarchy comes from weight, size, tracking and colour.
   ========================================================================== */

/* --- Tokens --------------------------------------------------------------- */
:root {
  /* Exact brand values from the client's own storefront. */
  --bg:          #ffffff;
  --surface:     #eff1f2;
  --line:        #e2e5e7;
  --line-strong: #ccd1d4;
  --ink:         #2f2e2e;   /* 13.5:1 on white */
  --muted:       #605e5e;   /*  6.4:1 on white */
  --dark:        #0c0c0c;
  --dim:         #a3a1a1;   /*  7.8:1 on --dark */

  --cyan:  #38b6ff;
  --green: #7ed957;
  --grad:  linear-gradient(105deg, #38b6ff 0%, #4fc9ad 50%, #7ed957 100%);

  /* Focus is redefined per dark surface, so one rule covers the whole page. */
  --focus: #2f2e2e;

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
          "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Spacing scale: 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128 / 160 */
  --s1: 4px;  --s2: 8px;  --s3: 12px;  --s4: 16px;  --s5: 24px;  --s6: 32px;
  --s7: 48px; --s8: 64px; --s9: 96px;  --s10: 128px; --s11: 160px;

  --gutter:  clamp(20px, 5vw, 48px);
  --section: clamp(96px, 12vw, 160px);
  /* The sticky bar's own height, measured: the roundel at its largest (38px)
     plus 12px of padding either side is 62px, over the 60px min-height, and
     the always-present 1px bottom border makes 63. The hero subtracts it so
     the fold lands on the hero's bottom edge rather than a header below it. */
  --header-h: 63px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur:  520ms;

  --z-sticky: 100;
  --z-skip:   200;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 88px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.6;
  font-feature-settings: "kern" 1, "liga" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

img, video { max-width: 100%; display: block; }
/* <picture> is a format-negotiation wrapper only; display:contents keeps the
   <img> a direct child so grid and absolute positioning still reach it. */
picture { display: contents; }
h1, h2, h3, p, figure, ul { margin: 0; }
button { font: inherit; color: inherit; }

/* The ring follows the same contrast rule as everything else: ink on the light
   surfaces, brand green (11:1) on the dark ones. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: 3px;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Language switching ---------------------------------------------------
   Both languages ship in the DOM. :root[lang] decides which is painted, so the
   correct copy is right on the very first frame and the page still works with
   JS disabled (markup default is EN).                                        */
:root[lang="en"] [lang="cs"] { display: none; }
:root[lang="cs"] [lang="en"] { display: none; }

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

.section { padding-block: var(--section); }
.section--surface { background: var(--surface); }

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  z-index: var(--z-skip);
  background: var(--ink);
  color: #fff;
  padding: var(--s3) var(--s5);
  border-radius: 999px;
  text-decoration: none;
  font-size: 0.875rem;
  transition: top 180ms var(--ease);
}
.skip:focus { top: var(--s3); }

/* --- Type -----------------------------------------------------------------
   One family, four registers: display 700 at tight tracking, body 400 at
   normal, headings 600, and an 11px uppercase meta for labels.              */
.display {
  font-size: clamp(2.5rem, 1.15rem + 5.1vw, 4.75rem);
  line-height: 1.0;
  letter-spacing: -0.035em;
  font-weight: 700;
  text-wrap: balance;
}

.h2 {
  font-size: clamp(1.875rem, 1.1rem + 2.7vw, 3.25rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-weight: 700;
  text-wrap: balance;
}

.h3 {
  font-size: clamp(1.0625rem, 1rem + 0.32vw, 1.25rem);
  line-height: 1.25;
  letter-spacing: -0.012em;
  font-weight: 600;
}

.body {
  font-size: clamp(1rem, 0.97rem + 0.16vw, 1.0625rem);
  line-height: 1.6;
  color: var(--ink);
  max-width: 62ch;
  text-wrap: pretty;
}

.meta {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  line-height: 1.4;
  color: var(--dim);
}

/* The accented word. The brand mark is a gradient; a word is not — so the word
   keeps full contrast and the real gradient runs as a rule beneath it. */
.accent {
  font-style: normal;
  color: inherit;
  background-image: var(--grad);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0.055em;
  padding-bottom: 0.08em;
}

/* --- Header --------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid transparent;
  transition: border-color 300ms var(--ease);
}
.site-header.is-scrolled { border-bottom-color: var(--line); }

.bar {
  max-width: 1200px;
  margin-inline: auto;
  padding: var(--s3) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--s5);
  min-height: 60px;
}

/* The roundel is the logo. Nothing else is needed here. */
.brand { display: block; flex: none; line-height: 0; }
.brand img {
  width: clamp(32px, 3.4vw, 38px);
  height: auto;
}

.nav {
  flex: 1 1 auto;
  display: flex;
  justify-content: center;
  gap: clamp(var(--s4), 2.4vw, var(--s6));
}
.nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.875rem;
  white-space: nowrap;
  padding-block: var(--s2);
  transition: color 200ms var(--ease);
}
.nav a:hover { color: var(--ink); }

/* A filled track rather than a hairline: #ccd1d4 on white measures 1.5:1, well
   under the 3:1 WCAG applies to the boundary of a control. The state is carried
   by the filled pill instead, which is 13.5:1. */
.lang {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--surface);
  border-radius: 999px;
  padding: 3px;
}
.lang-btn {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 5px 10px;
  border-radius: 999px;
  transition: background-color 220ms var(--ease), color 220ms var(--ease);
}
.lang-btn:hover { color: var(--ink); }
.lang-sep { display: none; }

/* Active state derives from :root[lang], so it is correct on first paint
   without waiting for script.js. */
:root[lang="en"] .lang-btn[data-lang="en"],
:root[lang="cs"] .lang-btn[data-lang="cs"] {
  background: var(--ink);
  color: #fff;
}

/* --- Hero -----------------------------------------------------------------
   A frame from the film, full bleed: the unit in a kitchen, in use.

   The still is 1800x850, 2.12:1, and its content is fixed: the counter and
   splashback fill the left third at a relative luminance of 0.47–0.67, the
   unit stands at x 29–43% with its light ring at y 60%, the man occupies
   x 52–80%, and the top quarter and the right fifth are dark, 0.01–0.27.
   Two things follow from that and both are measured, not guessed.

   First, `cover` on a box narrower than 2.12:1 throws away the sides, so the
   crop is anchored left: it keeps the counter the copy needs and still holds
   the unit and the man inside the frame at every width down to 1024.

   Second, there is no dark region on the left large enough to hold a block of
   type, so the scrim has to make one. It is a corner gradient rather than a
   band: darkest at the bottom-left where the copy sits, gone entirely by two
   thirds of the way across and up. The unit, the light ring, the greens, the
   man and the whole top of the frame are never touched. */
.hero { position: relative; }

.hero-media {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: clip;
  background: #16171a;
}
.hero-media-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Stacked, the frame is wide enough to hold everything, so it stays centred
     on the unit rather than on the geometry. */
  object-position: 42% 50%;
}
/* Only drawn where the copy is over the picture. */
.hero-scrim { display: none; }

.hero-copy {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1200px;
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-top: clamp(var(--s6), 5vw, var(--s7));
  padding-bottom: clamp(var(--s7), 6vw, var(--s9));
}
.hero .display {
  font-size: clamp(2.25rem, 1rem + 3.9vw, 3.5rem);
  max-width: 13ch;
}
.hero .hero-sub { max-width: 34ch; }

.masthead {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.17em;
  color: var(--ink);
  padding-bottom: var(--s4);
  position: relative;
}
/* The one gradient rule on the light half of the page. */
.masthead::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 80px;
  height: 3px;
  border-radius: 2px;
  background-image: var(--grad);
}

.display { margin-top: var(--s6); }

.hero-sub {
  margin-top: var(--s5);
  font-size: clamp(1.0625rem, 1rem + 0.34vw, 1.1875rem);
  line-height: 1.5;
  color: var(--muted);
  max-width: 44ch;
  text-wrap: pretty;
}

.act {
  margin-top: var(--s7);
  display: flex;
  align-items: center;
  gap: var(--s5);
  flex-wrap: wrap;
}

.price {
  font-size: 1rem;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: -0.005em;
}
.price--onDark { color: var(--dim); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
  color: #fff;
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  padding: 14px 26px;
  border-radius: 999px;
  transition: background-color 240ms var(--ease), transform 240ms var(--ease);
}
.btn:hover { background: #000; }
.btn:active { transform: translateY(1px); }
.btn--light { background: #fff; color: #0c0c0c; }
.btn--light:hover { background: #e8f6ff; }

/* ==========================================================================
   THE DARK CHAPTER — poster grid, then the film. One ground, no seam.
   ========================================================================== */
.chapter {
  background: var(--dark);
  color: #fff;
  --focus: var(--green);
  padding-block: var(--section);
}

.furniture {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s5);
  flex-wrap: wrap;
  margin-bottom: clamp(var(--s6), 4vw, var(--s7));
}
.furn-mark {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--dim);
}

/* --- Poster grid ---------------------------------------------------------- */
.grid {
  display: grid;
  gap: 12px;
}

/* Media is absolutely positioned so it never contributes intrinsic height:
   rows are set by the grid, and only the type-only card can grow one. */
.tile {
  position: relative;
  overflow: hidden;
  background: #000;
  min-width: 0;
}
.tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 900ms var(--ease);
}
.tile:hover img { transform: scale(1.035); }

/* --- The turning layer -----------------------------------------------------
   The grid turns like a cube layer: a whole row at a time, each tile pivoting
   on the same horizontal axis, staggered so the turn sweeps across rather than
   snapping in unison.

   No `preserve-3d` anywhere. The two faces are rotated independently — front
   0deg to -180deg, back 180deg to 0deg — which reaches the same picture and
   avoids the one real trap in this construction: a `preserve-3d` child inside
   an `overflow: hidden` parent is flattened by several engines, and .tile has
   carried `overflow: hidden` since the grid was built. Perspective sits on the
   tile, so each row shares a vanishing point.

   The faces are absolutely positioned inside the tile's existing box, so the
   grid geometry cannot move: the turn happens entirely inside a rectangle
   whose size is set by the row template and never by its contents. */
.tile[data-cube] { perspective: 1400px; }

.face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* Crisp, not languid: 420ms is long enough to read as a turn and short
     enough that the row is done before you start waiting for it. */
  transition: transform 420ms var(--ease);
}
.face--back  { transform: rotateX(180deg); }
.tile.is-turned .face--front { transform: rotateX(-180deg); }
.tile.is-turned .face--back  { transform: rotateX(0deg); }

/* The type faces. White, so a turn alternates picture and page — the same two
   grounds the rest of the site is built from, rather than a third thing. */
.face--type {
  background: #fff;
  display: flex;
  align-items: flex-end;
  padding: clamp(20px, 2.4vw, 30px);
}
.face-line {
  font-size: clamp(1.25rem, 0.82rem + 1.45vw, 1.9375rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.12;
  color: var(--ink);          /* 13.5:1 on white */
  text-wrap: balance;
}

/* Not optional, and not a reduced version: no rotation at all. The front faces
   are what the page is; the turn is decoration on top of it. */
@media (prefers-reduced-motion: reduce) {
  .face { transition: none; }
  .tile.is-turned .face--front { transform: none; }
  .tile.is-turned .face--back  { transform: rotateX(180deg); }
}

/* Legibility comes from a gradient at the card's base, carried by the caption
   box itself. The top two-thirds of every photograph stays untouched. */
.cap {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  padding: clamp(20px, 2.4vw, 30px);
  padding-top: clamp(64px, 13vw, 130px);
  background: linear-gradient(to top,
    rgba(0, 0, 0, 0.90) 0%,
    rgba(0, 0, 0, 0.74) 26%,
    rgba(0, 0, 0, 0.40) 60%,
    rgba(0, 0, 0, 0) 100%);
}

.cap-line {
  font-size: clamp(1.25rem, 0.82rem + 1.45vw, 1.9375rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.12;
  color: #fff;
  text-wrap: balance;
}
.cap-h {
  font-size: clamp(1.25rem, 0.9rem + 1.15vw, 1.75rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: #fff;
}
.cap-sub {
  margin-top: var(--s3);
  font-size: 0.9375rem;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.82);
  max-width: 30ch;
}

/* Same gradient logic, smaller: a label sits at the base where the photograph
   is already dark, not over a bright top corner. */
.meta--pin {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  padding: clamp(18px, 2.2vw, 26px);
  padding-top: clamp(48px, 9vw, 84px);
  color: #fff;
  background: linear-gradient(to top,
    rgba(0, 0, 0, 0.86) 0%,
    rgba(0, 0, 0, 0.56) 42%,
    rgba(0, 0, 0, 0) 100%);
}

/* The one solid card. It carries the single verified hard spec, and it is the
   only place the brand gradient is a whole surface. Ink is near-black: white
   on #7ed957 is 1.8:1, near-black on it is 10.8:1. */
/* The card's layout belongs to its face, not to the tile. The faces are
   absolutely positioned, so a flex box and padding declared on .tile--grad
   itself governs nothing — the copy ends up hard against the top-left corner
   with two thirds of the card empty below it. Everything that positions the
   type therefore lives on the face.

   Bottom-aligned, on the same optical inset as .cap, so the spec sits where
   every photograph's caption sits and the row reads as one line of type. */
.tile--grad { background-image: var(--grad); }
.tile--grad .face--front {
  display: flex;
  align-items: flex-end;
  padding: clamp(20px, 2.4vw, 30px);
}
.cap-line--ink { color: #0c0c0c; }
.cap-line--cs  { font-size: clamp(1rem, 0.83rem + 0.6vw, 1.1875rem); line-height: 1.28; }
.num {
  font-size: 1.22em;
  font-weight: 700;
  font-variant-numeric: lining-nums tabular-nums;
}

/* Per-tile framing. Each of these is the crop that keeps the unit in the frame
   at that tile's own proportion — none of them is the default centre. The unit
   sits left of centre in most of the set, so most of these pull left. */
.tile--1 img { object-position: 42% 50%; }   /* keeps the board and glass right */
.tile--2 img { object-position: 46% 52%; }   /* narrow slice: unit and the lamp glow */
.tile--3 img { object-position: 44% 50%; }
.tile--4 img { object-position: 58% 50%; }   /* keeps the window, drops dead desk */
.tile--5 img { object-position: 50% 54%; }
.tile--7 img { object-position: 44% 50%; }   /* keeps the brass column in shot */
.tile--8 img { object-position: 50% 56%; }   /* keeps the scattered herbs */

/* --- The film ------------------------------------------------------------- */
.film { margin-top: clamp(var(--s8), 8vw, var(--s10)); }
.furniture--meta { margin-bottom: var(--s4); }

/* The source is 1280x608 of picture inside a 720p frame; matching that ratio
   and covering trims the baked-in letterbox bars exactly. */
.player {
  position: relative;
  width: 100%;
  aspect-ratio: 1280 / 608;
  min-height: 240px;
  background: #000;
  overflow: hidden;
}
.player-media {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The film's own surface, as a button. It carries no paint of its own — the
   film is the affordance — but it is focusable, so the ring has to land on the
   frame rather than on nothing. */
.player-hit {
  position: absolute;
  inset: 0;
  z-index: 1;
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.player-hit:focus-visible { outline-offset: -4px; }

/* One affordance, in the site's own language. Nothing here resembles a browser
   control: a round glass chip and a hairline that fills. */
.sound {
  position: absolute;
  /* Above the fullscreen hit layer, which covers the whole frame: without this
     the chip is painted under it and its clicks go to fullscreen instead. */
  z-index: 2;
  right: clamp(16px, 3vw, 32px);
  bottom: clamp(20px, 3vw, 34px);
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  /* The chip has to hold a white glyph over an unknown film frame, so it is
     opaque enough that even a blown-out frame leaves the icon above 3:1. */
  background: rgba(8, 8, 8, 0.72);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: #fff;
  cursor: pointer;
  transition: background-color 220ms var(--ease), border-color 220ms var(--ease),
              transform 220ms var(--ease);
}
.sound:hover { background: rgba(8, 8, 8, 0.9); border-color: #fff; }
.sound:active { transform: scale(0.94); }
.sound:focus-visible { outline-color: #fff; }
.sound-ico { width: 22px; height: 22px; }
.sound-on { display: none; }
.sound.is-on .sound-off { display: none; }
.sound.is-on .sound-on  { display: inline; }

.track {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(255, 255, 255, 0.2);
  pointer-events: none;
}
.track-fill {
  display: block;
  width: 100%;
  height: 100%;
  background-image: var(--grad);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* --- Anatomy -------------------------------------------------------------
   The plate runs the full column rather than sitting in a narrow half: its
   labels are burned into the artwork at a fixed size, so the only way to keep
   them legible is to give the drawing real width.                          */
/* minmax(0, 1fr) rather than the implicit auto column: an auto track takes its
   floor from the widest item's min-content, so one wide child can stretch the
   column past the viewport and take the body copy with it. Stated explicitly,
   the column can never be widened by its contents. */
.anatomy {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(var(--s7), 5vw, var(--s8));
}
.anatomy-copy { min-width: 0; max-width: 62ch; }
.anatomy-copy .body { margin-top: var(--s5); }
.anatomy-copy .h2 + .body { margin-top: clamp(var(--s5), 3vw, var(--s6)); }

/* The plate used to hold a 900px minimum so its burned-in labels stayed legible,
   and scroll below that. That is what cropped on a phone: the labels sit in the
   left 55% of the artwork, so a frame seated at the product end showed five
   leader lines pointing at nothing. Worse, a 900px child inside a grid column
   can widen the column on engines that do not honour min-width:0 on the
   scroller — which drags the body copy out with it, and body{overflow-x:clip}
   then hides the evidence by clipping instead of scrolling. Both symptoms, one
   cause. The minimum is gone, and with it the scroll.

   Narrow: the plain render, framed on its own ink. Cropping the annotated
   plate was tried first and cannot work — measured row by row, the five leader
   lines run past the drawing's left edge at 61.0% and terminate on the unit
   itself, as far in as 65.2%, so every cut either leaves stray lines pointing
   at nothing or slices the lamp. The unannotated file has no such problem: its
   ink sits at x 38.9–69.9%, y 10.4–89.8% of 1480x800, and a 5:7 frame at 57%
   lands it dead centre with 3.8% of air either side. */
.plate-frame {
  min-width: 0;
  aspect-ratio: 5 / 7;
  max-width: 360px;
  margin-inline: auto;
  overflow: clip;
}
.plate {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 57% 50%;
}

/* The five callouts as type, in the page's own face. Same rule and rhythm as
   the claims list in the Czech chapter, so it reads as page furniture rather
   than a new component. */
.callouts {
  list-style: none;
  padding: 0;
  margin-top: clamp(var(--s6), 5vw, var(--s7));
  max-width: 32rem;
  margin-inline: auto;
}
.callouts li {
  padding-block: var(--s3);
  border-top: 1px solid var(--line);
  font-size: 0.9375rem;
  letter-spacing: -0.006em;
}
.callouts li:last-child { border-bottom: 1px solid var(--line); }

/* 1000px is where .wrap's content box first clears 900px, which is the width at
   which the artwork's own label type lands at ~11px. At or above it the plate
   is shown whole, exactly as drawn, and never scrolls. */
@media (min-width: 1000px) {
  .plate-frame {
    aspect-ratio: auto;
    max-width: none;
    overflow: visible;
  }
  .plate {
    height: auto;
    object-fit: fill;
  }
  .callouts { display: none; }
}

/* --- Czech market --------------------------------------------------------- */
.czech {
  display: grid;
  gap: clamp(var(--s7), 6vw, var(--s9));
  align-items: center;
}
.czech-copy { min-width: 0; }
.czech-sub {
  margin-top: var(--s4);
  font-size: clamp(1.0625rem, 1rem + 0.34vw, 1.1875rem);
  color: var(--muted);
}
.czech-copy > .body { margin-top: var(--s5); }

.claims {
  list-style: none;
  padding: 0;
  margin-top: clamp(var(--s6), 4vw, var(--s7));
}
.claims li {
  padding-block: var(--s5);
  border-top: 1px solid rgba(47, 46, 46, 0.16);
}
.claims li:last-child { padding-bottom: 0; }
.claims .body { margin-top: var(--s2); color: var(--muted); }

/* A real certification mark: given its own air and its own size, never lined up
   as one of a row of decorative trust badges. */
.badge {
  width: clamp(88px, 11vw, 116px);
  height: auto;
  margin-top: clamp(var(--s6), 4vw, var(--s7));
}

.docs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(var(--s4), 2.4vw, var(--s6));
  min-width: 0;
}
/* Both documents are white pages; a hairline and a soft lift keep them reading
   as physical objects on the tinted surface. */
.doc img {
  width: 100%;
  height: auto;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  box-shadow: 0 18px 40px -24px rgba(18, 24, 31, 0.45);
}

/* --- Closing -------------------------------------------------------------- */
.closing {
  background: var(--dark);
  color: #fff;
  --focus: var(--green);
}
/* The frame is a studio sweep, so it arrives with a ground of its own and two
   edges to answer for. Measured on the shipped render: the top met the Czech
   section at rgb(239,241,242) against rgb(238,240,239) — three levels of
   luminance but opposite hue, blue-leaning above and green-leaning below, which
   is exactly the mismatch that reads as a seam rather than as a join. The
   bottom was worse and simply hard: rgb(245,245,245) straight into rgb(12,12,12),
   a 233-level cut.

   So the sweep is dissolved into whatever it meets instead of butted against
   it. The band takes the surface colour of the section above, and the image
   fades to nothing over its top 18%, which puts the join between two identical
   colours. The bottom fades into the closing black over 6%.

   Both numbers are bounded by where the object is, not chosen by eye. The ink
   sits at y 34.9–79.8% of the source and the green line at 39.6–66.8%. At the
   widest crop, where the band is 2.63:1 and `cover` keeps only the middle 68%
   of the frame, that ink lands at 27.8–93.8% of the band; at phone widths the
   band is narrower than the source, nothing is cropped, and the ink sits at
   34.9–79.8%. 18% and 6% clear the object at both extremes. */
.closing-band {
  position: relative;
  width: 100%;
  aspect-ratio: 1000 / 380;
  min-height: 280px;
  max-height: 66vh;
  overflow: hidden;
  background: var(--surface);
}
.closing-band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 18%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 18%);
}
/* The lower join, in the closing block's own colour. A mask cannot do this one:
   it would dissolve the sweep into the band's background, which is the pale
   surface, and the pale surface would still hit the black on a hard line. */
.closing-band::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  /* A pixel floor as well as a percentage: at phone widths the band is only
     280px tall and a bare 6% is a 17px ramp, which is steep enough to read as
     a dark edge rather than as a fade. 34px holds the slope under 7 levels per
     pixel everywhere, and still stops short of the object's base. */
  height: max(6%, 34px);
  background: linear-gradient(to top, var(--dark) 0%, rgba(12, 12, 12, 0) 100%);
  pointer-events: none;
}
.closing-act {
  display: grid;
  gap: clamp(var(--s5), 3vw, var(--s7));
  align-items: end;
  padding-block: clamp(var(--s7), 7vw, var(--s9));
}
.closing-act .h2 { max-width: 16ch; }
.closing-act .act { margin-top: 0; }

/* --- Footer --------------------------------------------------------------- */
.site-footer {
  --focus: var(--green);
  background: #000;
  color: #fff;
  padding-block: clamp(var(--s8), 7vw, var(--s9)) var(--s7);
}
.footer-grid {
  display: grid;
  gap: clamp(var(--s7), 5vw, var(--s8));
  align-items: start;
}
/* The roundel has a real alpha channel, so it sits on black unframed. */
.footer-mark { width: 42px; height: 42px; }
.footer-word {
  margin-top: var(--s4);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.17em;
}
.footer-about {
  margin-top: var(--s4);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--dim);
  max-width: 34ch;
}
.footer-h { margin-bottom: var(--s4); }
.footer-links {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--s3);
  justify-items: start;
}
.footer-links a {
  color: #fff;
  text-decoration: none;
  font-size: 0.9375rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.24);
  padding-bottom: 2px;
  transition: border-color 200ms var(--ease);
}
.footer-links a:hover { border-bottom-color: #fff; }

.footer-base {
  margin-top: clamp(var(--s7), 5vw, var(--s8));
  padding-top: var(--s5);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.footer-year {
  font-size: 0.8125rem;
  color: var(--dim);
  letter-spacing: 0.04em;
}

/* --- Motion ---------------------------------------------------------------
   Progressive throughout: without JS the .js class is never set, nothing is
   ever hidden, and the page renders complete on the first frame.            */
.js .rise,
.js .fade,
.js [data-load] { opacity: 0; }

.js .rise,
.js [data-load] { transform: translateY(18px); }

/* A technical drawing should not drift. */
.js .fade { transform: none; }

.js .rise.is-in,
.js .fade.is-in,
.js [data-load].is-in {
  opacity: 1;
  transform: none;
}

.js .rise      { transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
.js .fade      { transition: opacity 760ms var(--ease); }
.js [data-load]{ transition: opacity 620ms var(--ease), transform 620ms var(--ease); }

/* The escape hatch, and the reason the reveals are safe at all. CSS transitions
   are throttled to a stop in a background tab and in headless renderers, so
   adding .is-in there sets the target state but never animates to it — the
   element stays at opacity 0 and the section screenshots blank. This class
   removes the hiding mechanism outright rather than asking a transition to
   finish, and script.js sets it on a timeout, on print, and immediately if the
   document is already hidden when it runs. */
.js.reveal-off .rise,
.js.reveal-off .fade,
.js.reveal-off [data-load],
.js.reveal-off .hero-media-img {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
  transition-delay: 0ms !important;
  /* The same reasoning one step further: a scroll-driven animation in a
     renderer that never scrolls is pinned to its start value, so the product
     would photograph 8% under its composed size. */
  animation: none !important;
}

/* Hero load choreography, ordered rather than uniform. */
.js [data-load="1"] { transition-delay:  60ms; }
.js [data-load="2"] { transition-delay: 130ms; }
.js [data-load="3"] { transition-delay: 220ms; }
.js [data-load="4"] { transition-delay: 310ms; }

/* --- The hero, pushing in --------------------------------------------------
   The one piece of motion on the page tied to the reader rather than to a
   moment: the frame closes in by 5% as the hero scrolls away. It grows and
   never shrinks, because the picture is sized to cover its box exactly —
   anything under 1.0 would pull its edges inside the frame and show the ground
   behind it. 5% over a screen of scrolling is under the threshold where you
   would call it an animation; you register that the room came closer.

   Where the browser has scroll-driven animations this runs from CSS alone, off
   the main thread, and there is no scroll listener at all. The timeline is
   named on the frame rather than taken from the image, because the image is
   the thing being transformed and a transformed subject would feed its own
   progress back into the timeline. script.js drives the same curve by hand for
   browsers without it, and does nothing at all here. */
@keyframes hero-push {
  from { transform: scale(1); }
  to   { transform: scale(1.05); }
}

.js .hero-media-img { will-change: transform; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .js .hero-media {
      view-timeline-name: --hero-media;
      view-timeline-axis: block;
    }
    .js .hero-media-img {
      animation: hero-push linear both;
      animation-timeline: --hero-media;
      /* `exit` starts the moment the frame's top edge reaches the top of the
         viewport, which is the first pixel of scroll that actually takes the
         hero away. */
      animation-range-start: exit 0%;
      animation-range-end: exit 100%;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Composed size, no scroll animation, nothing for script.js to drive. The
     !important also outranks the inline transform of the JS fallback. */
  .js .hero-media-img {
    transform: none !important;
    animation: none !important;
    will-change: auto;
  }
  .js .rise, .js .fade, .js [data-load] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    transition-delay: 0ms !important;
  }
  .tile:hover img { transform: none; }
  .skip { transition: none; }
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Print never scrolls, so nothing may depend on an intersection to appear. */
@media print {
  .js .rise, .js .fade, .js [data-load], .js .hero-media-img {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  /* A printed page has no viewport to fill. */
  .hero { min-height: 0; }
  .site-header { position: static; }
}

/* ==========================================================================
   Responsive — single column first, then the composed layouts.
   ========================================================================== */

/* Mobile gallery: one column, and each card keeps roughly the shape it was
   shot in. Forcing a 3:2 restaurant pass into a 4:5 card would throw away the
   brass and the plates either side of the unit, which is the whole reason that
   frame exists. */
.tile { aspect-ratio: 4 / 5; }             /* the three portraits: 1, 2, 3 */
.tile--4, .tile--7 { aspect-ratio: 3 / 2; }
.tile--5 { aspect-ratio: 1 / 1; }
.tile--8 { aspect-ratio: 5 / 4; }
.tile--grad { aspect-ratio: auto; min-height: 300px; }

/* Keep the header honest on small screens: the mark and the language switch
   are the only two things that have to be there on a single page. */
@media (max-width: 639px) {
  .nav { display: none; }
  .bar { justify-content: space-between; }
}

/* Two columns, with the two landscapes taken full width so they keep their
   proportion instead of being squeezed into half a row. Placed explicitly:
   auto-flow would strand a card beside a hole every time a full-width tile
   lands on an odd column. */
@media (min-width: 600px) and (max-width: 899px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tile--1 { grid-column: 1; grid-row: 1; }
  .tile--2 { grid-column: 2; grid-row: 1; }
  .tile--4 { grid-column: 1 / -1; grid-row: 2; aspect-ratio: 16 / 9; }
  .tile--3 { grid-column: 1; grid-row: 3; }
  .tile--5 { grid-column: 2; grid-row: 3; aspect-ratio: 4 / 5; }
  .tile--7 { grid-column: 1 / -1; grid-row: 4; aspect-ratio: 16 / 9; }
  .tile--8 { grid-column: 1; grid-row: 5; aspect-ratio: 4 / 5; }
  .tile--6 { grid-column: 2; grid-row: 5; aspect-ratio: auto; }
}

@media (min-width: 820px) {
  .czech   { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
  .footer-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .closing-act { grid-template-columns: minmax(0, 1fr) auto; }
}

/* The Czech spec runs about twice the length of the English one, and above
   900px the card is only a 3-column slot — 194px wide at the breakpoint
   itself, which is where it overflowed. Measured, not guessed: the type is
   scaled to the slot across this band so the longest string still clears the
   card's own padding at its narrowest. English is untouched. */
@media (min-width: 900px) {
  .cap-line--cs { font-size: clamp(0.8125rem, 0.2rem + 0.78vw, 1.1875rem); }
}

@media (min-width: 900px) {
  /* Twelve columns, three rows, 5-3-4 over 5-4-3 over 6-6. The first two rows
     mirror each other rather than repeat, and the last resolves square — so no
     row reads as a line of equal cards, and the eye is given somewhere to stop.

     The spans are chosen against each frame's own proportion, not for tidiness.
     At the 1104px container a 5-column tile is 453px and the row is 560, which
     is 0.81 — the kitchen frame's native 0.806, so it lands essentially
     uncropped. The 3-column slot is a deliberate tall slice, and it holds the
     bedside frame, where the subject is dead centre and the crop costs nothing.
     The two landscapes get the 6- and 7-column slots, where 1.49 survives. */
  .grid {
    grid-template-columns: repeat(12, minmax(0, 1fr));
    grid-template-rows:
      minmax(clamp(380px, 44vw, 560px), auto)
      minmax(clamp(300px, 33vw, 420px), auto)
      minmax(clamp(320px, 37vw, 480px), auto);
  }
  .tile { aspect-ratio: auto; }
  .tile--grad { min-height: 0; }

  .tile--1 { grid-column:  1 / 6;  grid-row: 1; }
  .tile--2 { grid-column:  6 / 9;  grid-row: 1; }
  .tile--3 { grid-column:  9 / 13; grid-row: 1; }

  .tile--4 { grid-column:  1 / 6;  grid-row: 2; }
  .tile--5 { grid-column:  6 / 10; grid-row: 2; }
  .tile--6 { grid-column: 10 / 13; grid-row: 2; }

  .tile--7 { grid-column:  1 / 7;  grid-row: 3; }
  .tile--8 { grid-column:  7 / 13; grid-row: 3; }
}

/* --- The hero, copy on the picture -----------------------------------------
   Above this width the picture takes the screen and the copy sits on it. The
   hero is the viewport minus the header, so the frame ends exactly on the fold.

   The scrim is the only thing laid over the photograph and it is a corner, not
   a band: `to top right` puts its darkest point at the bottom-left, where the
   copy is, and takes it to nothing by 64% of the diagonal. Measured on the
   shipped render, that leaves the unit, its light ring, the greens, the man
   and the entire top of the frame untouched, and it is the reason the copy can
   be white over a counter whose own luminance is 0.47–0.67. */
@media (min-width: 1024px) {
  .hero {
    height: calc(100vh - var(--header-h));
    height: calc(100svh - var(--header-h));
    min-height: 520px;
    /* The frame is 2.12:1 and the crop is anchored left, so the man's right
       edge (image x 80%) only survives while the hero stays wider than 1.69:1.
       On a tall screen at 1024 the full viewport height is 705px, which is
       1.45:1, and it cuts him in half — measured, 59% of him left in frame.
       Capping the height at 58vw holds the ratio and keeps him whole; on wide
       screens the viewport is already shorter than this and nothing changes. */
    max-height: 58vw;
    display: flex;
    align-items: flex-end;
  }

  .hero-media {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
  }
  /* Anchored left: it keeps the counter the copy needs, and still holds the
     unit (image x 29–43%) and the man (52–80%) inside the frame. */
  .hero-media-img { object-position: 0% 50%; }

  /* The scrim is white, not black, and that is the whole argument. White text
     on this counter needs roughly 50% black to clear 4.5:1, and 50% black in
     the bottom-left corner lands on the unit: measured, a dark corner scrim
     strong enough to carry the copy left the PonicTank at 0.32 of its own
     luminance. Washing the counter up instead of down carries dark type just
     as well and darkens nothing at all — on the shipped render the unit
     measures 1.00–1.07 of its unscrimmed luminance, the man 1.00, the top of
     the frame 1.05. The picture is never dimmed anywhere.

     The horizontal mask is what makes that true. It is opaque to 26% of the
     width and gone by 38%; the unit begins at 36%. Everything to the right of
     the copy — the unit, the greens, the man, the ovens — is the photograph
     untouched. */
  .hero-scrim {
    display: block;
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
      rgba(255, 255, 255, 0.94) 0%,
      rgba(255, 255, 255, 0.88) 34%,
      rgba(255, 255, 255, 0.70) 54%,
      rgba(255, 255, 255, 0.32) 72%,
      rgba(255, 255, 255, 0) 88%);
    -webkit-mask-image: linear-gradient(to right, #000 0%, #000 26%, transparent 38%);
    mask-image: linear-gradient(to right, #000 0%, #000 26%, transparent 38%);
  }

  /* Off the 1200 grid and onto the viewport's own margin. At 1440 that is 120px
     the copy did not have, and it is what moves the headline's right edge from
     37% of the screen to 29% — clear of both the unit and the mask's falloff. */
  .hero-copy {
    max-width: none;
    padding-top: 0;
    padding-bottom: clamp(var(--s7), 7vh, var(--s9));
  }
  /* Both measures are bound to the viewport, not to the text, because the
     scrim's mask is a percentage and the copy is not: at 1024 a 366px line is
     40% of the screen and runs out past the wash into bare photograph, where
     it measured 2.4:1. 30vw keeps every line inside the mask and short of the
     unit, which begins at 36% of the width. */
  .hero .display {
    font-size: clamp(2.25rem, 0.6rem + 3.2vw, 3.5rem);
    max-width: min(12ch, 30vw);
  }
  /* A shade darker than the light-ground muted, measured over the photograph
     rather than over paper. */
  .hero .hero-sub { color: #3d3c3c; max-width: min(34ch, 30vw); }
  .hero .price    { color: #4a4848; }
}


/* ---------------------------------------------------------------- the rooms
   Seven photographs, mixed aspect by design (4:5, 3:2, 1:1, 5:4), so the grid
   lets each keep its own frame instead of cropping them all to one shape.
   Dark ground: every frame is lit by the product, and a white page would
   fight that. */
.chapter--rooms { background: #0d0f0e; color: #f4f6f5; padding-block: clamp(72px, 10vw, 160px); }
.chapter--rooms .h2 { color: #fff; }
.chapter--rooms .furn-mark { color: rgba(244,246,245,.5); }

.g-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(10px, 1.4vw, 20px);
  margin-top: clamp(28px, 4vw, 56px);
}
.g-tile { position: relative; margin: 0; overflow: hidden; background: #111; border-radius: 2px; }
.g-tile img { display: block; width: 100%; height: 100%; object-fit: cover; }

.g-tile.g--tall { grid-column: span 4; aspect-ratio: 4 / 5; }
.g-tile.g--sq   { grid-column: span 4; aspect-ratio: 1 / 1; }
.g-tile.g--wide { grid-column: span 6; aspect-ratio: 3 / 2; }

/* The caption sits on the photograph, over a gradient that only darkens the
   strip it occupies — the frames stay legible at full strength. */
.chapter--rooms .meta--pin {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.2em 1em .9em;
  color: #fff; font-size: clamp(10px, .78vw, 12px);
  letter-spacing: .09em; text-transform: uppercase;
  background: linear-gradient(to top, rgba(0,0,0,.62), rgba(0,0,0,0));
}

@media (max-width: 900px) {
  .g-tile.g--tall, .g-tile.g--sq { grid-column: span 6; }
  .g-tile.g--wide { grid-column: span 12; }
}
@media (max-width: 560px) {
  .g-tile.g--tall, .g-tile.g--sq, .g-tile.g--wide { grid-column: span 12; }
}

/* The white studio frame closes the run full-width — it is the one image with
   a white ground, so it reads as a break rather than another room. */
.g-tile.g--band { grid-column: span 12; aspect-ratio: 16 / 7; background: #fff; }
.g-tile.g--band img { object-fit: contain; }
.g-tile.g--band .meta--pin { color: #2f2e2e; background: none; }
@media (max-width: 560px) { .g-tile.g--band { aspect-ratio: 4 / 3; } }

/* --card-inset-fix
   The spec card's copy was sitting hard against the top-left corner with two
   thirds of the card empty beneath it. It is one tile in a grid of pinned
   captions, so it reads correctly bottom-aligned with the same optical inset —
   and the Czech string, which is roughly twice the English, sets the height. */
.tile--grad .face--front {
  display: flex;
  align-items: flex-end;
  padding: clamp(20px, 2.4vw, 32px);
}
.tile--grad .cap-line { margin: 0; max-width: 26ch; }

/* --closing-seam-fade
   The closing frame is a white studio sweep whose ground is a shade off the
   page white, so butting it against the section produced a visible step across
   the full viewport. The image is masked to nothing at both edges: the ground
   dissolves into the page and the product and its green line stay untouched. */
.closing-band { background: #fff; }
.closing-band img {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
}

/* The three sites share a founder and little else, so the connection is stated
   plainly here as well as in structured data — a schema claim with no on-page
   counterpart is the kind search engines discount. */
.founder { margin-top: 10px; font-size: 0.8125rem; line-height: 1.55; color: #605e5e; }
.founder__also { display: block; margin-top: 3px; }
.founder__also a { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(47,46,46,.28); }
.founder__also a:hover { color: #2f2e2e; border-bottom-color: currentColor; }


/* ==========================================================================
   Synth footer — the SynthCard material from trusynth.com.
   Ground #17120a, rim rgba(216,196,142,.16), the silk-brass WebGL foil, and
   the etched mark. Values are the source's own; the card fills the footer
   instead of holding the hero's 1.586 card ratio.
   ========================================================================== */
.synth {
  padding: clamp(20px, 3vw, 40px) clamp(16px, 4vw, 48px) clamp(28px, 4vw, 56px);
  background: transparent;
}

.synth__card {
  position: relative;
  container-type: inline-size;
  width: 100%;
  max-width: none;
  margin: 0;
  border-radius: clamp(16px, 2.6vw, 28px);
  overflow: hidden;
  isolation: isolate;
  background: #17120a;
  border: 1px solid rgba(216, 196, 142, 0.16);
  box-shadow:
    0 40px 120px rgba(0, 0, 0, 0.85),
    0 8px 30px rgba(0, 0, 0, 0.6),
    inset 0 0 0 1px rgba(242, 232, 200, 0.14);
}
/* The lit top edge and shadowed bottom edge that give the metal its thickness. */
.synth__card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 246, 227, 0.35),
    inset 0 -1px 0 rgba(20, 14, 4, 0.5);
  z-index: 2;
}

.synth__foil {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
}
/* Without WebGL the card keeps its ground and rim and simply does not shimmer. */
.synth__card.is-flat .synth__foil { display: none; }

/* The content sits on the foil, in the source's own ink. */
.synth__face {
  position: relative;
  z-index: 1;
  padding: clamp(34px, 6vw, 76px) clamp(20px, 4vw, 48px);
  text-align: center;
  color: #2b2210;
}
.synth__mark {
  width: clamp(96px, 11vw, 148px);
  height: auto;
  margin: 0 auto clamp(16px, 2.2vw, 24px);
}
.synth__label {
  margin: 0 0 10px;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
  font-size: clamp(9px, 0.95vw, 11px);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  line-height: 1.9;
  color: rgba(43, 34, 16, 0.72);
}
.synth__label b { font-weight: 700; color: #2b2210; }
.synth__body {
  max-width: 54ch;
  margin: 0 auto clamp(18px, 2.4vw, 26px);
  font-size: 0.9375rem;
  line-height: 1.6;
  color: rgba(43, 34, 16, 0.82);
}
.synth__link {
  display: block;
  width: var(--etch-w, min(46cqw, 380px));
  margin: clamp(26px, 4vw, 54px) auto 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: clamp(9px, 0.95vw, 11px);
  font-weight: 600;
  /* Ranged to the mark above it: a fixed width plus text-align-last stretches
     the single line so its ends sit under the logo's ends. The tracking is a
     floor — justification adds to it, never below it. */
  letter-spacing: 0.14em;
  text-align: justify;
  text-align-last: justify;
  text-transform: uppercase;
  color: rgba(43, 34, 16, 0.78);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: color 240ms cubic-bezier(0.16, 1, 0.3, 1);
}
/* No ring on a mouse click. :focus-visible fires for keyboard only, so the
   keyboard path keeps an indicator — removing that outright would strand
   anyone not using a pointer. */
.synth__link:focus { outline: none; }
.synth__link:hover { background: rgba(242, 232, 200, 0.42); border-color: rgba(43, 34, 16, 0.6); }
.synth__link:focus-visible { outline: 2px solid #2b2210; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .synth__link { transition: none; } }

/* The mark is embossed by the shader, not painted over it: the etch in the
   foil is the logo. The <img> stays in the markup for the no-WebGL fallback
   and for assistive tech, and is hidden once the foil is live — two copies of
   the same mark, one stamped and one flat, is what made it read as a smudge. */
.synth__card:not(.is-flat) .synth__mark { display: none; }
.synth__card.is-flat .synth__mark {
  display: block;
  filter: brightness(0) invert(1);
  opacity: 0.86;
}
/* With the etch centred in the card, the copy needs room to clear it. */
.synth__card:not(.is-flat) .synth__face { padding-top: clamp(96px, 15vw, 190px); }

/* The card carries the etched mark and one link. Nothing else earns a place,
   so the face is sized to those two rather than to copy that is no longer here. */
.synth__card:not(.is-flat) .synth__face { padding-top: clamp(112px, 17vw, 210px); }
.synth__face { padding-bottom: clamp(28px, 4vw, 52px); }

.synth__card a, .synth__card button { -webkit-tap-highlight-color: transparent; }
