@charset "utf-8";
/* ===========================================================================
   NEWSPORTVISION — components
   =========================================================================== */

/* --- Canvas & grid -------------------------------------------------------- */
.canvas { position: relative; isolation: isolate; }
.wrap {
  width: var(--content);
  margin-inline: auto;
  position: relative;
}
.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  column-gap: var(--gutter);
}
.bleed { width: var(--vw); margin-left: calc(50% - var(--vw) / 2); }

/* Column placement helpers. On phones (6 cols) everything falls to full width
   unless it explicitly opts out with .keep. */
.c1{grid-column-end:span 1}.c2{grid-column-end:span 2}.c3{grid-column-end:span 3}
.c4{grid-column-end:span 4}.c5{grid-column-end:span 5}.c6{grid-column-end:span 6}
.c7{grid-column-end:span 7}.c8{grid-column-end:span 8}.c9{grid-column-end:span 9}
.c10{grid-column-end:span 10}.c11{grid-column-end:span 11}.c12{grid-column-end:span 12}
.s1{grid-column-start:1}.s2{grid-column-start:2}.s3{grid-column-start:3}.s4{grid-column-start:4}
.s5{grid-column-start:5}.s6{grid-column-start:6}.s7{grid-column-start:7}
.s8{grid-column-start:8}.s9{grid-column-start:9}.s10{grid-column-start:10}

@media (max-width: 767px) {
  .c1,.c2,.c3,.c4,.c5,.c6,.c7,.c8,.c9,.c10,.c11,.c12 { grid-column: 1 / -1 !important; }
  .s1,.s2,.s3,.s4,.s5,.s6,.s7,.s8,.s9,.s10 { grid-column-start: auto; }
  .keep-half { grid-column: span 3 !important; }
}

/* Columns that sit side by side on a wide screen stack below this, and a stack
   needs the air a gutter gave it: without it a photograph lands flush on the
   line of type beneath and reads as covering it. Only grids that actually wrap
   to a second row are affected. */
@media (max-width: 1023px) {
  .grid { row-gap: var(--space-3); }
}

/* The grid, made visible. A hairline column field that sits behind the whole
   canvas — the way a layout grid shows through thin paper. */
.gridlines {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: .16;
}
.gridlines i {
  position: absolute; top: 0; bottom: 0;
  width: var(--rule-hair);
  background: currentColor;
}

/* --- The rule -------------------------------------------------------------
   The logo's white bar, generalised. This is the site's single most reused
   object: divider, nav state, progress, mask edge, button fill. */
.rule { display: block; height: var(--rule-hair); background: var(--rule-color); border: 0; }
.rule--thin { height: var(--rule-thin); }
.rule--bar  { height: var(--rule-bar); }
.rule--white{ background: var(--nsv-white); }
.rule--ink  { background: var(--nsv-ink); }
.rule--yellow { background: var(--nsv-yellow); }

/* A rule that draws itself across its track when it enters. */
.rule--draw { transform-origin: left center; }
.js [data-reveal] .rule--draw,
.js .rule--draw[data-reveal] { transform: scaleX(0); }
.is-in .rule--draw, .rule--draw.is-in { transform: scaleX(1); transition: transform var(--t-cine) var(--ease-rule); }

/* --- The justified line ---------------------------------------------------
   NEW ▁▁▁ / SPORT / VISION. Every display line fills its measure; where the
   words run out, the rule takes over. .jline is the "words + rule" case,
   [data-justify] is the "stretch the words" case (handled in justify.js via
   Archivo's width axis). */
.jline {
  display: flex;
  align-items: baseline;
  gap: var(--atom);
  width: 100%;
}
.jline > .jline__t { flex: 0 0 auto; }
.jline__rule {
  flex: 1 1 auto;
  min-width: var(--atom);
  height: var(--rule-bar);
  background: var(--rule-color);
  /* Sit on the baseline, and tuck back under the preceding glyph by the same
     proportion the bar tucks under the W in the logo (5/111 of its width). */
  margin-left: calc(var(--rule-bar) * -0.45);
  align-self: baseline;
  position: relative;
  top: calc(var(--rule-bar) * -0.06);
}
.jline--white .jline__rule { background: var(--nsv-white); }

/* --- Editorial numbering -------------------------------------------------- */
.idx {
  font-family: var(--font-meta);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-quiet);
}

