/* Immersive tier: the reference experience for spec sections 1 to 10.
   Load order: core/fonts/fonts.css, core/tokens/tokens.css, core/a11y/a11y.css, this file, generated.css (per-item art
   direction written by build.js from content/work.json and assets/manifest.json).

   Direction (nexverto-ux ref 02): primary Immersive Visual, complement Quiet Luxury, because the page's job is to let the
   work be seen and NexVerto's voice is premium, understated and executive. Axes D1 F3 E4 T4 C4 I4 M4 R1 S2 K3.
   The visual world: graphite objects drawn on a drafting board, joined by NexVerto's one blue line. */

/* ---------------------------------------------------------------------------------------------------------------
   1. Tier tokens (contextual layer on top of core/tokens)
   --------------------------------------------------------------------------------------------------------------- */
:root {
  --gap: clamp(16px, 2.2vw, 32px);
  --header-h: 72px;
  --z-header: 40;
  --line: var(--brand);                 /* the NexVerto line */
  --display-wght: 560;                  /* resting weight of the display face; scrubbed by motion on the full tier */
}
:root, html[data-theme="dark"] {
  --plate: #131f27;
  --plate-edge: #1f2d37;
  --plate-grid: rgb(140 191 255 / .055);
  --grain-opacity: .07;
}
html[data-theme="light"] {
  --plate: #eceae3;
  --plate-edge: #dedbd2;
  --plate-grid: rgb(16 79 182 / .06);
  --grain-opacity: .045;
}

/* ---------------------------------------------------------------------------------------------------------------
   2. Base
   --------------------------------------------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; } /* filtered items and unused controls stay hidden whatever their layout rule */
