/* ============================================================
   Version B - immersive editorial prototype
   Self-contained: shares nothing with the Version A stylesheets.
   Dark-only by design.

   Colour is treated as light rather than surface: almost every hue
   below appears as a gradient, a glow or a blend, never as a large
   flat fill.
   ============================================================ */

:root {
  /* ground - near-black carrying a faint blue undertone so the
     atmosphere layers have something to sit in */
  --void:        #06070d;
  --void-2:      #0a0c16;
  --midnight:    #0f1c3a;

  /* ink */
  --paper:       #f2eee6;      /* warm off-white */
  --paper-dim:   #949bad;
  --paper-faint: #4e5468;

  /* light */
  --electric:    #2f6bff;
  --cyan:        #6fe6ff;
  --violet:      #7d5cff;
  --iris:        #ff9ad5;      /* used only as a refractive edge */

  --rule:        #1a1e2b;
  --focus:       var(--cyan);

  --measure:     72rem;
  --gutter:      clamp(1.25rem, 4vw, 4.5rem);
  --ease-out:    cubic-bezier(.16,.84,.28,1);

  /* pointer position, written by v2.js. Defaults keep the page
     sensible when nothing is tracking. */
  --px: 50%;
  --py: 40%;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--void);
  color: var(--paper);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 0.95rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  overflow-x: hidden;
}

a { color: inherit; }

:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

.shell { width: 100%; max-width: var(--measure); margin-inline: auto; padding-inline: var(--gutter); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip:focus {
  position: fixed; top: 1rem; left: 1rem; width: auto; height: auto; clip: auto;
  margin: 0; padding: 0.7rem 1rem; z-index: 100;
  background: var(--paper); color: var(--void);
  font: 600 0.8rem/1 ui-sans-serif, system-ui, sans-serif;
  letter-spacing: 0.08em; text-transform: uppercase;
}

/* ================= atmosphere =================================
   Three stacked layers, none of which repaint while the pointer
   moves. .atmos is a static wash. .glow and .iris-field are single
   elements the script moves and rotates with transform only, so the
   "light" tracks the cursor on the compositor. */
.atmos, .glow, .iris-field { position: fixed; pointer-events: none; }
.atmos { inset: 0; z-index: 0; }

.atmos {
  background:
    radial-gradient(75vmax 55vmax at 84% -10%, rgba(15, 28, 58, 0.9) 0%, transparent 60%),
    radial-gradient(60vmax 50vmax at 4% 106%, rgba(125, 92, 255, 0.14) 0%, transparent 58%),
    radial-gradient(95vmax 75vmax at 50% 46%, rgba(47, 107, 255, 0.06) 0%, transparent 72%);
}

.glow {
  top: 0; left: 0; z-index: 0;
  width: 46vmax; height: 46vmax; margin: -23vmax 0 0 -23vmax;
  background: radial-gradient(closest-side, rgba(111, 230, 255, 0.16), transparent 70%);
  opacity: 0; will-change: transform;
}

/* The refractive field: a conic sweep of the accent hues, blended as
   light. It is rotated and nudged by the pointer, which is what gives
   the "iridescent object turning" feeling without any WebGL. */
.iris-field {
  top: 0; left: 0; z-index: 0;
  width: 60vmax; height: 60vmax; margin: -30vmax 0 0 -30vmax;
  background: conic-gradient(from 0deg,
    rgba(111,230,255,0.20), rgba(47,107,255,0.16), rgba(125,92,255,0.18),
    rgba(255,154,213,0.13), rgba(111,230,255,0.20));
  filter: blur(60px);
  mix-blend-mode: screen;
  opacity: 0;
  will-change: transform;
}

/* Both live effects are desktop-only: a phone has no pointer to track
   and no budget for two extra compositor layers. */
.glow, .iris-field { display: none; }
@media (hover: hover) and (pointer: fine) {
  .glow, .iris-field { display: block; }
  .glow.is-live { opacity: 1; transition: opacity 0.7s var(--ease-out); }
  .iris-field.is-live { opacity: 1; transition: opacity 1.1s var(--ease-out); }

  .grain {
    position: fixed; inset: 0; z-index: 1; pointer-events: none;
    opacity: 0.03; mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  }
}
.grain { display: none; }

.site-head, main, .site-foot { position: relative; z-index: 2; }

/* ================= masthead ================================== */
.site-head {
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.1rem var(--gutter);
  font-size: 0.7rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--paper-dim);
  background: transparent; border-bottom: 1px solid transparent;
  transition: background-color 0.45s var(--ease-out), border-color 0.45s var(--ease-out);
}
.site-head.is-past-hero {
  background: rgba(6, 7, 13, 0.74);
  -webkit-backdrop-filter: blur(12px);   /* Safari still needs the prefix */
  backdrop-filter: blur(12px);
  border-bottom-color: var(--rule);
}
.site-head a { text-decoration: none; }
.masthead-mark { color: var(--paper); letter-spacing: 0.3em; }
.site-nav { display: flex; gap: clamp(1rem, 3vw, 2.25rem); }
.site-nav a { position: relative; padding-block: 0.2rem; }
.site-nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, var(--cyan), var(--violet));
  transform: scaleX(0); transform-origin: right;
  transition: transform 0.4s var(--ease-out);
}
.site-nav a:hover::after, .site-nav a:focus-visible::after { transform: scaleX(1); transform-origin: left; }
.site-nav a[aria-current="page"] { color: var(--paper); }

