/* The site.
 *
 * Values come from design/tokens.css, which the panel reads too - they are
 * on the asset path, loaded first, and not duplicated here. What is here
 * is how a page uses them, which is not how a 402px module in someone
 * else's sidebar uses them: the system is shared, the composition is not.
 *
 * Same rules as the panel: no cards, no shadows, no radii, separation by
 * space and three rule weights, one accent meaning one thing.
 */

@font-face {
  font-family: 'KeyParts Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-latin-fa398884.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'KeyParts Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-latin-ext-6a06a286.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'KeyParts Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-400-latin-c6016505.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'KeyParts Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-500-latin-7c1dc074.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'KeyParts Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-500-latin-ext-e1b7a5f7.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

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

html {
  color-scheme: light dark;
  background: var(--page);
  /* Propshaft rewrites this url to the digested asset; a custom property
     is the only way to hand the same file to a rule further down without
     writing the path twice. */
  --paper: url("/assets/paper-983b5d1a.png");
}

body {
  margin: 0;
  padding: 0 var(--s3);
  background: var(--page);
  color: var(--ink);
  font: 400 16px/1.6 var(--sans);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

/* The measure is 660px and stays 660px. What the wide layout adds is a
   margin column beside it for the section labels, not a wider line. */
.wrap {
  max-width: 660px;
  margin: 0 auto;
}

/* --------------------------------------------------------------------------
   Masthead
   ----------------------------------------------------------------------- */

.top {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s4) 0 var(--s2);
  border-bottom: 1.5px solid var(--rule-hard);
}

.top__mark { flex: none; height: 15px; width: auto; }

.top__name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-decoration: none;
}

.top__nav {
  margin-left: auto;
  display: flex;
  gap: var(--s3);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.top__nav a { color: var(--ink-3); text-decoration: none; }
.top__nav a:hover { color: var(--ink); }

/* --------------------------------------------------------------------------
   Page
   ----------------------------------------------------------------------- */

h1 {
  margin: var(--s6) 0 0;
  font-size: 40px;
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.lede {
  margin: var(--s3) 0 0;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-2);
}

/* Apparatus, not a heading in the visual hierarchy: it names the section
   rather than announcing it. Narrow, it has to separate as well as name,
   so it keeps a rule; wide, it moves into the margin and the rule goes,
   because a label standing outside the measure is already a separation. */
main > section { margin-top: var(--s6); }

h2 {
  margin: 0;
  padding-bottom: var(--s1);
  border-bottom: 1px solid var(--rule);
  font-size: 13px;
  font-family: var(--mono);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* The step the page did not have. Between the 18px lede and the 40px
   headline there was nothing, so after the first screen the page never
   changed register again - every section below the fold was 16px text
   under an 13px label. */
h3 {
  margin: var(--s5) 0 0;
  font-size: 26px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.025em;
}

p { margin: var(--s2) 0 0; }
p, li { color: var(--ink-2); }
h1 + .lede { color: var(--ink-2); }

a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
/* Hover thickens the underline. It used to turn the link vermilion,
   which told the reader that the pointer was over a moment worth
   watching. The accent is not a state. */
a:hover { text-decoration-thickness: 2px; }

strong { font-weight: 600; color: var(--ink); }

ul, ol { margin: var(--s2) 0 0; padding: 0; list-style: none; }

li {
  position: relative;
  margin-top: var(--s2);
  padding-left: var(--s3);
}

li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 11px;
  width: 6px;
  height: 1.5px;
  background: var(--rule-hard);
}

code {
  font-family: var(--mono);
  font-size: 0.88em;
  color: var(--ink);
}

/* A numbered sequence, the numbers in the gutter the way the panel hangs
   its timecodes. */
.steps { counter-reset: step; }

.steps li { padding-left: var(--s5); margin-top: var(--s5); }
.steps li:first-child { margin-top: var(--s3); }
.steps h3 { margin: 0; }
.steps p { margin-top: var(--s1); }

.steps li::before {
  counter-increment: step;
  content: counter(step);
  /* On the cap line of a 26px heading, not the top of its line box. */
  top: 7px;
  width: auto;
  height: auto;
  background: none;
  font-family: var(--mono);
  font-size: 13px;
  /* Not the accent. The accent means "worth watching" and nothing else;
     spending it on "item three" teaches the reader the wrong thing two
     screens before they meet the panel that depends on it. */
  color: var(--ink-3);
}

.note {
  margin: var(--s3) 0 0;
  padding-left: var(--s2);
  border-left: 2px solid var(--rule);
  font-size: 15px;
}

/* Page rank, the same rule as the masthead's: the two that frame the
   page are one weight and one length, and nothing else on the page draws
   a horizontal line at all. */
.foot {
  margin: var(--s7) 0 0;
  padding: var(--s2) 0 var(--s5);
  border-top: 1.5px solid var(--rule-hard);
  display: flex;
  gap: var(--s3);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.foot a { color: var(--ink-3); text-decoration: none; }
.foot a:hover { color: var(--ink); }
.foot__spacer { margin-left: auto; }


/* --------------------------------------------------------------------------
   The film, to scale

   The same bar the panel draws, at the scale of a page: the real sections
   of the real video in the screenshot below it, in their real proportions,
   with the four the model marked. Not a pattern that looks like sections.

   The head crosses it in fourteen seconds. Ahead of the head the sections
   are pale; behind it they are there. That is the product's whole claim in
   one gesture, and it is the only moving thing on the site.

   No canvas. Eight rectangles and a moving rule are eight rectangles and a
   moving rule, and the DOM draws those crisply at any density for nothing.

   And no caption. The bar it used to carry - the film's length, its
   sections, how many are worth watching - is printed by the panel eighty
   pixels lower, off the same numbers. A graphic that needs a line of type
   to say what it is has not said it.
   ----------------------------------------------------------------------- */

.filmbar { margin: var(--s4) 0 0; }

/* Apparatus for the bar, in the margin where the section labels are.
   One fact a line. */
.filmbar__tally span { display: block; }

.filmbar__tally {
  margin: 0 0 var(--s1);
  line-height: 1.5;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.filmbar__track {
  position: relative;
  height: var(--s4);
  overflow: hidden;
  /* The film's extent, always. A border is painted outside the padding
     box, so the wash - inset: 0 - never covers it: whatever the head is
     doing, the length of the film is on the page. Same weight and same
     length as the rules that frame the page, because it is the same rank
     of statement. */
  border-bottom: 1.5px solid var(--rule-hard);
}

/* Same construction as the panel's bar: the divisions are gaps in one ink,
   not a second tone, so what the eye reads is where sections begin. */
.filmbar__seg {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--tint-2);
  border-right: 2px solid transparent;
  background-clip: padding-box;
}

.filmbar__seg--key { background-color: var(--accent); }

/* What has not been read yet, and the head at its edge. */
.filmbar__wash {
  position: absolute;
  inset: 0;
  background: var(--page);
  opacity: 0.55;
  border-left: 2px solid var(--ink);
  animation: filmbar-sweep 14s linear infinite;
}

/* Across in seven seconds, four resolved, then the ink lifts again while
   the wash is off-screen - so the loop has no snap back. It used to cross
   in ten of fourteen seconds and stand resolved for under two, which put
   the bar in its least legible state most of the time. */
@keyframes filmbar-sweep {
  0%   { transform: translateX(0);    opacity: 0.55; }
  50%  { transform: translateX(100%); opacity: 0.55; }
  80%  { transform: translateX(100%); opacity: 0; }
  81%  { transform: translateX(0);    opacity: 0; }
  100% { transform: translateX(0);    opacity: 0.55; }
}

/* --------------------------------------------------------------------------
   The panel, photographed
   ----------------------------------------------------------------------- */

/* Life size, with the caption in the gutter beside it rather than the
   gutter left empty: 402px of screenshot in a 660px measure was 258px of
   nothing running down the page's most persuasive asset. */
.panelshot {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  margin: var(--s5) 0 0;
}

.panelshot__img {
  display: block;
  width: 402px;
  max-width: 100%;
  height: auto;
  flex: none;
}

.panelshot__img--dark { display: none; }

.panelshot__note {
  flex: 1;
  min-width: 140px;
  padding-top: 2px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-3);
}

/* Paper. The grain plate over everything at a strength you notice only by
   removing it: multiply on white darkens the tooth, screen on black lifts
   it, which is what those two inks actually do. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: var(--paper);
  background-size: 200px 200px;
  mix-blend-mode: multiply;
}

@media (prefers-color-scheme: dark) {
  .panelshot__img { display: none; }
  .panelshot__img--dark { display: block; }

  /* On black the same plate has to be inverted to do the same job. */
  body::after { mix-blend-mode: screen; filter: invert(1); opacity: 0.55; }
}