html { scroll-padding-top: calc(var(--header-h) + 16px); }
body {
  margin: 0; min-height: 100dvh;
  background: var(--bg); color: var(--ink);
  font: 400 var(--text-body)/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
h1, h2, h3, p, ul, ol, figure { margin: 0; }
h1, h2, h3 { font-family: var(--font-display); font-weight: 500; letter-spacing: -.025em; line-height: 1.05; text-wrap: balance; font-optical-sizing: auto; }
p, li { text-wrap: pretty; }
p { color: var(--ink-muted); }
img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
::selection { background: var(--brand); color: #fff; }
.wrap { width: min(var(--page-max), 100% - 2 * var(--page-gutter)); margin-inline: auto; }

/* ---------------------------------------------------------------------------------------------------------------
   3. Layers (spec section 2). Each layer is its own element with its own stacking context (isolation), so a
   z-index only competes with its siblings. Two traps this file avoids on purpose:
   - a transformed ancestor becomes the containing block for position:fixed, so the cursor preview lives at the end of
     <body>, outside every gallery item that FLIP or parallax transforms;
   - a transformed element creates a stacking context, so a raised z-index inside a moving card can never lift it
     above the header; overlays are raised by moving them to the overlay layer, not by raising a number.
   Background   body background colour
   Environment  .layer-environment: fixed film grain, pointer-events none, hidden from assistive technology
   Media        .plate and its picture inside each item (own stacking context)
   Content      header, main, footer
   Interactive  links, buttons, the gallery controls (inside content, raised only where they overlap media)
   Overlay      .cursor-preview at body level
   Transition   the browser's ::view-transition tree, and .project-media's mask reveal when that is unsupported
   System UI    skip link, live region, the motion switch
   --------------------------------------------------------------------------------------------------------------- */
.layer-environment {
  position: fixed; inset: 0; z-index: var(--z-environment); pointer-events: none;
  background-image: url("assets/grain.svg"); background-size: 240px 240px; /* resolved against this stylesheet */
  opacity: var(--grain-opacity); mix-blend-mode: overlay;
}
.site-header, main, .site-footer { position: relative; z-index: var(--z-content); }
.site-header { z-index: var(--z-header); }
.skip { z-index: var(--z-system); }

/* ---------------------------------------------------------------------------------------------------------------
   4. Header: wordmark, one nav, one primary action
   --------------------------------------------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0;
  display: flex; align-items: center; gap: 8px 24px;
  min-height: var(--header-h); padding-inline: var(--page-gutter);
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.wordmark { display: inline-flex; align-items: center; min-height: 44px; font: 700 20px/1 var(--font-wordmark); letter-spacing: -.02em; --link-ink: var(--wordmark-nex); }
.site-header .wordmark { view-transition-name: wordmark; } /* one name per page: the footer wordmark stays unnamed */
.wordmark b { font-weight: 700; color: var(--verto); }
.site-nav { display: flex; gap: 4px; margin-left: auto; }
.site-nav a { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 12px; border-radius: var(--radius-2); font-size: var(--text-sm); font-weight: 500; --link-ink: var(--ink-muted); transition: background-color var(--dur-2); }
.site-nav a:hover { --link-ink: var(--ink); background: var(--surface-2); }
.site-nav a[aria-current="page"] { --link-ink: var(--ink); }
.site-nav a[aria-current="page"] > .t { background-size: 100% 1px; }

/* Primary action. The magnetic pull moves the wrapper (translate); the press moves the button (transform):
   two elements, two properties, never one property written twice (spec section 3, coordination). */
.magnet { display: inline-block; translate: var(--mx, 0px) var(--my, 0px); transition: translate 380ms var(--ease-out-expo); }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px; padding: 12px 20px; border: 1px solid var(--brand); border-radius: var(--radius-2);
  background: var(--brand); --link-ink: var(--brand-ink); font: 600 16px/1.2 var(--font-body); white-space: nowrap;
  box-shadow: var(--btn-lit);
  transition: transform var(--dur-1) var(--ease-mechanical), box-shadow var(--dur-1), background-color var(--dur-2);
}
.btn:hover { box-shadow: var(--btn-lit-hover); transform: translateY(-1px); }
.btn:active { transform: translateY(1px) scale(.98); box-shadow: var(--btn-lit-press); }
.btn > .t { background-image: none; }
.btn .arrow { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.btn .arrow path { transition: transform var(--dur-2) var(--ease-out); }
.btn:hover .arrow path, .btn:focus-visible .arrow path { transform: translateX(4px); }
.site-header .btn { min-height: 44px; padding: 10px 16px; font-size: 15px; }

/* ---------------------------------------------------------------------------------------------------------------
   5. Hero: kinetic editorial headline and the signature line
   --------------------------------------------------------------------------------------------------------------- */
.hero {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); align-items: end;
  padding-block: clamp(40px, 8vh, 112px) 0;
}
.hero h1 {
  grid-column: 1 / -1;
  font-size: var(--text-display); line-height: .94; letter-spacing: -.04em;
  font-variation-settings: "wght" var(--display-wght), "opsz" 144;
}
.kinetic .line { display: block; }
/* Each word masks itself, so a word that wraps never shows through the line below while it rises. */
.kinetic .w { display: inline-block; overflow: clip; padding-block: .06em .1em; margin-block: -.06em -.1em; vertical-align: top; }
.kinetic .w > span { display: inline-block; }
.hero .lede { grid-column: 7 / -1; margin-top: clamp(24px, 3vw, 40px); font-size: var(--text-lede); line-height: 1.55; max-width: 44ch; }
.hero .lede, .project-hero .lede { color: var(--ink-muted); }

.signature { grid-column: 1 / -1; margin-top: clamp(24px, 5vw, 64px); color: var(--ink-dim); }
.sig { width: 100%; height: auto; overflow: visible; }
.sig-tall { display: none; }
.sig .box, .sig .glyph { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sig .spine { fill: none; stroke: var(--line); stroke-width: 2.25; stroke-linecap: round; stroke-dasharray: 1 1; stroke-dashoffset: var(--draw, 0); }
.sig .node { fill: var(--line); stroke: var(--line); stroke-width: 2; transition: fill var(--dur-3) var(--ease-out), r var(--dur-3) var(--ease-out); }
.sig .station { color: var(--accent); transition: color var(--dur-3) var(--ease-out), opacity var(--dur-3) var(--ease-out); }
/* Before the line arrives, a station waits dim with a hollow node. Only script adds .is-waiting, so with no script or
   with reduced motion the drawing is complete and every station is lit. */
.sig .station.is-waiting { color: var(--ink-dim); opacity: .55; }
.sig .station.is-waiting .node { fill: var(--bg); }
.sig .label { font: 500 13px/1 var(--font-body); fill: currentColor; letter-spacing: .01em; }

/* ---------------------------------------------------------------------------------------------------------------
   6. Gallery: shared item anatomy
   --------------------------------------------------------------------------------------------------------------- */
.work { padding-block: clamp(64px, 9vw, 128px) 0; }
.work-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 20px 32px; margin-bottom: clamp(32px, 4vw, 56px); }
.work-head h2 { font-size: var(--text-h2); grid-column: 1; }
.controls { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 32px; padding-top: 16px; border-top: 1px solid var(--border); }
.gallery-status { grid-column: 2; grid-row: 1; font-size: var(--text-sm); color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.controls[inert] { visibility: hidden; } /* no script: the controls could not work, so they keep their space but stay out of sight */

/* Filters: typographic, not pills. The active one is underlined by a line that draws across. */
.filters, .views { display: flex; flex-wrap: wrap; gap: 4px 8px; }
.filters button, .views button {
  position: relative; display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 10px; border: 0; border-radius: var(--radius-1); background: none;
  color: var(--ink-muted); font-size: var(--text-sm); font-weight: 500;
  transition: color var(--dur-2), background-color var(--dur-2), transform var(--dur-1) var(--ease-mechanical);
}
.filters button::after, .views button::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: 6px; height: 2px; border-radius: 2px;
  background: var(--line); transform: scaleX(0); transform-origin: left center; transition: transform var(--dur-3) var(--ease-out-expo);
}
.filters button:hover, .views button:hover { color: var(--ink); background: var(--surface-2); }
.filters button:active, .views button:active { transform: translateY(1px); }
.filters button[aria-pressed="true"], .views button[aria-pressed="true"] { color: var(--ink); }
.filters button[aria-pressed="true"]::after, .views button[aria-pressed="true"]::after { transform: scaleX(1); }
.count { font-size: 12px; font-variant-numeric: tabular-nums; color: var(--ink-dim); translate: 0 -.4em; }
.filter-toggle, .more-toggle, .more-label { display: none; } /* phone controls, switched on in section 10 */
.views svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.views button[aria-pressed="true"] svg { color: var(--accent); }

.gallery { list-style: none; margin: 0; padding: 0; }
.item { position: relative; min-width: 0; }
.item-media { display: block; position: relative; aspect-ratio: var(--ratio-d, 4 / 3); }
.plate {
  position: absolute; inset: 0; overflow: hidden; isolation: isolate; border-radius: var(--radius-3);
  background:
    linear-gradient(var(--plate-grid) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(90deg, var(--plate-grid) 1px, transparent 1px) 0 0 / 32px 32px,
    radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--plate-edge) 70%, transparent), transparent 70%),
    var(--plate);
  box-shadow: inset 0 0 0 1px var(--plate-edge);
}
/* The NexVerto line under each object, drawn once the item is in view. */
.plate::after { content: ""; position: absolute; left: 8%; right: 8%; bottom: 10%; height: 1px; background: var(--line); opacity: .55; transform-origin: left center; }
.plate img {
  position: absolute; inset: 7% 8% 12%; width: 84%; height: 81%;
  object-fit: contain; object-position: var(--focal-d, 50% 50%);
  translate: 0 var(--parallax, 0px);           /* owned by the media-parallax spec */
  scale: var(--zoom, 1);                        /* owned by the CSS hover state below */
  transition: scale 700ms var(--ease-out-expo);
  -webkit-user-drag: none; user-select: none;
}
.item-text { display: grid; gap: 6px; margin-top: 16px; }
.item-title { font-size: clamp(1.5rem, 1.15rem + 1.1vw, 2.25rem); line-height: 1.1; font-variation-settings: "wght" 500, "opsz" 72; transition: font-variation-settings var(--dur-3) var(--ease-out); }
.item-title a { --link-ink: var(--ink); }
.item-title a::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: var(--radius-3); } /* the whole item is the target */
.item-cat { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; color: var(--ink-dim); }
.item-cat::before { content: ""; width: 18px; height: 2px; border-radius: 2px; background: var(--line); }
.item-summary { font-size: 16px; line-height: 1.55; max-width: 46ch; }
.item:has(a:focus-visible) .plate { outline: 3px solid var(--accent); outline-offset: 4px; }
.gallery[data-view="index"] .item:has(a:focus-visible) { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-1); }
.gallery[data-view="index"] .item:has(a:focus-visible) .plate { outline: none; }
.item a:focus-visible { outline: none; }
@media (hover: hover) and (pointer: fine) {
  html[data-motion="full"] .item:hover { --zoom: 1.045; }
  .item:hover .item-title { font-variation-settings: "wght" 600, "opsz" 72; }
}