/* ================= hero ====================================== */
.hero {
  min-height: 100vh; min-height: 100svh;
  display: grid; grid-template-rows: 1fr auto; align-content: end;
  padding-block: 7rem 2.25rem;
}
.hero-inner { align-self: end; }

.hero-eyebrow {
  display: flex; align-items: center; gap: 0.9rem;
  margin: 0 0 clamp(1rem, 2vw, 1.75rem);
  font-size: 0.68rem; letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--cyan);
}
.hero-eyebrow::before {
  content: ""; width: clamp(1.5rem, 5vw, 3.5rem); height: 1px;
  background: currentColor; opacity: 0.5;
}

/* ---- contour field --------------------------------------------
   Seven nested curves that read two ways at once: as topographic
   contour lines and as sets of swell rolling in. Tight and folded at
   the top, opening out toward the bottom, which is the shape of the
   place itself, where the range meets the coast. Nothing is drawn
   literally; it is the same line family under two readings.
   Each band is its own <g> so the pointer can move them at different
   rates, which is what turns flat linework into depth. */
.hero-contours {
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none; overflow: hidden;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 55%, #000 25%, transparent 78%);
  mask-image: radial-gradient(120% 90% at 50% 55%, #000 25%, transparent 78%);
}
.hero-contours svg { width: 130%; height: 100%; margin-left: -15%; display: block; }
.hero-contours path {
  fill: none;
  /* stroke lives on the <svg> element in the markup, see the note there:
     a fragment URL in an external sheet is not resolved consistently. */
  stroke-width: 1.1;
  vector-effect: non-scaling-stroke;
}
.hero-contours g { will-change: transform; }

/* ---- living swell -------------------------------------------
   Two transforms per band, on two nested groups so they never fight
   over the same property: the outer <g> is where the pointer parallax
   is written from JS, the inner .band-flow carries this continuous
   drift from CSS.

   The motion is deliberately slow and small, a few pixels over twenty
   seconds or more, with each band on its own period so they pass
   through each other the way real swell does instead of marching in
   step. Nothing here is fast enough to pull the eye away from the
   name sitting on top of it. Transform only. */
@keyframes swell {
  0%   { transform: translate3d(-7px, 0, 0); }
  50%  { transform: translate3d(7px, -4px, 0); }
  100% { transform: translate3d(-7px, 0, 0); }
}

.band-flow {
  animation: swell var(--period, 24s) ease-in-out infinite;
  animation-delay: var(--phase, 0s);
  will-change: transform;
}
/* prime numbers of seconds keep the bands from re-syncing */
[data-band="1"] .band-flow { --period: 19s; --phase: -2s;  }
[data-band="2"] .band-flow { --period: 23s; --phase: -7s;  }
[data-band="3"] .band-flow { --period: 29s; --phase: -13s; }
[data-band="4"] .band-flow { --period: 31s; --phase: -4s;  }
[data-band="5"] .band-flow { --period: 37s; --phase: -19s; }
[data-band="6"] .band-flow { --period: 41s; --phase: -9s;  }
[data-band="7"] .band-flow { --period: 43s; --phase: -25s; }

/* Touch devices get the swell and nothing else: no pointer parallax to
   layer on top, so the whole field is dialled back a little. */
@media (hover: none), (pointer: coarse) {
  .hero-contours { opacity: 0.38; }
}

/* the name and its two chromatic ghosts share one grid cell */
.hero-name-stack { position: relative; z-index: 1; display: grid; }
.hero-name-stack > * { grid-area: 1 / 1; }

/* Display type is sized by whichever axis is scarcer. On a short or
   landscape screen the height budget wins, so the name never grows
   taller than the viewport it has to live in - that is what keeps the
   hero intact on a laptop, a tablet in landscape and a phone alike. */
.hero-name, .hero-ghost {
  margin: 0;
  font-family: Anton, "Arial Narrow", Impact, ui-sans-serif, sans-serif;
  font-weight: 400;
  font-size: clamp(2.6rem, min(15.5vw, 21svh), 15rem);
  line-height: 0.86;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}
.hero-name { color: var(--paper); position: relative; z-index: 2; }
.hero-name span, .hero-ghost span { display: block; }
.hero-name .is-outline {
  color: transparent;
  -webkit-text-stroke: 1px var(--paper-dim);
}

/* Chromatic edge separation. Two tinted copies offset a few pixels and
   blended as light - the same idea as a lens splitting colour, done
   with transforms so it costs nothing to move. Hidden from assistive
   tech and from anyone without a fine pointer. */
.hero-ghost {
  z-index: 1; pointer-events: none;
  mix-blend-mode: screen; opacity: 0;
  will-change: transform;
}
.hero-ghost[data-ghost="a"] { color: var(--cyan); }
.hero-ghost[data-ghost="b"] { color: var(--iris); }
.hero-ghost .is-outline { color: transparent; -webkit-text-stroke: 1px currentColor; }
@media (hover: hover) and (pointer: fine) {
  .hero-ghost.is-live { opacity: 0.42; }
}

.hero-rule {
  height: 1px; margin: clamp(1.5rem, 3vw, 2.5rem) 0 clamp(1rem, 2vw, 1.5rem);
  background: linear-gradient(90deg, var(--cyan), var(--violet) 30%, var(--paper-faint) 60%, transparent);
  transform-origin: left;
}

.hero-sub {
  display: flex; flex-wrap: wrap; gap: 0.5rem clamp(1rem, 4vw, 3rem); margin: 0;
  font-size: clamp(0.72rem, 0.68rem + 0.25vw, 0.85rem);
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--paper-dim);
}
.hero-sub b { font-weight: 500; color: var(--paper); }

