/* Ramuel Galarza: base styles.
   Plain white page. One typeface (ABC Monument Grotesk Medium), one text size and one tiny label size,
   tight leading, hairline rules: the type system of a Cargo site. All spacing is on an 8px scale. The objects are neutral
   (white, grey, black) so the photographs and film stills are the only colour.
   Breakpoints: mobile under 768px, desktop 768px and up. */

@property --u { syntax: '<length>'; inherits: true; initial-value: 1px; }

/* ABC Monument Grotesk (Dinamo). The six cuts live in /fonts; only the ones a page uses are fetched. */
@font-face { font-family: "ABC Monument Grotesk"; src: url("../fonts/ABCMonumentGrotesk-Regular.otf") format("opentype"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "ABC Monument Grotesk"; src: url("../fonts/ABCMonumentGrotesk-RegularItalic.otf") format("opentype"); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "ABC Monument Grotesk"; src: url("../fonts/ABCMonumentGrotesk-Medium.otf") format("opentype"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "ABC Monument Grotesk"; src: url("../fonts/ABCMonumentGrotesk-MediumItalic.otf") format("opentype"); font-weight: 500; font-style: italic; font-display: swap; }
@font-face { font-family: "ABC Monument Grotesk"; src: url("../fonts/ABCMonumentGrotesk-Bold.otf") format("opentype"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "ABC Monument Grotesk"; src: url("../fonts/ABCMonumentGrotesk-BoldItalic.otf") format("opentype"); font-weight: 700; font-style: italic; font-display: swap; }

:root {
  --bg: #fff;
  --ink: #161616;
  --ink-2: #595959;            /* 7:1 on white */
  --line: #d6d6d3;             /* hairline rules */
  --alert: #b3261e;            /* form errors: 6.5:1 on white */
  --font: "ABC Monument Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --fw: 500;                   /* everything is set in the Medium cut */

  /* Spacing: every gap, margin and padding is one of these. An 8px scale, with 4 for the smallest gaps. */
  --s-4: .25rem;
  --s-8: .5rem;
  --s-16: 1rem;
  --s-24: 1.5rem;
  --s-32: 2rem;
  --s-48: 3rem;
  --s-64: 4rem;
  --s-96: 6rem;

  /* Type sits on the same grid: 17px on a 20px line on phones, 20px on a 24px line from 768px up. */
  --fs: 1.0625rem;
  --lh: 1.25rem;
  --fs-label: .75rem;          /* the tiny section labels, on a 16px line */
  --lh-label: 1rem;
  --indent: var(--s-32);       /* paragraphs run on with an indent, not a gap */
  --hang: var(--s-24);         /* hanging indent for wrapped lines in lists */
  --gutter: var(--s-16);       /* THE gap: page margin, under every rule, and between columns. 16px on phones, 24px from 768px */
  --bar: var(--s-48);          /* height of one header row */
  --head: calc(var(--bar) * 2 - var(--s-8));   /* the sticky header: two rows on a phone, one from 768px */
  --col-label: 7rem;           /* the label column of every ruled list (About, Film, Photography) */
  --measure: 52rem;            /* how wide a text block may run */

  /* object materials */
  --m-white: #fcfcfb;
  --m-paper: #f3f2ee;
  --m-light: #e8e8e6;
  --m-dark: #2b2b2b;
  --m-black: #141414;

  color-scheme: light;
}
/* Dark mode: the page goes dark, the objects stay as they are. It follows the visitor's system
   setting until they choose with the Dark / Light control in the header. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #111110; --ink: #f2f2ef; --ink-2: #a8a8a3; --line: #363634; --alert: #ff8a80;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #111110; --ink: #f2f2ef; --ink-2: #a8a8a3; --line: #363634; --alert: #ff8a80;
  color-scheme: dark;
}
@media (min-width: 768px) {
  :root { --fs: 1.25rem; --lh: 1.5rem; --indent: var(--s-48); --hang: var(--s-64); --gutter: var(--s-24); --head: var(--bar); --col-label: 14rem; }
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-top: var(--head); }
:root[data-motion="on"] { scroll-behavior: smooth; }
html.modal-open { overflow: hidden; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs);
  font-weight: var(--fw);
  line-height: var(--lh);
  -webkit-font-smoothing: antialiased;
}
[hidden] { display: none !important; }
img { max-width: 100%; display: block; }
h1, h2, h3, h4 { margin: 0; font: inherit; text-wrap: balance; }
p, ul, ol, dl, dd, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
i, em { font-style: italic; }
b, strong { font-weight: 700; }
button { font: inherit; color: inherit; }

/* Links stand alone as plain text, the Cargo way; they underline on hover. Links inside a sentence stay underlined. */
a { color: inherit; text-decoration: none; text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { text-decoration: underline; }
.prose a, p > a:not(:only-child) { text-decoration: underline; }
a.out::after { content: "\00a0↗"; content: "\00a0↗" / ""; }

.prose p + p { text-indent: var(--indent); }
.soft { color: var(--ink-2); }
.label { font-size: var(--fs-label); line-height: var(--lh-label); }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Focus: a dark ring with a white ring inside it, so one of them always shows. */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; box-shadow: 0 0 0 3px var(--bg); }
:focus:not(:focus-visible) { outline: none; }
[tabindex="-1"]:focus { outline: none; box-shadow: none; }

.skip-link {
  position: absolute; left: var(--gutter); top: -6rem; z-index: 100;
  display: inline-flex; align-items: center; min-height: var(--s-48); padding: 0 var(--s-16);
  background: var(--ink); color: var(--bg); text-decoration: none;
}
.skip-link:focus { top: var(--s-8); }

/* Controls are plain type, the Cargo way: an action sits in square brackets, like [Play];
   a choice that holds a state (on/off, chosen) has a small dot before it, filled when on.
   No boxes. They underline on hover. The text is one line; the hit area is 48px tall. */
.act {
  appearance: none; border: 0; margin: 0; padding: 0; background: none;
  display: inline-flex; align-items: center; min-height: var(--s-48);
  color: inherit; text-align: left; text-decoration: none; white-space: nowrap; cursor: pointer;
}
.act::before { content: "["; content: "[" / ""; }
.act::after { content: "]"; content: "]" / ""; }
.act:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; }
.act[aria-pressed]::before, .act[aria-checked]::before, .act[aria-current]::before {
  content: ""; flex: none; width: var(--s-8); height: var(--s-8); margin-right: var(--s-8);
  border-radius: 50%; border: 2px solid currentColor;
}
.act[aria-pressed]::after, .act[aria-checked]::after, .act[aria-current]::after { content: none; }
.act[aria-pressed="true"]::before, .act[aria-checked="true"]::before, .act[aria-current="true"]::before { border-width: var(--s-4); }
.act[aria-disabled="true"] { color: var(--ink-2); cursor: default; text-decoration: none; }
.acts { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s-16); }

/* ---------- page ----------
   A hairline under the header and above every section. Each section has a tiny label under its rule,
   and its content beside the label on wide screens. */
.top {
  position: sticky; top: 0; z-index: 20;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: var(--gutter);
  margin: 0 var(--gutter); background: var(--bg); border-bottom: 1px solid var(--line);
}
.top nav { grid-column: 1 / -1; grid-row: 2; margin-top: calc(var(--s-8) * -1); }
@media (min-width: 768px) {
  .top { grid-template-columns: minmax(0, 1fr) auto auto; }
  .top nav { grid-column: auto; grid-row: auto; margin-top: 0; }
}
.top a { display: inline-flex; align-items: center; min-height: var(--bar); }
.top a[aria-current="true"], .top a[aria-current="page"] { text-decoration: underline; }
.top nav ul { display: flex; flex-wrap: wrap; gap: 0 var(--s-16); }
.top .tools { display: flex; align-items: center; gap: 0 var(--s-16); }
/* Spanish is swapped in by script: nothing is shown until it has been */
html[data-lang-pending] body { visibility: hidden; }
/* in the header the language and theme controls are plain text, like the links beside them */
.top .act { min-height: var(--bar); }
.top .act::before, .top .act::after { content: none; }
.top .tools .act { padding-inline: var(--s-4); margin-inline: calc(var(--s-4) * -1); }
/* Contact sits in the nav on wide screens; on a phone it moves up beside the language and theme controls,
   so the row of links fits on one line in both languages. Only one of the two is ever shown. */
@media (max-width: 767px) { .top nav .nav-contact { display: none; } }
@media (min-width: 768px) { .top .tools .tool-contact { display: none; } }
.top .act:hover { text-decoration: underline; }

/* a stage whose object could not be built takes no room */
.stage[data-mounted="error"] { display: none; }
.fallback a { text-decoration: underline; }
/* the editor's preview marks itself */
.draft-note { position: fixed; right: var(--gutter); bottom: var(--gutter); z-index: 50; margin: 0; padding: var(--s-4) var(--s-8); background: var(--ink); color: var(--bg); }

/* the 3D stages must never widen the page: clip sideways only, so things can still fall in from above */
main { padding: 0 var(--gutter); overflow-x: clip; }
.intro { padding-block: var(--gutter); max-width: 34em; }

/* One gap everywhere: the space under a rule, above the next one, beside a column and at the page edge are all --gutter. */
.row {
  display: grid; gap: var(--s-24); padding-block: var(--gutter);
  border-top: 1px solid var(--line);
}
.row-head { display: grid; gap: var(--s-16); align-content: start; max-width: 22rem; }
.row-head h2 { font-size: var(--fs-label); line-height: var(--lh-label); }
.row-body { display: grid; gap: var(--s-24); min-width: 0; }
.piece { display: grid; gap: var(--s-16); min-width: 0; width: 100%; max-width: var(--piece-max, 46rem); }
.caption { display: grid; gap: var(--s-4); }
.detail { max-width: var(--measure); }
@media (min-width: 768px) {
  .row { grid-template-columns: minmax(9rem, 2fr) minmax(0, 10fr); gap: var(--gutter); }
  /* the objects are large and get room: space above them, and between an object and its caption */
  .piece { gap: var(--s-24); }
  .piece > .stage { margin-block: var(--s-32) 0; }
}
@media (min-width: 1100px) {
  .row-body.split { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); column-gap: var(--gutter); align-items: start; }
  /* the portrait stays in view while the CV scrolls past */
  .row-body.split > .portrait { position: sticky; top: calc(var(--bar) + 1px + var(--gutter)); }
}
/* the credit at the very end: a hairline and one tiny line, on the page margin */
.credit { margin: 0 var(--gutter); padding-block: var(--gutter); border-top: 1px solid var(--line); }
.credit .label { text-box: trim-start cap alphabetic; }