/* Editorial view (default; also the no-script layout). Asymmetric 12-column composition: each item has its own
   span and ratio (generated.css), rows pair up to 11 or 12 columns, and every second visible item drops lower. */
.gallery[data-view="editorial"] { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: clamp(56px, 7vw, 120px) var(--gap); align-items: start; }
.gallery[data-view="editorial"] .item { grid-column: span var(--span, 6); }
.gallery[data-view="editorial"] .item:nth-child(even of :not([hidden])) { margin-top: clamp(40px, 9vw, 160px); }

/* Index view: an editorial list. Desktop with a fine pointer shows the image beside the cursor (overlay layer);
   touch and reduced motion keep the thumbnail in the row. Same information, different interaction (spec section 6). */
.gallery[data-view="index"] { display: grid; border-top: 1px solid var(--border); }
.gallery[data-view="index"] .item { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 4px 24px; padding-block: 20px; border-bottom: 1px solid var(--border); }
.gallery[data-view="index"] .item-media { height: 88px; width: calc(88px * var(--ar-d, 1.3333)); } /* same ratio as in every view, so the morph scales evenly */
.gallery[data-view="index"] .item-text { margin: 0; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; column-gap: 32px; }
.gallery[data-view="index"] .item-title { font-size: clamp(1.75rem, .9rem + 3vw, 4.5rem); line-height: 1; font-variation-settings: "wght" 400, "opsz" 144; }
.gallery[data-view="index"] .item-cat { grid-column: 2; grid-row: 1; }
.gallery[data-view="index"] .item-summary { grid-column: 1 / -1; max-width: 64ch; }
@media (hover: hover) and (pointer: fine) {
  .gallery[data-view="index"] .item:hover .item-title { font-variation-settings: "wght" 600, "opsz" 144; }
  .gallery[data-view="index"] .item:hover { background: linear-gradient(90deg, color-mix(in srgb, var(--brand) 7%, transparent), transparent 70%); }
  html[data-motion="full"] .gallery[data-view="index"] .item { grid-template-columns: minmax(0, 1fr); }
  html[data-motion="full"] .gallery[data-view="index"] .item-media { display: none; }
}

