/* ==========================================================================
   layout.css — one block per region, in document order.
   Shared across index.html, about.html, contact.html.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Header — identical on every page
   -------------------------------------------------------------------------- */

.site-header{
  padding:clamp(3rem, 9vh, 6rem) 0 0;
  text-align:center;
}

.wordmark{
  font-family:var(--font-display);
  font-weight:500;
  font-size:var(--size-wordmark);
  letter-spacing:var(--track-wordmark);
  text-indent:var(--track-wordmark);
  text-transform:uppercase;
  line-height:1.1;
  margin:0;
}

.wordmark a{ text-decoration:none; }

.role{
  font-size:var(--size-label);
  font-weight:400;
  color:var(--muted);
  margin:1.1rem 0 0;
  letter-spacing:0.2em;
  text-indent:0.2em;
}

.site-nav{
  margin-top:clamp(2rem, 5vh, 3.25rem);
  padding-bottom:1.25rem;
  border-bottom:1px solid var(--rule);
  display:flex;
  justify-content:center;
  gap:clamp(1.5rem, 4vw, 2.75rem);
}

/* Current page. Set with aria-current="page" in the markup, so the
   styling and the accessibility signal can't drift apart. */
.site-nav a[aria-current="page"]{
  color:var(--ink);
}


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

.page{ padding:var(--page-top) 0 0; }


/* --------------------------------------------------------------------------
   Film entries (work page)
   -------------------------------------------------------------------------- */

/* Poster left, text right. flex-wrap rather than a media query: when the
   poster and a --film-text-min text column no longer fit side by side, the
   text drops underneath on its own. No breakpoint to keep in sync. */
.film{
  display:flex;
  flex-wrap:wrap;
  align-items:flex-start;
  gap:var(--film-gap);
}

.film + .film{ margin-top:clamp(3.5rem, 8vh, 5.5rem); }

.film__poster-link{
  flex:0 1 var(--poster-w);
  max-width:100%;
}

.film__text{ flex:1 1 var(--film-text-min); }

/* The meta block carries top margin when it sits under a poster in the
   one-column case; alongside one it should start level with the artwork. */
.film__text > .film__meta:first-child{ margin-top:0; }

/* Box holding the Vimeo embed. Set to the film's native ratio, not 16:9,
   so the player matches the stills below it and adds no letterbox of its
   own. --frame-bg shows while the player loads. */
.film__frame{
  position:relative;
  aspect-ratio:var(--ratio-film);
  background:var(--frame-bg);
  overflow:hidden;
}

.film__frame iframe,
.film__frame img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:0;
  object-fit:cover;
}

/* Poster — the film's entry on the work page, and a link into its page.
   Deliberately narrow: a 2:3 image at full measure is 1440px tall, so the
   visitor would scroll past a poster to reach anything else. The work page
   carries nothing but 2:3 posters and the film page carries nothing but
   1.90:1 stills, so no two image shapes ever compete in one column. */
.film__poster{
  max-width:var(--poster-w);
  transition:opacity var(--ease);
}

a:hover > .film__poster{ opacity:var(--dim); }

.film__title a{ text-decoration:none; }

.film__meta{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:0.75rem 1.25rem;
  margin-top:1.5rem;
}

.film__title{
  font-family:var(--font-display);
  font-weight:500;
  font-size:var(--size-title);
  letter-spacing:0.02em;
  margin:0;
}

.film__tag{
  font-family:var(--font-display);
  font-size:var(--size-label);
  letter-spacing:0.16em;
  text-transform:uppercase;
  color:var(--muted);
}

.film__logline{
  margin:0.85rem 0 0;
  max-width:52ch;
  font-size:var(--size-logline);
  line-height:1.65;
}

/* Each credit is one flex item that can't break internally, so a role never
   gets separated from the name it belongs to. Lines break between credits,
   never inside one. The separator hangs off the end of each item so a
   wrapped line never opens with a stray middot. */
/* Credits — one per line, role and name in two columns.

   The run-on billing block this replaces set roles and names in identical
   type, so "Production Sound Johnny Caicedo" read as one four-word blob.
   The fix isn't the line break, it's the contrast: roles take the same
   small tracked uppercase the site uses for every other label, names take
   the serif at reading size. A job title can't be mistaken for a person. */
.credits{
  margin:0;
  padding-top:1.75rem;
  border-top:1px solid var(--rule);

  /* max-content sizes the role column to the longest label rather than to
     a magic number, so adding SUPERVISING SOUND EDITOR later widens it
     instead of wrapping it. minmax(0, …) lets it shrink and wrap on a
     phone rather than pushing the page sideways. */
  display:grid;
  grid-template-columns:minmax(0, max-content) minmax(0, 1fr);
  align-items:baseline;
  column-gap:var(--credits-gap);

  /* No row-gap: the space belongs to the start of each credit, not between
     grid rows. That way a role carrying two names keeps them tight enough to
     read as one credit, while the credits themselves stay apart. */
  row-gap:0;
}