/* The first line of a column starts at its cap height, not its line box, so text, labels and
   pictures that sit side by side all begin on exactly the same line under the rule. */
.intro > p:first-of-type, .row-head h2, .bio-text > p:first-child { text-box: trim-start cap alphabetic; }

/* a short screen (a phone held sideways, a zoomed-in page) cannot spare room for a header that stays put */
@media (max-height: 30rem) {
  .top { position: static; }
  html { scroll-padding-top: 0; }
  .row-body.split > .portrait { position: static; }
}

/* ---------- about: a plain black-and-white portrait, then the bio ---------- */
.portrait { display: grid; gap: var(--s-8); width: min(100%, 15rem); }
.portrait img { width: 100%; height: auto; filter: grayscale(1); }
@media (min-width: 768px) { .portrait { width: min(100%, 20rem); } }
@media (min-width: 1100px) { .portrait { width: 100%; } }

/* ---------- bio and CV, after a Cargo information page ----------
   The CV is a two-column list: a label or year on the left, entries with hanging indents on the right. */
.bio { max-width: var(--measure); }
.bio-text p + p { text-indent: var(--indent); }
.cv { display: grid; gap: var(--s-24); margin-top: var(--s-48); }
.cv dl { display: grid; gap: var(--s-24); margin: 0; }
.cv-head { margin-top: var(--s-24); text-transform: uppercase; letter-spacing: .01em; }
.cv-row { display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); column-gap: var(--s-16); }
/* a long address breaks rather than running off a narrow screen */
.cv-row dd { min-width: 0; overflow-wrap: anywhere; }
/* on a phone the stacked links get a little air, so each is easy to hit */
@media (max-width: 767px) { .cv-row dd p + p > a.out:only-child { display: inline-block; margin-top: var(--s-4); } }
.cv-row dt.caps { text-transform: uppercase; letter-spacing: .01em; }
.cv-row dd p { padding-left: var(--hang); text-indent: calc(var(--hang) * -1); }
.cv-row time { font-variant-numeric: tabular-nums; }