/* --- Section head --------------------------------------------------------- */
.shead { display: flex; align-items: baseline; gap: var(--space-2); padding-bottom: var(--space-1); }
.shead .rule { flex: 1 1 auto; }

/* --- Text links -----------------------------------------------------------
   The underline is the logo rule, drawn from the left. On the way out it
   leaves from the right, so the gesture never simply rewinds. */
.tlink {
  position: relative;
  display: inline-block;
  padding-bottom: .1em;
  background-image: linear-gradient(var(--rule-color), var(--rule-color));
  background-repeat: no-repeat;
  background-position: 100% 100%;
  background-size: 0% var(--rule-thin);
  transition: background-size var(--t-ui) var(--ease-editorial),
              color var(--t-micro) linear;
}
.tlink:focus-visible {
  background-position: 0% 100%;
  background-size: 100% var(--rule-thin);
}
@media (hover: hover) { .tlink:hover {
  background-position: 0% 100%;
  background-size: 100% var(--rule-thin);
} }

/* Inverting link — used sparingly, on the footer and menu. */
.tlink--invert {
  background: none;
  padding: .04em .18em;
  margin-inline: -.18em;
  transition: background-color var(--t-micro) var(--ease-enter),
              color var(--t-micro) var(--ease-enter);
}
.tlink--invert:focus-visible {
  background-color: var(--fg);
  color: var(--bg);
}
@media (hover: hover) { .tlink--invert:hover {
  background-color: var(--fg);
  color: var(--bg);
} }

/* --- Large action ---------------------------------------------------------
   An entire grid row behaving as a button. The yellow field grows from the
   side the pointer entered; the arrow crosses the full column, not 4px. */
.action {
  --action-fg: var(--fg);
  --action-bg: transparent;
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: clamp(20px, 2.2vw, 42px) 0;
  border-top: var(--rule-thin) solid var(--rule-color);
  border-bottom: var(--rule-thin) solid var(--rule-color);
  color: var(--action-fg);
  overflow: clip;
  isolation: isolate;
}
.action + .action { border-top: 0; }
.action::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--nsv-yellow);
  transform: scaleX(0);
  transform-origin: var(--origin, left) center;
  transition: transform var(--t-ui) var(--ease-editorial);
}
.action:focus-visible::before { transform: scaleX(1); }
@media (hover: hover) { .action:hover::before { transform: scaleX(1); } }
.action:focus-visible { --action-fg: var(--nsv-ink); }
@media (hover: hover) { .action:hover { --action-fg: var(--nsv-ink); } }
.on-yellow .action::before { background: var(--nsv-ink); }
.on-yellow .action:focus-visible { --action-fg: var(--nsv-yellow); }
@media (hover: hover) { .on-yellow .action:hover { --action-fg: var(--nsv-yellow); } }

.action__label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h3);
  line-height: 1;
  letter-spacing: var(--track-h);
  text-transform: uppercase;
  padding-left: 0;
  transition: padding-left var(--t-ui) var(--ease-editorial);
}
.action:focus-visible .action__label {
  padding-left: clamp(12px, 1.4vw, 28px);
}
@media (hover: hover) { .action:hover .action__label {
  padding-left: clamp(12px, 1.4vw, 28px);
} }
.action__arrow {
  width: clamp(44px, 5vw, 92px);
  height: var(--rule-bar);
  position: relative;
  flex: 0 0 auto;
  margin-right: 0;
  transition: margin-right var(--t-ui) var(--ease-editorial);
}
.action__arrow::before {
  content: "";
  position: absolute; inset: 0;
  background: currentColor;
  clip-path: polygon(0 35%, 62% 35%, 62% 0, 100% 50%, 62% 100%, 62% 65%, 0 65%);
}
.action:focus-visible .action__arrow {
  margin-right: calc(var(--page-x) * -0.5);
}
@media (hover: hover) { .action:hover .action__arrow {
  margin-right: calc(var(--page-x) * -0.5);
} }

/* --- Image frames ---------------------------------------------------------
   Images are layout, not cards. The frame clips; the image inside counter-
   moves, so the photograph and its window are never rigidly locked.

   Three motions touch a photograph, and each owns its own property on its own
   element so they can never overwrite one another:
     the frame      clips (overflow: clip — not hidden, which would make the
                    frame a scroll container and stall the scroll timeline)
     <picture>      the entrance: clip-path and scale
     <img>          the drift: translate, and its arrival: opacity */