.credits__row + .credits__row > .credits__role,
.credits__row + .credits__row > .credits__name:first-of-type{
  margin-top:1.1rem;
}

/* The rows exist to group each dt/dd pair semantically; display:contents
   lets their dt and dd become grid items so the columns line up. */
.credits__row{ display:contents; }

/* Stated on the items, not left to align-items on .credits. align-self:auto
   has to resolve through a display:contents row, which is exactly the corner
   browsers have disagreed on; saying it here removes the question. */
.credits__role,
.credits__name{ align-self:baseline; }

/* Both columns are pinned explicitly rather than left to auto-placement, so a
   role carrying two names puts the second one under the first instead of
   knocking it into the label column. */
/* --credits-lift is an optical correction, so it's applied with relative
   positioning: it moves the glyphs without moving the row the grid measured. */
.credits__role{
  grid-column:1;
  position:relative;
  top:calc(-1 * var(--credits-lift));
  font-family:var(--font-display);
  font-size:var(--size-label);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:var(--muted);
}

/* nowrap sets the priority under space pressure: a person's name holds its
   line and the role wraps instead. A role reads fine over two lines; a name
   broken across them reads as two people. Watch this if you ever credit a
   name longer than the widest role label. */
.credits__name{
  grid-column:2;
  margin:0;
  font-size:var(--size-logline);
  white-space:nowrap;
}

/* Stills. Stacked full-measure with a tight gap so they read as one
   filmstrip rather than separate sections. The files are cropped to
   the film's native 1.90:1 — no baked-in letterbox, so the page does the
   letterboxing and the frames sit clean on white. */
.film__stills{
  margin-top:clamp(2rem, 5vh, 3rem);
  display:flex;
  flex-direction:column;
  gap:var(--stills-gap);
}

/* Variant: no footage yet. A rule stands in for the frame, so the
   absence reads as a choice rather than a broken embed. */
.film--text{
  border-top:1px solid var(--rule);
  padding-top:1.75rem;
}

/* With no poster the text has the whole measure, so the logline doesn't
   need the 52ch column it would need beside one — it sits on a single
   line. Same caveat as the film page: keep it under ~110 characters. */
.film--text .film__logline{
  max-width:none;
  text-wrap:pretty;
}


/* --------------------------------------------------------------------------
   Film page (family-style.html)

   One film, its own page. Everything here is 1.90:1 or text — the poster
   stays on the work page so the two shapes never share a column.
   -------------------------------------------------------------------------- */

/* .film__tag is a <span> inside .film__meta on the work page and a <p> of
   its own here, so it has to carry no margin and take spacing from context. */
.film-page__title + .film__tag{
  display:block;
  margin:0.9rem 0 0;
}

.film-page__title{
  font-family:var(--font-display);
  font-weight:500;
  font-size:var(--size-film-title);
  letter-spacing:0.02em;
  line-height:1.15;
  margin:0;
}

/* The player. Sits above the logline — someone who came here to watch
   shouldn't have to read a paragraph first.

   Overrides .film__frame's ratio: this box has to match the uploaded file,
   not the picture inside it. At --ratio-film the player had 1.90:1 to work
   with and a 16:9 file to place, so it pillarboxed and filled the gap with
   its own background — white bars down both edges. At --ratio-source the
   file fills the frame exactly and only the film's own black letterbox
   shows, which is invisible against --paper. */
.film-page__player{
  margin-top:1.75rem;
  aspect-ratio:var(--ratio-source);
}

/* Logline under the player. Runs the full measure rather than a 52ch
   column: a logline is one sentence, so at this size it lands on a single
   line that ends where the player ends, instead of breaking mid-air in the
   middle of the page. Keep loglines under ~110 characters or this wraps to
   a second line long enough to be a chore to read. */
.film-page__logline{
  margin-top:1.6rem;
  max-width:none;
  text-wrap:pretty;
}

/* The credits sit after the stills. The rule and the gap stop them reading
   as a caption for the still directly above. */
.film-page__credits{ margin-top:clamp(2.5rem, 6vh, 4rem); }


/* --------------------------------------------------------------------------
   About page
   -------------------------------------------------------------------------- */

.bio{
  max-width:var(--measure-text);
  font-size:var(--size-lead);
  line-height:1.7;
}