/* Reel view: one row the visitor drags, swipes, steps with the buttons or walks with the arrow keys. */
.gallery[data-view="reel"] {
  display: grid; grid-auto-flow: column; grid-auto-columns: max-content; gap: var(--gap);
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory;
  margin-inline: calc(var(--page-gutter) * -1); padding: 4px var(--page-gutter) 20px; scroll-padding-inline: var(--page-gutter);
  scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent;
}
.gallery[data-view="reel"] .item { scroll-snap-align: start; width: max-content; }
.gallery[data-view="reel"] .item-media { --reel-h: min(58vh, 540px); height: var(--reel-h); width: calc(var(--reel-h) * var(--ar-d, 1)); }
.gallery[data-view="reel"] .item-text { max-width: 36ch; }
.gallery[data-view="reel"] .item-summary { display: none; }
.gallery[data-view="reel"].is-dragging { scroll-snap-type: none; cursor: grabbing; user-select: none; }
.gallery[data-view="reel"].is-dragging a { pointer-events: none; }
html[data-motion="full"] .gallery[data-view="reel"] { cursor: grab; }
.reel-steps { display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px; }
.reel-steps button {
  display: inline-grid; place-items: center; width: 48px; height: 48px; padding: 0;
  border: 1px solid var(--ink-dim); border-radius: 50%; background: var(--surface); color: var(--ink);
  transition: background-color var(--dur-2), transform var(--dur-1) var(--ease-mechanical), opacity var(--dur-2);
}
.reel-steps button:hover { background: var(--surface-3); }
.reel-steps button:active { transform: scale(.94); }
.reel-steps button:disabled { opacity: .35; cursor: default; }
.reel-steps svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.reel-hint { font-size: var(--text-sm); color: var(--ink-dim); margin-right: auto; align-self: center; }
[data-gallery]:not([data-view="reel"]) .reel-steps { display: none; }