.frame {
  position: relative;
  overflow: clip;
  background-color: var(--nsv-steel-line);
  /* A 20px print of the photograph stands in until the real one arrives, so a
     lazily-loaded frame is never an empty grey rectangle. */
  background-image: var(--lqip, none);
  background-size: cover;
  background-position: var(--focus, 50% 50%);
}
.frame picture { display: block; width: 100%; height: 100%; }
.frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
  display: block;
}
/* A photograph arrives over its own print rather than popping in. Marked by
   the head script as each one loads. */
.js .frame img { opacity: 0; transition: opacity 240ms var(--ease-enter); }
.js .frame img.is-loaded { opacity: 1; }

/* Counter-motion. The photograph is cut 8% taller than its window and centred
   on it, then travels through that margin as the frame crosses the screen —
   3.5% of its own height each way, so an edge can never come into view.
   Driven by the scroll position itself where the browser supports it: it runs
   on the compositor, exactly in step with the finger, with no script at all. */
.frame[data-counter] img { position: relative; top: -4%; height: 108%; }
@keyframes counter {
  from { translate: 0 -3.5%; }
  to   { translate: 0 3.5%; }
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .frame[data-counter] img {
      animation: counter linear both;
      animation-timeline: view();
    }
  }
}

.frame--tall   { aspect-ratio: 3 / 4; }
.frame--port   { aspect-ratio: 4 / 5; }
.frame--sq     { aspect-ratio: 1 / 1; }
.frame--land   { aspect-ratio: 3 / 2; }
.frame--wide   { aspect-ratio: 16 / 9; }
.frame--pano   { aspect-ratio: 21 / 9; }
.frame--slit   { aspect-ratio: 9 / 16; }
.frame--mono img { filter: grayscale(1) contrast(1.06); }

/* The mask reveal: a field withdraws and exposes the print underneath.
   Short enough that a photograph is resolved by the time the reader's eye
   reaches it, rather than still arriving behind them. */
.js [data-reveal="frame"]:not(.is-in) :is(picture, .frame--mark > img) {
  clip-path: inset(0 0 100% 0);
}
.js [data-reveal="frame"].is-in :is(picture, .frame--mark > img) {
  animation: rv-wipe 680ms var(--ease-editorial) var(--rd, 0ms) backwards,
             rv-settle 920ms var(--ease-editorial) var(--rd, 0ms) backwards;
}
@keyframes rv-wipe   { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes rv-settle { from { scale: 1.035; } to { scale: 1; } }

figure { margin: 0; }
.cap {
  display: flex; gap: var(--space-1);
  margin-top: var(--space-1);
  align-items: baseline;
}
.cap .idx { flex: 0 0 auto; }
.cap p { font-family: var(--font-text); font-style: italic; font-weight: 300;
         font-size: var(--fs-small); line-height: 1.35; color: var(--fg-quiet); max-width: 30em; }

/* --- Header ---------------------------------------------------------------- */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: var(--z-header);
  padding: clamp(14px, 1.5vw, 26px) 0;
  color: var(--header-fg, var(--nsv-ink));
  transition: background-color var(--t-ui) var(--ease-enter),
              color var(--t-ui) var(--ease-enter),
              padding var(--t-ui) var(--ease-enter);
}
.site-header::after {
  content: "";
  position: absolute; left: var(--page-x); right: var(--page-x); bottom: 0;
  height: var(--rule-hair);
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--t-editorial) var(--ease-rule);
}
.site-header.is-stuck { background: var(--header-bg, var(--nsv-paper)); padding: clamp(10px,1vw,16px) 0; }
.site-header.is-stuck::after { transform: scaleX(1); }

.header-inner { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }

/* The masthead: the real three-line lockup, at page scale. */
.mast { display: block; flex: 0 0 auto; transition: transform var(--t-ui) var(--ease-enter); transform-origin: left top; }
.site-header.is-stuck .mast { transform: scale(.84); }
.mast__l {
  display: flex; align-items: baseline; gap: .12em;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(14px, 1.22vw, 21px);
  line-height: var(--lh-display);
  letter-spacing: var(--track-lockup);
  text-transform: uppercase;
}
.mast__bar {
  flex: 1 1 auto;
  height: .137em;               /* 3/16 of the cap (cap = .73em) */
  background: var(--mast-bar, var(--nsv-white));
  margin-left: -.06em;
  position: relative; top: -.02em;
  transform-origin: left center;
  transition: transform var(--t-ui) var(--ease-editorial);
}
@media (hover: hover) { .mast:hover .mast__bar { transform: scaleX(1.14); } }
.site-header:not(.is-stuck) .mast__bar { --mast-bar: var(--nsv-white); }
.site-header.is-stuck .mast__bar { --mast-bar: currentColor; }