/* The bar still says what it has to say standing still - and standing
   still it says the true thing, which is the film fully resolved. */
@media (prefers-reduced-motion: reduce) {
  .filmbar__wash { display: none; }
}

@media (max-width: 560px) {
  .panelshot { flex-wrap: wrap; gap: var(--s2); }
}

/* --------------------------------------------------------------------------
   Wide: the labels move out of the measure

   Aicher's margin column. A mono label smaller than the text it organises
   reads as apparatus when it stands outside the measure and as fine print
   when it is stacked inside it - same type, same size, opposite effect.
   Below this width there is no room for a margin, so the labels come back
   into the column and take their rule back with them.
   ----------------------------------------------------------------------- */

@media (min-width: 881px) {
  .wrap { max-width: 824px; }

  /* The grid is the whole page, not just the article, so the masthead and
     the footer keep the same left edge as the text. A frame wider than
     everything it frames is two left edges and a reason for neither. */
  .wrap {
    display: grid;
    grid-template-columns: 136px minmax(0, 1fr);
    column-gap: var(--s4);
  }

  .wrap > * { grid-column: 2; }

  /* .wrap > main, not main: the rule above is a class selector and would
     otherwise win, pinning the article into the text column and taking
     the margin away from the labels inside it. */
  .wrap > main {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
  }

  main > * { grid-column: 2; }

  /* Subgrid, so every section's label hangs off the same margin rather
     than off its own. */
  main > section {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
  }

  main > section > * { grid-column: 2; }

  /* Its first line, not the top of its box: the label sits on the same
     line as the text it names. */
  main > section > *:nth-child(2) { margin-top: 0; }

  /* The bar hangs its tally in the same margin, on the same line. */
  .filmbar {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
  }

  .filmbar__track { grid-column: 2; }

  .filmbar__tally {
    grid-column: 1;
    margin: 0;
    padding: 5px 0 0;
    text-align: right;
    margin-right: -0.1em;
  }

  main > section > h2 {
    grid-column: 1;
    /* Optical, not a gap: it drops the label onto the first line of the
       text beside it. The one vertical value on the page that is not
       from the scale, because the scale cannot know a cap height. */
    padding: 5px 0 0;
    border: 0;
    text-align: right;
    /* The tracking puts a space after the last letter; without this the
       label's right edge is a letter-space short of the text column. */
    margin-right: -0.14em;
  }
}