/* Cursor-driven preview (overlay layer, body level, hidden from assistive technology). */
.cursor-preview {
  position: fixed; left: 0; top: 0; z-index: var(--z-overlay); pointer-events: none;
  width: clamp(240px, 22vw, 360px); aspect-ratio: 4 / 3; border-radius: var(--radius-3); overflow: hidden;
  background:
    linear-gradient(var(--plate-grid) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, var(--plate-grid) 1px, transparent 1px) 0 0 / 24px 24px, var(--plate);
  box-shadow: var(--shadow-lift), inset 0 0 0 1px var(--plate-edge);
  opacity: 0; scale: .9; translate: var(--px, -999px) var(--py, -999px);
  transition: opacity var(--dur-2) var(--ease-out), scale 320ms var(--ease-out-expo);
}
.cursor-preview.is-on { opacity: 1; scale: 1; }
.cursor-preview img { width: 100%; height: 100%; object-fit: contain; padding: 8%; }

/* ---------------------------------------------------------------------------------------------------------------
   7. Closing call to action and footer
   --------------------------------------------------------------------------------------------------------------- */
.cta { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); padding-block: clamp(96px, 12vw, 176px) clamp(64px, 8vw, 112px); }
.cta h2 { grid-column: 1 / span 8; font-size: var(--text-h2); }
.cta p { grid-column: 1 / span 6; margin-top: 16px; font-size: var(--text-lede); }
.cta .actions { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; margin-top: 32px; }
.text-link { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; --link-ink: var(--accent); }
/* The site's one slim footer (Joe, 2026-10-15: "Simplify it so that we can see things but not take up real estate"): one line on a
   desktop, two short lines on a phone; the same links as every nexverto.com page, then the visitor's motion switch. */
.site-footer { display: flex; flex-wrap: wrap; align-items: center; gap: 0 20px; padding: 6px var(--page-gutter); border-top: 1px solid var(--border); font-size: 13px; line-height: 1.4; color: var(--ink-dim); }
.site-footer .copyright { margin: 0; white-space: nowrap; }
.site-footer .copyright .wordmark { min-height: 0; font-size: 15px; }
.site-footer nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0 20px; margin-left: auto; }
.site-footer nav a, .site-footer .f-phone { display: inline-flex; align-items: center; min-height: 44px; font-size: 13px; --link-ink: var(--ink-muted); }
.site-footer nav a:hover, .site-footer .f-phone:hover { --link-ink: var(--ink); }
.site-footer .f-phone { font-weight: 600; white-space: nowrap; }
.site-footer .motion-switch { font-size: 13px; }
/* The switch is shown by script; its place is kept from the start so the footer never shifts when it appears (CLS 0). */
.site-footer .motion-switch[hidden] { display: inline-flex; visibility: hidden; }
/* System UI: the visitor's own motion switch, remembered on this device. */
.motion-switch { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 6px 4px; border: 0; background: none; color: var(--ink-muted); font-size: var(--text-sm); }
.motion-switch .track { position: relative; width: 36px; height: 20px; border-radius: 10px; border: 1px solid var(--ink-dim); background: var(--surface); transition: background-color var(--dur-2); }
.motion-switch .track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--ink-dim); transition: translate var(--dur-2) var(--ease-mechanical), background-color var(--dur-2); }
.motion-switch[aria-pressed="true"] .track { background: var(--brand); border-color: var(--brand); }
.motion-switch[aria-pressed="true"] .track::after { translate: 16px 0; background: #fff; }
.motion-switch:hover { color: var(--ink); }

/* ---------------------------------------------------------------------------------------------------------------
   8. Project pages
   --------------------------------------------------------------------------------------------------------------- */
.crumbs { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; padding-top: clamp(32px, 5vw, 56px); font-size: var(--text-sm); color: var(--ink-dim); }
.crumbs a { display: inline-flex; align-items: center; min-height: 44px; --link-ink: var(--ink-muted); }
.crumbs span[aria-hidden] { color: var(--border-strong); }
.project-hero { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: clamp(24px, 3vw, 40px); padding-top: 8px; }
.project-hero h1 { grid-column: 1 / span 10; font-size: clamp(2.75rem, 1.4rem + 5.2vw, 7rem); line-height: .96; letter-spacing: -.04em; font-variation-settings: "wght" var(--display-wght), "opsz" 144; }
.project-hero .lede { grid-column: 1 / span 7; font-size: var(--text-lede); line-height: 1.55; max-width: 52ch; }
.project-media { grid-column: 1 / -1; position: relative; aspect-ratio: 21 / 9; margin-top: clamp(8px, 2vw, 24px); }
.project-media .plate img { inset: 8% 20% 12%; width: 60%; height: 80%; }
.project-body { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); padding-block: clamp(64px, 8vw, 120px) 0; }
.project-body h2 { grid-column: 1 / span 4; font-size: clamp(1.75rem, 1.2rem + 1.8vw, 2.75rem); align-self: start; position: sticky; top: calc(var(--header-h) + 24px); }
.points { grid-column: 6 / -1; list-style: none; padding: 0; margin: 0; border-top: 1px solid var(--border); }
.points li { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 12px; padding-block: 20px; border-bottom: 1px solid var(--border); font-size: 18px; color: var(--ink); }
.points li::before { content: ""; width: 18px; height: 2px; margin-top: .8em; border-radius: 2px; background: var(--line); }
.project-links { grid-column: 6 / -1; display: flex; flex-wrap: wrap; gap: 4px 28px; margin-top: 24px; }
.project-demo { padding-block: clamp(64px, 8vw, 120px) 0; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); }
.project-demo h2 { grid-column: 1 / span 4; font-size: clamp(1.75rem, 1.2rem + 1.8vw, 2.75rem); }
.project-demo .demo { grid-column: 6 / -1; }
.project-next { margin-top: clamp(64px, 8vw, 120px); border-top: 1px solid var(--border); }
.project-next a { display: grid; grid-template-columns: minmax(0, 1fr) 160px; align-items: center; gap: 24px; padding-block: 28px; --link-ink: var(--ink); }
.project-next .next-label { display: block; font-size: var(--text-sm); color: var(--ink-dim); }
.project-next .next-title { display: block; font: 500 clamp(1.75rem, 1rem + 2.6vw, 3.5rem)/1.05 var(--font-display); letter-spacing: -.03em; font-variation-settings: "wght" 460, "opsz" 144; transition: font-variation-settings var(--dur-3) var(--ease-out); }
.project-next a:hover .next-title, .project-next a:focus-visible .next-title { font-variation-settings: "wght" 600, "opsz" 144; }
.project-next .item-media { aspect-ratio: 4 / 3; }