.header-nav { display: flex; align-items: center; gap: clamp(16px, 2vw, 40px); padding-top: .2em; }
.header-nav a.meta { position: relative; padding-bottom: 6px; }
.header-nav a.meta::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: var(--rule-thin); background: currentColor;
  transform: scaleX(0); transform-origin: left center;
  transition: transform var(--t-ui) var(--ease-editorial);
}
.header-nav a.meta:focus-visible::after { transform: scaleX(1); }
@media (hover: hover) { .header-nav a.meta:hover::after { transform: scaleX(1); } }
.header-nav a.meta[aria-current="page"]::after { transform: scaleX(1); }
.header-links { display: flex; align-items: center; gap: clamp(16px, 2vw, 40px); }
@media (max-width: 1023px) { .header-links { display: none; } }
@media (max-width: 460px) {
  .header-nav { gap: 14px; }
  .site-header { padding-top: 12px; padding-bottom: 12px; }
}

/* Language toggle — two words on one strict baseline, separated by a rule. */
.lang { display: flex; align-items: center; gap: 8px; }
.lang__sep { width: var(--rule-hair); height: 1em; background: currentColor; opacity: .45; }
.lang a { opacity: .5; transition: opacity var(--t-micro) linear; }
.lang a:focus-visible { opacity: 1; }
@media (hover: hover) { .lang a:hover { opacity: 1; } }
.lang a[aria-current="true"] { opacity: 1; }

/* Menu button: the word plus a two-bar mark that is the logo rule, twice. */
.menu-btn { display: flex; align-items: center; gap: 10px; color: inherit; }
.menu-btn__bars { display: grid; gap: 4px; width: 26px; }
.menu-btn__bars i { display: block; height: 2px; background: currentColor; transform-origin: right center;
                    transition: transform var(--t-ui) var(--ease-editorial); }
@media (hover: hover) { .menu-btn:hover .menu-btn__bars i:first-child { transform: scaleX(.62); } }
.menu-btn[aria-expanded="true"] .menu-btn__bars i:first-child { transform: scaleX(.4); }

/* --- Fullscreen menu ------------------------------------------------------
   Not an overlay sliding over the page: the viewport becomes a second
   typographic canvas, wiped in by a clip from the top edge. */
.menu-panel {
  position: fixed; inset: 0;
  z-index: var(--z-menu);
  background: var(--nsv-yellow);
  color: var(--nsv-ink);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(14px, 1.5vw, 26px) 0 var(--space-3);
  clip-path: inset(0 0 100% 0);
  visibility: hidden;
  transition: clip-path var(--t-ui) var(--ease-exit), visibility 0s linear var(--t-ui);
}
.menu-panel.is-open {
  clip-path: inset(0 0 0 0);
  visibility: visible;
  transition: clip-path var(--t-editorial) var(--ease-editorial), visibility 0s;
}
/* A phone on its side is shorter than the list. The panel scrolls rather than
   cutting lines off, and that scroll never leaks to the page underneath. */
.menu-panel { overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.menu-panel > nav { min-height: min-content; }
/* The line the reader chose holds its mark while the next page loads. */
.menu-list a.is-going .menu-tab { width: clamp(38px, 3.8vw, 64px); }
.menu-list a.is-going .mword::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: .1em;
  height: var(--rule-bar); background: var(--nsv-ink);
  transform-origin: left center;
  animation: going var(--t-ui) var(--ease-rule) both;
}
@keyframes going { from { transform: scaleX(0); } to { transform: scaleX(1); } }
/* The nav fills the middle band so the list can actually sit in the centre
   of the viewport rather than at the top of its own content box. */