.hero-cue {
  display: flex; align-items: center; gap: 0.7rem;
  font-size: 0.64rem; letter-spacing: 0.26em; text-transform: uppercase; color: var(--paper-faint);
}
.hero-cue i { display: block; width: 2.5rem; height: 1px; background: currentColor; transform-origin: left; }

/* ================= sections ================================== */
.section { padding-block: clamp(5rem, 12vh, 9rem); }

.section-label {
  display: flex; align-items: baseline; gap: 1rem;
  margin: 0 0 clamp(2rem, 5vw, 3.5rem);
  padding-top: 1rem; border-top: 1px solid var(--rule);
  font-size: 0.68rem; letter-spacing: 0.28em; text-transform: uppercase; color: var(--paper-dim);
  font-weight: 400;
}
.section-label b { font-weight: 400; color: var(--cyan); }

/* ================= work index ================================
   Each row carries its own mood through two custom properties, so the
   rule, the number and the preview all pick up that project's light. */
.work-list { border-top: 1px solid var(--rule); }

.work-row {
  --mood-1: var(--cyan);
  --mood-2: var(--electric);
  position: relative;
  display: grid; grid-template-columns: auto 1fr auto;
  align-items: baseline; gap: clamp(0.9rem, 3vw, 2.5rem);
  padding: clamp(1.5rem, 3.5vw, 2.6rem) 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none; overflow: hidden;
}
.work-row[data-mood="crew"] { --mood-1: #7fd4ff; --mood-2: var(--electric); }
.work-row[data-mood="nexp"] { --mood-1: #ff9448; --mood-2: #2748a8; }
.work-row[data-mood="song"] { --mood-1: var(--iris);  --mood-2: var(--violet); }

/* the rule under each row lights up in that project's colour */
.work-row::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, var(--mood-1), var(--mood-2) 55%, transparent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.6s var(--ease-out);
}
.work-row:hover::before, .work-row:focus-visible::before { transform: scaleX(1); }

.work-num {
  font-size: 0.7rem; letter-spacing: 0.2em; color: var(--paper-faint);
  transition: color 0.4s var(--ease-out);
}
.work-row:hover .work-num, .work-row:focus-visible .work-num { color: var(--mood-1); }

.work-title {
  margin: 0;
  font-family: Anton, "Arial Narrow", Impact, ui-sans-serif, sans-serif;
  font-weight: 400; font-size: clamp(1.5rem, min(5.4vw, 7svh), 4rem);
  line-height: 1; letter-spacing: 0.005em; text-transform: uppercase; color: var(--paper);
  /* long titles must never push the row wider than the screen */
  overflow-wrap: break-word; hyphens: auto;
  transition: transform 0.55s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .work-row:hover .work-title, .work-row:focus-visible .work-title {
    transform: translateX(clamp(0.5rem, 1.5vw, 1.25rem));
  }
}

.work-meta {
  font-size: 0.66rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--paper-dim); text-align: right;
}