/* Demonstration: a call on the main line. Every line is shown at rest; the control plays it line by line (motion-specs.js). */
.call { border: 1px solid var(--border); border-radius: var(--radius-3); background: var(--surface); box-shadow: var(--shadow); overflow: hidden; }
.call-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 20px; border-bottom: 1px solid var(--border); font-size: var(--text-sm); color: var(--ink-dim); }
.call-controls { display: flex; gap: 8px; }
.call-controls button { min-height: 40px; min-width: 84px; padding: 6px 14px; border: 1px solid var(--ink-dim); border-radius: var(--radius-2); background: none; color: var(--ink); font-size: 14px; font-weight: 600; transition: background-color var(--dur-2), transform var(--dur-1) var(--ease-mechanical); }
.call-controls button:hover { background: var(--surface-3); }
.call-controls button:active { transform: translateY(1px); }
.call ol { list-style: none; margin: 0; padding: 8px 20px 20px; display: grid; gap: 4px; }
.call li { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.call li:last-child { border-bottom: 0; }
.call .who { font-size: 14px; font-weight: 600; color: var(--accent); }
.call .said { color: var(--ink); }

/* Demonstration: the platform workspace as one window with a row per tool (not a grid of equal cards). */
.workspace { border: 1px solid var(--border); border-radius: var(--radius-3); background: var(--surface); box-shadow: var(--shadow); overflow: hidden; }
.workspace-bar { display: flex; align-items: center; gap: 10px; padding: 14px 20px; border-bottom: 1px solid var(--border); font-size: var(--text-sm); color: var(--ink-dim); }
.workspace-bar::before { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--line); }
.workspace ul { list-style: none; margin: 0; padding: 4px 20px 8px; }
.workspace li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 24px; align-items: baseline; padding: 16px 0; border-bottom: 1px solid var(--border); }
.workspace li:last-child { border-bottom: 0; }
.workspace b { font-weight: 600; color: var(--ink); }
.workspace span { font-size: 15px; color: var(--ink-muted); text-align: right; }