/* Keeps the paragraph from ending on a two-word runt line. */
.bio p{ text-wrap:pretty; }

.bio p{ margin:0 0 1.25rem; }
.bio p:last-child{ margin-bottom:0; }

.portrait{
  max-width:340px;
  margin:0 0 2.5rem;
}


/* --------------------------------------------------------------------------
   Contact page
   -------------------------------------------------------------------------- */

/* Centred, unlike Work and About. Those pages carry enough content to hold a
   left margin; this one is a single row, and left-aligning it under a centred
   header gives the page two competing axes and a large empty right side. */
.contact{ text-align:center; }

/* Four marks, one line, none of them labelled -- so every link carries an
   aria-label in the markup. That is the only name a screen reader gets;
   without it these are four blank links. */
.contact__list{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:var(--contact-gap);
}

/* Each link is a --contact-slot square with its mark centred in it. The square
   never shows; it exists so the target clears the ~44px a thumb needs whatever
   --social-mark is set to. */
.contact__link{
  width:var(--contact-slot);
  height:var(--contact-slot);
  display:flex;
  align-items:center;
  justify-content:center;
  /* Three of these wrap an <svg>, which takes no underline, so the missing
     reset would show up only on a mark that is really text. */
  text-decoration:none;
  color:var(--muted);
  transition:color var(--ease);
}

.contact__link:hover{ color:var(--ink); }

/* Every mark is a filled path in currentColor, so the hover above is one rule
   for all four rather than one per mark. All solid by design: an outline glyph
   beside solid ones reads lighter at the same size no matter how it is tuned,
   which is what put the row out of balance while these were hand-drawn. */
.contact__list svg{
  width:var(--social-mark);
  height:var(--social-mark);
  flex:none;
}

/* Selector carries svg. for the same specificity reason as the wordmark. */
.contact__list svg.contact__pictograph{
  width:calc(var(--social-mark) * var(--mark-scale-mail));
  height:calc(var(--social-mark) * var(--mark-scale-mail));
}

/* IMDb has never had a pictograph -- its mark is a lettermark, so it is sized
   by height and left to find its own width. There is no setting where four
   letters occupy a square.

   These are the real letterforms: IMDb's is a heavy condensed grotesque and
   Archivo at weight 600 was never going to pass for it. Their official lockup
   is the wordmark inside a rounded frame, shipped as one compound path, so
   dropping its first sub-path leaves the letters alone.

   Selector carries svg. so it outweighs the square sizing above. */
.contact__list svg.contact__wordmark{
  width:auto;
  height:calc(var(--social-mark) * 0.55);
}

/* Applied with opacity rather than a dimmer colour so the single hover rule
   still works: the correction rides on top of whatever colour the link is,
   instead of needing its own hover value. */
.contact__link--word{ opacity:var(--mark-dim-word); }

.contact__note{
  max-width:46ch;
  margin:2rem auto 0;
  color:var(--muted);
}


/* --------------------------------------------------------------------------
   Tech page (tech/index.html)

   Reached only by handing out the URL. Shares the type and colour of the film
   pages because there is one person behind both and no reason to design twice;
   kept apart by routing, not by looking different. Nothing on the film side
   links here, and this page carries no nav.
   -------------------------------------------------------------------------- */

/* The film pages get their header rule from .site-nav's border. There is no nav
   here, so the header draws its own. */
.site-header--plain{
  padding-bottom:1.25rem;
  border-bottom:1px solid var(--rule);
}

.tech__links{
  display:flex;
  flex-wrap:wrap;
  gap:0.75rem 1.75rem;
  margin:0;
}

/* Each link is its mark plus its word, so the whole pair is one target rather
   than a 15px glyph next to a separate one. */
.tech__links a{
  display:inline-flex;
  align-items:center;
  gap:var(--link-gap);
}

/* flex:none stops a long label squeezing the glyph out of shape when the row
   wraps on a phone. */
.tech__links svg{
  width:var(--link-mark);
  height:var(--link-mark);
  flex:none;
}

/* For any mark that runs to the edge of its own viewBox rather than sitting
   inside padding. Scaled, not dimmed: shrinking a solid reads as sized, while
   a lightened one reads as disabled. */
.tech__links svg.mark--bleed{
  width:calc(var(--link-mark) * var(--link-bleed));
  height:calc(var(--link-mark) * var(--link-bleed));
}

/* Sections are divided by a rule rather than by space alone: with four jobs of
   very different lengths, space alone stops reading as a boundary. Same idiom as
   the credits block and .film--text on the film pages. */
.tech__section{ margin-top:2.75rem; }