.work-wipe {
  position: absolute; inset: 0; background: var(--void);
  transform: scaleX(0); transform-origin: right; pointer-events: none;
}

/* Inline poster, touch devices only.
   Declared as a background-image *inside* a (hover: none) query on
   purpose: browsers never fetch background images belonging to rules
   that do not match, so a desktop visitor never requests these files -
   and unlike a JS swap, this still works with scripting disabled.
   They are decorative; the title, credits and link carry the meaning,
   which is why they are aria-hidden. */
.work-figure { display: none; }

@media (hover: none) {
  .work-figure {
    display: block; grid-column: 1 / -1;
    margin: 1rem 0 0.25rem;
    background-repeat: no-repeat; background-position: center;
    background-size: cover;
    border: 1px solid var(--rule);
    position: relative;
  }
  .work-figure[data-fig="crew"] {
    aspect-ratio: 16 / 9;
    background-image: url("media/silva_crew_poster.jpg");
  }
  .work-figure[data-fig="nexp"] {
    aspect-ratio: 9 / 16; max-width: 62%;
    background-image: url("media/silva_nexp_poster.jpg");
  }
  /* the project's own light, laid over its poster */
  .work-figure::after {
    content: ""; position: absolute; inset: 0;
    box-shadow: inset 0 0 70px -12px var(--mood-1);
    opacity: 0.55;
  }
}

/* ================= hover preview ============================= */
.preview {
  /* Anchored to the centre of the viewport. The -50% offsets are applied
     by GSAP (xPercent/yPercent) so they compose with the scale tween
     instead of fighting it. The frame never follows the pointer. */
  position: fixed; top: 50%; left: calc(50% + clamp(2rem, 6vw, 7rem)); z-index: 3;
  width: var(--pv-w, 26rem); max-width: calc(100vw - 3rem);
  aspect-ratio: var(--pv-ar, 16 / 9);
  max-height: calc(100vh - 8rem);
  pointer-events: none; opacity: 0; display: none;
  border: 1px solid rgba(242, 238, 230, 0.10); background: rgba(10, 12, 22, 0.55);
  overflow: hidden; will-change: transform;
  box-shadow: 0 30px 80px -30px rgba(0,0,0,0.75);
}
@media (hover: hover) and (pointer: fine) { .preview { display: block; } }

/* the mood colour rims the frame like reflected light */
.preview::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 60px -10px var(--pv-mood, var(--cyan));
  opacity: 0.55;
}
.preview img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  opacity: 0; transition: opacity 0.55s var(--ease-out);
}
.preview img.is-ready { opacity: 1; }