/* Demonstration: a page assembling itself. */
.page-demo { border: 1px solid var(--border); border-radius: var(--radius-3); background: var(--surface); box-shadow: var(--shadow); padding: 16px; }
.page-demo svg { width: 100%; height: auto; }
.page-demo .block { fill: var(--surface-3); }
.page-demo .ink { fill: var(--ink-dim); }
.page-demo .brand { fill: var(--brand); }
.page-demo .rule { stroke: var(--line); stroke-width: 2; }

/* ---------------------------------------------------------------------------------------------------------------
   9. Transitions (spec section 3, page transition; section 4, project-to-detail)
   --------------------------------------------------------------------------------------------------------------- */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 180ms; animation-timing-function: var(--ease-out); }
::view-transition-group(*) { animation-duration: 460ms; animation-timing-function: var(--ease-out-expo); }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
/* Transition layer fallback where cross-document View Transitions are missing: the project image opens from a mask. */
@keyframes mask-open { from { clip-path: inset(10% 14% 10% 14% round 24px); } to { clip-path: inset(0 round 18px); } }
.project-media.is-revealing .plate { animation: mask-open 560ms var(--ease-out-expo) both; }

/* Fail-safe: anything script hides before animating shows itself after 2.5 s if the script never runs. */
@keyframes nv-failsafe { to { opacity: 1; transform: none; translate: none; } }
html[data-motion="full"] .kinetic .w > span { transform: translateY(108%); animation: nv-failsafe 0s 2.5s forwards; }
html[data-motion="simplified"] .kinetic .line { opacity: 0; animation: nv-failsafe 0s 2.5s forwards; }

/* ---------------------------------------------------------------------------------------------------------------
   10. Responsive: recomposed, not shrunk (spec section 6)
   --------------------------------------------------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .gallery[data-view="editorial"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery[data-view="editorial"] .item { grid-column: auto; }
  .hero .lede { grid-column: 3 / -1; }
  .project-body h2, .project-demo h2 { grid-column: 1 / -1; position: static; margin-bottom: 24px; }
  .points, .project-links, .project-demo .demo { grid-column: 1 / -1; }
  .project-media { aspect-ratio: 16 / 10; }
}
@media (max-width: 700px) {
  :root { --header-h: 64px; }
  .site-header { gap: 8px 12px; }
  .site-nav { margin-left: auto; }
  .hero { padding-top: 32px; }
  .hero .lede { grid-column: 1 / -1; }
  .sig-wide { display: none; }
  .sig-tall { display: block; max-width: 420px; margin-inline: auto; }
  .work-head { grid-template-columns: minmax(0, 1fr); }
  .gallery-status { grid-column: 1; grid-row: auto; }
  .controls { flex-direction: column; align-items: flex-start; }
  /* Phone composition: one column, the art-directed phone crop fills its plate, items step in and out. */
  .gallery[data-view="editorial"] { grid-template-columns: minmax(0, 1fr); row-gap: 56px; }
  .gallery[data-view="editorial"] .item:nth-child(even of :not([hidden])) { margin-top: 0; margin-left: 14%; }
  .gallery[data-view="editorial"] .item:nth-child(odd of :not([hidden])) { margin-right: 6%; }
  .item-media { aspect-ratio: var(--ratio-m, 4 / 5); }
  .plate img { inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--focal-m, 50% 50%); }
  .plate::after { bottom: 8%; }
  .gallery[data-view="index"] .item { grid-template-columns: 72px minmax(0, 1fr); gap: 4px 16px; }
  .gallery[data-view="index"] .item-media { height: 90px; width: 72px; aspect-ratio: auto; }
  .gallery[data-view="index"] .item-text { grid-template-columns: minmax(0, 1fr); }
  .gallery[data-view="index"] .item-cat { grid-column: 1; grid-row: auto; }
  .gallery[data-view="index"] .item-summary { display: none; }
  .gallery[data-view="reel"] .item { width: 78vw; }
  .gallery[data-view="reel"] .item-media { height: auto; width: 100%; }
  .cta h2, .cta p { grid-column: 1 / -1; }
  .project-hero h1, .project-hero .lede { grid-column: 1 / -1; }
  .project-media { aspect-ratio: var(--ratio-m, 4 / 5); margin-inline: calc(var(--page-gutter) * -1); }
  .project-media .plate { border-radius: 0; }
  .project-media .plate img { inset: 0; width: 100%; height: 100%; }
  .project-next a { grid-template-columns: minmax(0, 1fr) 96px; }
  .call li { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .workspace li { grid-template-columns: minmax(0, 1fr); }
  .workspace span { text-align: left; }
  .site-footer { gap: 0 16px; padding-block: 4px; }
  .site-footer nav { display: contents; }
}
/* Phones (390 px first). The gallery opens as the swipe row (core/preferences.js and immersive.js choose the view), the
   controls fit one row (the filters open from a button, the views are icons), pictures sit at 60% of the width so the
   next one peeks, and type and space are sized to the screen. Nothing above 480 px changes. */