.tech__section + .tech__section{
  margin-top:var(--section-gap);
  padding-top:var(--section-gap);
  border-top:1px solid var(--rule);
}

/* No rule above the first: the header already draws one directly above the link
   row, and a second hairline a few lines below reads as a mistake.

   Set in --ink, not the --muted the smaller labels use. A heading that names a
   section should outrank the job titles beneath it, and at this size muted grey
   would leave it quieter than the company names it sits over. */
.section-title{
  font-family:var(--font-display);
  font-weight:500;
  font-size:var(--size-section);
  letter-spacing:var(--track-section);
  text-transform:uppercase;
  color:var(--ink);
  margin:0 0 1.6rem;
}

.job + .job{ margin-top:var(--job-gap); }

/* Company, role and dates on one line while there is room, stacking in that
   order when there isn't. baseline rather than centre so the three different
   type sizes sit on a common line. */
.job__head{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:0.35rem 1.25rem;
  margin-bottom:0.9rem;
}

/* Company avatars, as supplied: 400px squares, three of them full-bleed colour
   and Meta's a glyph on white. Left in colour rather than forced monochrome --
   these are the companies' marks, not site furniture.

   The hairline border is what makes them a set. Round a white tile on a white
   page and it disappears; the border gives Meta the same silhouette as the three
   coloured squares, at the cost of being nearly invisible on those three. That
   trade is the right way round.

   align-self:center because .job__head aligns on the baseline, which for an
   image means its bottom edge -- it would hang below the company name. */
.job__logo{
  flex:none;
  align-self:center;
  width:var(--job-logo);
  height:var(--job-logo);
  border-radius:var(--job-logo-radius);
  border:1px solid var(--rule);
}

.job__co{
  font-family:var(--font-display);
  font-weight:500;
  font-size:var(--size-title);
  letter-spacing:0.02em;
  margin:0;
}

/* The business unit under a parent company — "Oracle Cloud Infrastructure"
   under Oracle. Set down to label size so the company still reads as the
   heading and this reads as a qualifier on it.

   The gap is a margin, not the space character that used to sit between them in
   the markup: one space at 18px is about 5px, while the flex gap to the role
   beside it is 20px, so the two read as jammed together and then flung apart. */
.job__unit{
  margin-left:var(--job-unit-gap);
  font-weight:400;
  font-size:var(--size-label);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:var(--muted);
}

.job__role,
.job__dates{
  font-family:var(--font-display);
  font-size:var(--size-label);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:var(--muted);
  margin:0;
}

/* Dates pushed to the far edge on a wide screen; margin-left:auto rather than
   justify-content so it collapses harmlessly when the row wraps on a phone. */
.job__dates{ margin-left:auto; }

/* list-style:none with a hanging bullet drawn by ::before, because the browser
   default marker sits at a size and colour we don't control. */
.job__points{
  list-style:none;
  margin:0;
  padding:0;
  max-width:var(--measure-text);
  font-size:var(--size-logline);
  line-height:1.65;
}

.job__points li{
  position:relative;
  padding-left:1.15rem;
}

.job__points li + li{ margin-top:0.7rem; }

.job__points li::before{
  content:"";
  position:absolute;
  left:0;
  /* 0.82em down the line box puts the dot on the x-height rather than the cap
     line, which is where the eye expects it next to lowercase text. */
  top:0.82em;
  width:4px;
  height:1px;
  background:var(--muted);
}

/* Label/value pairs — skills, education. Same two-column idea as the film
   credits, but the value wraps: a tools list is a paragraph, where a person's
   name is not. */
.spec{
  margin:0;
  display:grid;
  grid-template-columns:minmax(0, max-content) minmax(0, 1fr);
  column-gap:var(--spec-gap);
  row-gap:0;
}

.spec__row{ display:contents; }

.spec__row + .spec__row > .spec__key,
.spec__row + .spec__row > .spec__val{ margin-top:var(--spec-row); }

.spec__key,
.spec__val{ align-self:baseline; }

.spec__key{
  grid-column:1;
  position:relative;
  top:calc(-1 * var(--credits-lift));
  font-family:var(--font-display);
  font-size:var(--size-label);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  color:var(--muted);
}

.spec__val{
  grid-column:2;
  margin:0;
  font-size:var(--size-logline);
  line-height:1.6;
}


/* --------------------------------------------------------------------------
   Footer — identical on every page
   -------------------------------------------------------------------------- */

.site-footer{
  margin-top:var(--stack);
  padding:2rem 0 3rem;
  border-top:1px solid var(--rule);
  font-family:var(--font-display);
  font-size:var(--size-footer);
  letter-spacing:var(--track-footer);
  text-transform:uppercase;
  color:var(--muted);
}