/* Say Something has no still frame - it is audio. Instead of inventing
   one it gets an iridescent panel, which also happens to be its mood. */
.preview-audio {
  position: absolute; inset: 0; display: none;
  place-content: center; justify-items: center; gap: 1.1rem;
  background:
    radial-gradient(closest-side at 40% 35%, rgba(255,154,213,0.30), transparent 70%),
    radial-gradient(closest-side at 65% 70%, rgba(125,92,255,0.28), transparent 70%),
    var(--void-2);
}
.preview.is-audio .preview-audio { display: grid; }
.preview-audio span {
  font-size: 0.62rem; letter-spacing: 0.3em; text-transform: uppercase; color: var(--iris);
}
.preview-bars { display: flex; align-items: flex-end; gap: 4px; height: 3.5rem; }
.preview-bars i { width: 3px; background: var(--paper-dim); display: block; animation: bar 1.5s ease-in-out infinite; }
.preview-bars i:nth-child(1) { height: 40%; animation-delay: -1.2s; }
.preview-bars i:nth-child(2) { height: 75%; animation-delay: -0.9s; }
.preview-bars i:nth-child(3) { height: 55%; animation-delay: -0.6s; }
.preview-bars i:nth-child(4) { height: 95%; animation-delay: -0.3s; }
.preview-bars i:nth-child(5) { height: 62%; }
@keyframes bar { 0%,100% { transform: scaleY(0.45); } 50% { transform: scaleY(1); } }

/* ================= statement ================================= */
.statement p {
  max-width: 46ch; margin: 0 0 1.5rem;
  font-size: clamp(1.05rem, 1rem + 0.55vw, 1.5rem); line-height: 1.5; color: var(--paper);
}
.statement p + p { color: var(--paper-dim); font-size: 1rem; line-height: 1.7; }

.text-link {
  display: inline-flex; align-items: center; gap: 0.6rem; margin-top: 0.5rem;
  font-size: 0.7rem; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--cyan); text-decoration: none;
}
.text-link::after {
  content: ""; width: 1.6rem; height: 1px; background: currentColor;
  transition: width 0.35s var(--ease-out);
}
.text-link:hover::after, .text-link:focus-visible::after { width: 2.6rem; }

/* ================= contact ===================================
   Composed rather than dumped. The email stays the primary, at display
   scale; the phone sits directly under it as a labelled row at real
   reading size - not shrunk into the legal line the way it was. Both
   are equally reachable; only their weight differs. */
.contact { padding-block: clamp(4rem, 10vh, 7rem); }

.contact-invite {
  max-width: 30ch; margin: 0 0 clamp(1.5rem, 4vw, 2.5rem);
  font-size: clamp(1.05rem, 1rem + 0.5vw, 1.4rem);
  line-height: 1.45; color: var(--paper-dim);
}

/* Three channels of equal structural weight. The email leads by a
   step in scale and by sitting first, not by being a billboard: the
   old display-size address swamped the section and pushed the phone
   into the role of a footnote. */
.contact-grid {
  display: grid; gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: 1fr; align-items: start;
}
@media (min-width: 52rem) {
  .contact-grid { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }
}

.contact-list {
  display: grid; gap: 1.5rem 3rem; margin: 0;
  grid-template-columns: 1fr;
}
@media (min-width: 34rem) { .contact-list { grid-template-columns: repeat(3, minmax(0, auto)); } }

.contact-list > div { border-top: 1px solid var(--rule); padding-top: 1rem; }

.contact-list dt {
  margin: 0 0 0.5rem;
  font-size: 0.62rem; letter-spacing: 0.26em; text-transform: uppercase;
  color: var(--paper-faint);
}
.contact-list dd {
  margin: 0;
  font-size: clamp(0.95rem, 0.9rem + 0.25vw, 1.1rem);
  line-height: 1.4; color: var(--paper-dim);
}
.contact-list dd.is-primary {
  font-size: clamp(1.1rem, 1rem + 0.6vw, 1.45rem);
  color: var(--paper);
}
.contact-list a {
  text-decoration: none; color: inherit;
  border-bottom: 1px solid var(--paper-faint); padding-bottom: 2px;
  overflow-wrap: break-word;
  transition: color 0.3s var(--ease-out), border-color 0.3s var(--ease-out);
}
.contact-list a:hover, .contact-list a:focus-visible { color: var(--cyan); border-bottom-color: currentColor; }