.menu-panel > nav { display: grid; align-content: center; min-height: 0; }
.menu-list { display: grid; align-content: center; gap: clamp(2px, .4vh, 10px); }
.menu-list li { overflow: clip; }
.menu-list a {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-family: var(--font-display);
  font-weight: 800;
  /* The floor of that clamp is a real floor: below about 460px the type stops
     following the screen, and on the narrowest phones the longest name, its
     number and its arrow together ask for more room than the panel has — the
     list then sits wider than the screen it is drawn on. The second term caps
     the size by the page's own width, so the longest name always fits. It is
     only ever the smaller of the two below ~340px; every wider screen is set
     exactly as before. */
  font-size: min(clamp(34px, 7.4vw, 108px), calc(var(--vw, 100vw) / 10));
  line-height: 1.04;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  transform: translateY(105%);
  transition: transform var(--t-editorial) var(--ease-editorial);
}
.menu-panel.is-open .menu-list a { transform: translateY(0); }
.menu-list li:nth-child(1) a { transition-delay: 60ms; }
.menu-list li:nth-child(2) a { transition-delay: 105ms; }
.menu-list li:nth-child(3) a { transition-delay: 150ms; }
.menu-list li:nth-child(4) a { transition-delay: 195ms; }
.menu-list li:nth-child(5) a { transition-delay: 240ms; }
.menu-list li:nth-child(6) a { transition-delay: 285ms; }
.menu-list li:nth-child(7) a { transition-delay: 330ms; }
.menu-list .idx { flex: 0 0 auto; font-size: var(--fs-meta); align-self: flex-start;
                  padding-top: .55em; color: var(--axis, currentColor); opacity: .75; }
.menu-list a:focus-visible .idx { opacity: 1; }
@media (hover: hover) { .menu-list a:hover .idx { opacity: 1; } }
.menu-list a .mword { position: relative; display: inline-block; transition: letter-spacing var(--t-ui) var(--ease-editorial); }
.menu-list a:focus-visible .mword { letter-spacing: .012em; }
@media (hover: hover) { .menu-list a:hover .mword { letter-spacing: .012em; } }
.menu-list a[aria-current="page"] .mword::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: .1em;
  height: var(--rule-bar); background: var(--nsv-ink);
}
.menu-foot { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: baseline; }
@media (prefers-reduced-motion: reduce) {
  .menu-list a { transform: none; }
  .menu-panel { transition: none; }
}