@media (max-width: 480px) {
  .hero { padding-top: 20px; }
  .hero h1, .project-hero h1 { font-size: clamp(2.25rem, 1.2rem + 5.6vw, 2.75rem); }
  .hero .lede, .project-hero .lede { font-size: 1.125rem; }
  .work { padding-block: 48px 0; }
  .work-head { gap: 12px; margin-bottom: 20px; }
  .work-head h2, .cta h2, .project-body h2, .project-demo h2 { font-size: 1.75rem; }
  .controls { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding-top: 12px; }
  .filter-toggle {
    display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 8px 14px;
    border: 1px solid var(--ink-dim); border-radius: var(--radius-2); background: var(--surface); color: var(--ink);
    font-size: var(--text-sm); font-weight: 600;
  }
  .filter-toggle::after {
    content: ""; width: 7px; height: 7px; border: solid currentColor; border-width: 0 2px 2px 0; rotate: 45deg; translate: 0 -2px;
    transition: rotate var(--dur-2) var(--ease-out), translate var(--dur-2) var(--ease-out);
  }
  .filter-toggle[aria-expanded="true"]::after { rotate: -135deg; translate: 0 2px; }
  .filters { display: none; order: 3; flex: 1 0 100%; }
  .filter-toggle[aria-expanded="true"] ~ .filters { display: flex; }
  .views { margin-left: auto; flex-wrap: nowrap; }
  .views button { justify-content: center; min-width: 44px; padding-inline: 8px; }
  .views .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .gallery[data-view="editorial"] { row-gap: 40px; }
  .gallery[data-view="reel"] .item { width: 60vw; }
  .gallery[data-view="reel"] .item-title { font-size: 1.25rem; }
  .reel-hint { display: none; }
  .reel-steps button { width: 44px; height: 44px; }
  .cta { padding-block: 64px 48px; }
  .project-body, .project-demo { padding-block: 48px 0; }
  .project-next { margin-top: 48px; }
  /* A project's lede shows two lines; the label under it opens the rest (a checkbox, so it needs no script). */
  .more-toggle { display: block; position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
  .project-hero .lede { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
  .more-toggle:checked ~ .lede { display: block; }
  .more-label { display: inline-flex; align-items: center; justify-self: start; grid-column: 1 / -1; min-height: 44px; margin-top: -12px; font-size: var(--text-sm); font-weight: 600; color: var(--accent); cursor: pointer; }
  .more-open, .more-toggle:checked ~ .more-label .more-closed { display: none; }
  .more-toggle:checked ~ .more-label .more-open { display: inline; }
  .more-toggle:focus-visible ~ .more-label { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-1); }
}
@media (max-width: 420px) {
  .site-nav { display: none; }
  .site-header .magnet { margin-left: auto; }
  .site-header .btn { padding-inline: 12px; font-size: 14px; } /* wordmark and action fit side by side at 320 px */
}
@media (min-width: 1680px) {
  .gallery[data-view="editorial"] { max-width: 1680px; }
}

/* ---------------------------------------------------------------------------------------------------------------
   11. Reduced motion and forced colours
   --------------------------------------------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .magnet, .plate img, .btn, .filters button::after, .views button::after, .filter-toggle::after, .item-title, .cursor-preview { transition: none; }
  .btn:hover, .btn:active { transform: none; }
}
html[data-motion="reduced"] .magnet, html[data-motion="reduced"] .plate img { transition: none; translate: none; }
@media (forced-colors: active) {
  .plate { border: 1px solid CanvasText; }
  .filters button[aria-pressed="true"], .views button[aria-pressed="true"] { outline: 2px solid Highlight; }
  .sig .spine, .sig .node { stroke: CanvasText; }
  .layer-environment { display: none; }
}

/* nexverto.com link rule: no link carries a resting underline. */
a { text-decoration: none !important; }