/* ---------- 3D engine ----------
   .stage  : the box an object lives in. It scales everything inside it.
   .scene  : sets the unit (--u) and the perspective.
   .obj    : the turning point. Its origin is the centre of the object's footprint on the floor.
   .box    : a cuboid made of six .face elements, sized by --w --h --d and placed by --x --y --z (all in units).
   .pivot  : an empty placed point, for hinges and groups.
   .plate  : one flat face.
   One unit is stage-width / --design, so an object drawn on a 640-unit canvas fits any stage width. */
.stage {
  position: relative; container-type: inline-size; width: 100%;
  aspect-ratio: var(--ratio, 4 / 3);
  cursor: grab; touch-action: pan-y;
}
.stage.is-dragging { cursor: grabbing; }
.stage.is-locked { cursor: auto; }
.scene {
  line-height: 1.2; color: #161616;      /* type on the objects keeps its own ink in dark mode */
  --u: calc(100cqw / var(--design, 640));
  position: absolute; inset: 0;
  perspective: calc(var(--u) * var(--persp, 1800));
  user-select: none; -webkit-user-select: none;
}
/* isometric: parallel projection, so there is no vanishing point */
.stage.is-iso > .scene { perspective: none; }
.obj, .box, .pivot, .plate { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-style: preserve-3d; }
.obj { left: 50%; top: var(--oy, 66%); }
.box, .pivot, .plate {
  transform:
    translate3d(calc(var(--x) * var(--u)), calc(var(--y) * var(--u)), calc(var(--z) * var(--u)))
    var(--r);
}
.box, .plate {
  --W: calc(var(--w) * var(--u));
  --H: calc(var(--h) * var(--u));
  --D: calc(var(--d) * var(--u));
}
.face {
  position: absolute; display: block; margin: 0; padding: 0; border: 0;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: var(--mat, var(--m-white)); color: inherit;
  box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .12);
}
/* shading: the engine sets --dark on every face from one fixed light */
.face::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: #000; opacity: var(--dark, 0); pointer-events: none;
}
.face[data-shade="off"]::after { content: none; }
.box > .f { width: var(--W); height: var(--H); left: calc(var(--W) / -2); top: calc(var(--H) / -2); transform: translateZ(calc(var(--D) / 2)); }
.box > .b { width: var(--W); height: var(--H); left: calc(var(--W) / -2); top: calc(var(--H) / -2); transform: rotateY(180deg) translateZ(calc(var(--D) / 2)); }
.box > .r { width: var(--D); height: var(--H); left: calc(var(--D) / -2); top: calc(var(--H) / -2); transform: rotateY(90deg) translateZ(calc(var(--W) / 2)); }
.box > .l { width: var(--D); height: var(--H); left: calc(var(--D) / -2); top: calc(var(--H) / -2); transform: rotateY(-90deg) translateZ(calc(var(--W) / 2)); }
.box > .t { width: var(--W); height: var(--D); left: calc(var(--W) / -2); top: calc(var(--D) / -2); transform: rotateX(90deg) translateZ(calc(var(--H) / 2)); }
.box > .u { width: var(--W); height: var(--D); left: calc(var(--W) / -2); top: calc(var(--D) / -2); transform: rotateX(-90deg) translateZ(calc(var(--H) / 2)); }
.plate > .face { width: var(--W); height: var(--H); left: calc(var(--W) / -2); top: calc(var(--H) / -2); }
/* Two faces that meet at an edge are drawn exactly to it, and when the page is zoomed the smoothing of those
   edges lets a hairline of whatever is behind show through. So every face of a box reaches half a pixel past
   its edges (padding outside its own size, pulled back by the margin): neighbours overlap and the seam closes.
   The shading on ::after covers that half pixel too, so the overlap never shows as a lighter line. */