/* ================= footer ====================================
   Now only what a footer should carry: the legal line and a way back. */
.site-foot { border-top: 1px solid var(--rule); padding-block: 2rem 2.5rem; }
.foot-grid {
  display: flex; flex-wrap: wrap; gap: 0.75rem 2rem;
  align-items: baseline; justify-content: space-between;
  font-size: 0.66rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--paper-faint);
}
.foot-grid p { margin: 0; }
.foot-grid a { text-decoration: none; }
.foot-grid a:hover { color: var(--paper-dim); }

/* ================= hero entrance =============================
   CSS, not GSAP: it starts at first paint. The name never fades - it
   is the LCP element, so it is painted at full opacity immediately and
   only settles in scale. */
@keyframes settle { from { transform: scale(1.028); } to { transform: none; } }
@keyframes lift   { from { opacity: 0; transform: translateY(0.6rem); } to { opacity: 1; transform: none; } }
@keyframes wipeX  { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.hero-name-stack { animation: settle 1s var(--ease-out) both; }
.hero-eyebrow    { animation: lift 0.7s var(--ease-out) 0.1s both; }
.hero-rule       { animation: wipeX 1s var(--ease-out) 0.45s both; }
.hero-sub        { animation: lift 0.7s var(--ease-out) 0.55s both; }
.hero-cue        { animation: lift 0.7s var(--ease-out) 0.8s both; }

/* ================= responsive ================================
   One system, four bands, plus height and pointer as separate axes -
   a tablet in landscape is short and wide, a phone is tall and narrow,
   and neither is served by width alone. */

/* phones: the meta drops under the title instead of fighting it */
@media (max-width: 47.99rem) {
  .work-row { grid-template-columns: auto 1fr; row-gap: 0.55rem; }
  .work-meta { grid-column: 2; text-align: left; }
  .hero-name .is-outline, .hero-ghost .is-outline { -webkit-text-stroke-width: 0.6px; }
  .section-label { flex-wrap: wrap; }
}

/* tablet */
@media (min-width: 48rem) {
  .hero { padding-block: 8rem 2.5rem; }
  .work-meta { max-width: 22ch; }
}

/* laptop and up: more air, the index gets room to breathe */
@media (min-width: 64rem) {
  .work-row { padding-block: 2.4rem; }
  .section { padding-block: clamp(6rem, 13vh, 10rem); }
}

/* large desktop: cap the measure so lines never run too long */
@media (min-width: 90rem) {
  :root { --measure: 78rem; }
}

/* Short viewports - laptops with browser chrome, phones in landscape.
   The hero stops trying to be full height and simply fits. */
@media (max-height: 34rem) {
  .hero { min-height: auto; padding-block: 5.5rem 2rem; }
  .hero-cue { display: none; }
  .site-head { padding-block: 0.7rem; }
}

/* Coarse pointers: bigger tap targets, no hover-dependent affordances */
@media (pointer: coarse) {
  .site-nav { gap: 1.25rem; }
  .site-nav a, .masthead-mark { padding-block: 0.55rem; }
  .work-row { padding-block: 1.6rem; }
}

/* ================= reduced motion ============================
   Everything resolves to its finished state. v2.js additionally
   refuses to initialise, so no pointer tracking happens at all. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important; scroll-behavior: auto !important;
  }
  .hero-name-stack, .hero-eyebrow, .hero-rule, .hero-sub, .hero-cue {
    animation: none; opacity: 1; transform: none;
  }
  .hero-contours { animation: none; transform: none; opacity: 0.3; }
  .band-flow { animation: none !important; transform: none !important; }
  .glow, .iris-field, .hero-ghost, .work-wipe { display: none; }
  .preview-bars i { animation: none; }
  .work-row::before { transform: scaleX(1); }
}