/* --- Footer canvas --------------------------------------------------------- */
.footer-canvas { position: relative; padding-top: var(--space-6); padding-bottom: var(--space-3); }
.footer-canvas .got {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-mega);
  line-height: .9;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  display: block;
}
.mailto-big {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 600;
  /* The address is 12.6em long and has no place to break. On a phone it is
     sized to the column so it is never split mid-word ("…vision.c / om"). */
  font-size: min(var(--fs-h2), calc(var(--content) / 13.2));
  letter-spacing: var(--track-h);
  line-height: 1.05;
  text-transform: none;
  word-break: break-word;
}
.footer-grid { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5); align-items: baseline; }
.social { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* --- Custom cursor --------------------------------------------------------
   Desktop, fine pointer only. It is a rule, not a blob: the same bar the
   whole site is built from, carrying a word when there is one to carry. */
.cursor {
  position: fixed; top: 0; left: 0;
  z-index: var(--z-cursor);
  pointer-events: none;
  display: none;
  will-change: transform;
  mix-blend-mode: difference;
}
.cursor__bar {
  display: block;
  width: 22px; height: 2px;
  background: #fff;
  transform-origin: left center;
  transition: width var(--t-micro) var(--ease-editorial),
              height var(--t-micro) var(--ease-editorial);
}
.cursor__label {
  position: absolute; left: 0; top: 10px;
  font-family: var(--font-meta); font-size: 10.5px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: #fff;
  opacity: 0; transform: translateY(-4px);
  transition: opacity var(--t-micro) linear, transform var(--t-micro) var(--ease-editorial);
  white-space: nowrap;
}
.cursor.has-label .cursor__bar { width: 38px; }
.cursor.has-label .cursor__label { opacity: 1; transform: translateY(0); }
@media (hover: hover) and (pointer: fine) {
  body.cursor-on .cursor { display: block; }
}
@media (prefers-reduced-motion: reduce) { .cursor { display: none !important; } }

/* --- Reveals --------------------------------------------------------------
   Default entrance. Small, weighted, and never applied per sentence.
   Start-states apply only until the element is in; the entrance is an
   animation that fills backwards, so once it has played the element is left
   entirely to its own styles — its transitions and hover states untouched.
   The lift uses `translate`, never `transform`, for the same reason. */
.js [data-reveal="up"]:not(.is-in)   { opacity: 0; translate: 0 26px; }
.js [data-reveal="fade"]:not(.is-in) { opacity: 0; }
.js [data-reveal="mask"]:not(.is-in) { clip-path: inset(0 0 100% 0); }
.js [data-reveal="up"].is-in {
  animation: rv-fade var(--t-editorial) var(--ease-enter) var(--rd, 0ms) backwards,
             rv-lift var(--t-editorial) var(--ease-editorial) var(--rd, 0ms) backwards;
}
.js [data-reveal="fade"].is-in {
  animation: rv-fade var(--t-editorial) var(--ease-enter) var(--rd, 0ms) backwards;
}
.js [data-reveal="mask"].is-in {
  animation: rv-wipe var(--t-cine) var(--ease-editorial) var(--rd, 0ms) backwards;
}
@keyframes rv-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes rv-lift { from { translate: 0 26px; } to { translate: 0 0; } }

/* --- To top ---------------------------------------------------------------- */
.to-top { display: inline-flex; align-items: center; gap: 10px; }
.to-top__bar { width: 30px; height: var(--rule-thin); background: currentColor;
               transition: width var(--t-ui) var(--ease-editorial); }
@media (hover: hover) { .to-top:hover .to-top__bar { width: 50px; } }

/* ===========================================================================
   PAINT
   The logo's bar, made by hand. A crisp rule is the institution stating
   itself; a painted one is the same statement made with a brush. The site
   uses both, and never mixes them inside one object.
   =========================================================================== */
.paint {
  display: block;
  background: currentColor;
  -webkit-mask-image: var(--paint-1);
          mask-image: var(--paint-1);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  height: var(--rule-bar);
  width: 100%;
}
.paint--2 { -webkit-mask-image: var(--paint-2); mask-image: var(--paint-2); }
.paint--3 { -webkit-mask-image: var(--paint-3); mask-image: var(--paint-3); }
.paint--thin { height: calc(var(--rule-bar) * .55); }
.paint--heavy { height: calc(var(--rule-bar) * 2.1); }
.paint--axis { color: var(--axis-mark, currentColor); }

/* A short painted tab — the index mark that carries an item's axis colour. */
.tab {
  display: inline-block;
  width: clamp(40px, 4.4vw, 76px);
  height: clamp(9px, .92vw, 15px);
  flex: 0 0 auto;
  background: var(--axis-mark, var(--rule-color));
  -webkit-mask-image: var(--paint-tab-1);
          mask-image: var(--paint-tab-1);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  transition: width var(--t-ui) var(--ease-editorial);
}
.index__row:nth-child(3n+2) .tab, .wall__item:nth-child(3n+2) .tab {
  -webkit-mask-image: var(--paint-tab-2); mask-image: var(--paint-tab-2); }
.index__row:nth-child(3n) .tab, .wall__item:nth-child(3n) .tab {
  -webkit-mask-image: var(--paint-tab-3); mask-image: var(--paint-tab-3); }
@media (hover: hover) { a:hover > .tab, a:hover .tab, button:hover .tab { width: clamp(58px, 6.6vw, 108px); } }

/* A field that ends in paint instead of a straight cut. */
.tongue--paint::after {
  background: var(--bg);
  -webkit-mask-image: var(--paint-edge-1);
          mask-image: var(--paint-edge-1);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  height: calc(var(--act) * .92);
}
.tongue--paint-2::after { -webkit-mask-image: var(--paint-edge-2); mask-image: var(--paint-edge-2); }

/* Overprint: where two inks cross on press they multiply. */
.overprint { mix-blend-mode: multiply; }
.on-ink .overprint { mix-blend-mode: screen; }

/* ===========================================================================
   PRESS FURNITURE
   Crop marks and a colour bar — the marks a printer puts outside the trim so
   the sheet can be registered and the inks checked. Here they sit at the
   edges of the canvas, where they belong.
   =========================================================================== */
.crop {
  position: absolute;
  width: 26px; height: 26px;
  pointer-events: none;
  opacity: .5;
  color: var(--fg-quiet);
}
.crop::before, .crop::after {
  content: ""; position: absolute; background: currentColor;
}
.crop::before { width: 100%; height: var(--rule-hair); top: 0; }
.crop::after  { height: 100%; width: var(--rule-hair); left: 0; }
.crop--tr { right: 0; transform: scaleX(-1); }
.crop--bl { bottom: 0; transform: scaleY(-1); }
.crop--br { right: 0; bottom: 0; transform: scale(-1); }

.colourbar {
  display: flex; align-items: flex-end; gap: 0; width: 100%;
  border-bottom: var(--rule-hair) solid var(--fg);
  padding-bottom: 6px;
}
.colourbar i {
  display: block;
  flex: 1 1 0;
  height: clamp(16px, 1.9vw, 30px);
  -webkit-mask-image: var(--paint-tab-1);
          mask-image: var(--paint-tab-1);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  transition: height var(--t-ui) var(--ease-editorial);
}
@media (hover: hover) { .colourbar:hover i { height: clamp(22px, 2.6vw, 42px); } }
.colourbar i:nth-child(1) { background: var(--nsv-ink); }
.colourbar i:nth-child(2) { background: var(--nsv-yellow); }
.colourbar i:nth-child(3) { background: var(--nsv-culture); }
.colourbar i:nth-child(4) { background: var(--nsv-sport); }
.colourbar i:nth-child(5) { background: var(--nsv-art); }
/* The stock itself is shown the way a printer shows it — as an empty patch,
   outlined rather than inked. */
.colourbar i:nth-child(6) {
  background: var(--nsv-paper);
  -webkit-mask-image: none; mask-image: none;
  outline: var(--rule-hair) solid var(--fg);
  outline-offset: -1px;
}
.colourbar i:nth-child(even) { -webkit-mask-image: var(--paint-tab-2); mask-image: var(--paint-tab-2); }
.colourbar i:nth-child(3n) { -webkit-mask-image: var(--paint-tab-3); mask-image: var(--paint-tab-3); }
@media (prefers-reduced-motion: reduce) { .colourbar:hover i { height: clamp(16px, 1.9vw, 30px); } }

/* The colophon: the press sheet's own edge. */
.colophon { margin-top: var(--space-5); position: relative; }
.colophon__keys {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0;
  margin-top: 10px;
}
.colophon__keys span { display: block; }
@media (max-width: 767px) { .colophon__keys { font-size: 8.5px; letter-spacing: .06em; } }

/* ===========================================================================
   THE SWEEP
   One large painted mark per field, printed over the ground rather than
   placed on top of it: multiply is what a second ink actually does on press,
   so where it crosses the type nothing lightens and nothing is obscured. It
   is set low enough to be felt rather than looked at.
   =========================================================================== */
.sweep {
  position: absolute;
  left: calc(50% - var(--vw) / 2);
  width: var(--sweep-w, var(--vw));
  pointer-events: none;
  z-index: 0;
  background: var(--sweep-ink, var(--nsv-art));
  opacity: var(--sweep-o, .16);
  mix-blend-mode: multiply;
  -webkit-mask-image: var(--paint-1);
          mask-image: var(--paint-1);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  /* the tilt is the tuck: the logo's bar meets the W on a slight diagonal */
  transform: rotate(var(--sweep-tilt, -1.6deg));
  transform-origin: left center;
}
.on-ink .sweep { mix-blend-mode: screen; opacity: var(--sweep-o, .13); }
.sweep--2 { -webkit-mask-image: var(--paint-2); mask-image: var(--paint-2); }
.sweep--3 { -webkit-mask-image: var(--paint-3); mask-image: var(--paint-3); }
/* the canvas sits under the content, never over it */
.act-hero > .wrap, .act-axis > .wrap, .page-head > .wrap { position: relative; z-index: 1; }
@media (max-width: 767px) { .sweep { --sweep-o: .13; } }

/* The menu carries the same painted tab as the index, in place of a number. */
.menu-tab { width: clamp(26px, 2.6vw, 44px); height: clamp(7px, .7vw, 11px);
            align-self: center; margin-right: var(--space-1); flex: 0 0 auto; }
.menu-list a:focus-visible .menu-tab { width: clamp(38px, 3.8vw, 64px); }
@media (hover: hover) { .menu-list a:hover .menu-tab { width: clamp(38px, 3.8vw, 64px); } }
.menu-list li:not([data-axis]) .menu-tab { background: var(--nsv-ink); }

/* A drawn mark is an object, not a view: it is shown whole on the stock,
   never cropped to fill a frame. */
.frame--mark { background: var(--nsv-paper-deep); background-image: none; }
.frame--mark img { object-fit: contain; width: 82%; height: 82%; margin: 9%; }
.on-ink .frame--mark { background: #2A2A26; }

/* Borrowed stock is graded to one level so seven photographs from seven
   sources read as one set. NSV's own material is never touched. */
.frame--stock img { filter: saturate(.86) contrast(1.045); }