.box > .face { box-sizing: content-box; margin: -.5px; padding: .5px; }
.plate.round > .face { border-radius: 50%; }
.plate.two-sided > .face { backface-visibility: visible; -webkit-backface-visibility: visible; }

/* materials */
.m-white { --mat: var(--m-white); }
.m-paper { --mat: var(--m-paper); }
.m-light { --mat: var(--m-light); }
.m-dark { --mat: var(--m-dark); color: #fff; }
.m-black { --mat: var(--m-black); color: #fff; }
/* chrome: the engine paints each face with what it reflects; this grey only shows before it has */
.m-chrome { --mat: #b4b8bd; }
.face[data-shade="mirror"] { box-shadow: none; background-blend-mode: hard-light, normal; }

/* soft contact shadow on the floor */
.ground {
  position: absolute; pointer-events: none;
  width: calc(var(--gw, 300) * var(--u)); height: calc(var(--gd, 200) * var(--u));
  left: calc(var(--gw, 300) * var(--u) / -2); top: calc(var(--gd, 200) * var(--u) / -2);
  transform: translate3d(calc(var(--gx, 0) * var(--u)), calc(1 * var(--u)), calc(var(--gz, 0) * var(--u))) rotateX(90deg);
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: rgba(0, 0, 0, .2); border-radius: calc(var(--u) * 14);
  filter: blur(calc(var(--u) * 14));
}

/* anything on an object that can be pressed */
.face.press, .press { cursor: pointer; }
.obj img { -webkit-user-drag: none; user-select: none; }

/* ---------- motion off ---------- */
:root[data-motion="off"] *, :root[data-motion="off"] *::before, :root[data-motion="off"] *::after {
  animation: none !important; transition: none !important;
}

/* ---------- Windows high contrast / forced colors ---------- */
@media (forced-colors: active) {
  :focus-visible { outline: 3px solid Highlight; box-shadow: none; }
  .act[aria-disabled="true"] { color: GrayText; }
  .face { border: 1px solid CanvasText; }
  .face::after, .ground { display: none; }
}

/* ---------- print: the text, in black on white, without the objects and controls ---------- */
@media print {
  :root, :root[data-theme="dark"] { --bg: #fff; --ink: #161616; --ink-2: #595959; --line: #d6d6d3; color-scheme: light; }
  .top { position: static; }
  .tools, .acts, .skip-link, .stage, .caption { display: none !important; }
  .film-laurels img { filter: none !important; mix-blend-mode: normal !important; }
}
