/* ============================================================
   00. FONT FACES
   ============================================================

   Gaya Trial and Serial A Trial are both local/self-hosted —
   licensed trial files for this noncommercial college portfolio,
   not redistributed elsewhere. DM Mono is loaded separately via a
   Google Fonts <link> tag in index.html (see <head>), since no
   self-hosted copy of it exists in the project.
   ============================================================ */

@font-face {
  font-family: "Gaya Trial";
  src: url("../assets/fonts/gaya/gayatrial-regular.otf") format("opentype");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Gaya Trial";
  src: url("../assets/fonts/gaya/gayatrial-italic.otf") format("opentype");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
}

/*
  Only these two of the trial pack's 20 styles are used, per explicit
  authorization for this noncommercial portfolio: Bold (primary
  editorial heading weight) and Slanted15o (rare secondary accent).
  Every other variant (scan, blur, outline, pencil, rough, sticker,
  the other slant angles) is intentionally not copied into the
  project or referenced here.
*/
@font-face {
  font-family: "Serial A Trial";
  src: url("../assets/fonts/serial-a/SerialATRIAL-Bold.ttf") format("truetype");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

@font-face {
  font-family: "Serial A Trial";
  src: url("../assets/fonts/serial-a/SerialATRIAL-Slanted15o.ttf") format("truetype");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
}


/* ============================================================
   01. DESIGN TOKENS
   ============================================================ */

:root {
  --bg: #D4BCD2; /* Primary Background: Lavender Mist */
  --bg-alt: #ECC2DB; /* Secondary Background: Lilac Pink */
  --bg-card: #FDFBF7; /* Content Blocks: Off-White/Cream */
  --text-main: #2A1E2D; /* High contrast text: Dark Charcoal Purple */

  /*
    Accent system (replaces the old light yellow/gold/ochre trio,
    which was too low-contrast against the purple backgrounds).
  */
  --accent-soft: #2F4F8F; /* Editorial blue — Resume location subtitles, colophon labels, small secondary labels. Light-background use only: fails contrast on dark ink, so dark-ink secondary text uses --color-paper instead (see chapter-opener). */

  /*
    Vivid editorial hot pink, used for the same short, deliberate
    list of high-visibility interactive accents only (Broadcast/
    Resume/About page titles, Project Index active state, menu nav
    active/hover/focus, chapter opener titles) — see each selector's
    own comment for why it qualifies. Everywhere else keeps dark ink
    (--text-main) or the blue --accent-soft; this is not a global
    revert.
  */
  --accent-bright: #E83E83;

  /*
    #E83E83 on dark ink (#2A1E2D) measures ~4.12:1 — a pass for
    large text/controls (3:1) but a fail for small normal text
    (4.5:1). --accent-bright-readable exists only for the two small
    (10px) numerals that share the hot-pink treatment on dark ink:
    .menu-navigation__index and the active .project-index-row__number.
    Every large title/label stays on --accent-bright.
  */
  --accent-bright-readable: #F25A9B; /* ~5.08:1 on #2A1E2D — passes 4.5:1 normal text */

  /*
    --text-muted (and its --color-muted alias below) powers every
    short metadata label site-wide — dossier/broadcast index numbers,
    typology/date meta, "END OF PROJECT", "AWARDS", and Resume dates
    like "2016–PRESENT". Previously aliased to the old ochre-brown
    --accent-primary (#7A4E12); now reuses the same --accent-soft
    blue already used for link hover/focus/visited, so there's one
    blue token doing this job, not two. The old --accent-primary/
    --accent-hover ochre pair and the unused --accent alias were
    removed outright — nothing referenced them once --text-muted was
    retargeted (verified via project-wide search).
  */
  --text-muted: var(--accent-soft);

  /*
    --text-muted-strong used to be a darkened ochre for body copy
    (resume bullets, descriptions, muted lists). Per the "no
    yellow/gold/ochre in body text" rule, it's now aliased straight
    to --text-main (dark charcoal purple) instead of its own color.
  */
  --text-muted-strong: var(--text-main);

  /*
    Legacy tokens below are aliased to the palette above so every
    existing selector in this file re-themes consistently instead of
    leaving two clashing palettes in place. New rules should prefer
    the named tokens above directly.
  */
  --color-paper: var(--bg);
  --color-paper-deep: var(--bg-alt);
  --color-ink: var(--text-main);
  --color-muted: var(--text-muted);
  --color-line: rgba(13, 13, 13, 0.22);
  --color-line-light: rgba(255, 255, 255, 0.28);
  --color-white: #ffffff;
  --color-overlay: rgba(0, 0, 0, 0.52);

  /*
    Original pre-typography-redesign font (single font, inherited
    everywhere via html { font-family: var(--font-sans) }) — kept
    here, unused, as the fastest possible full revert path:

    --font-sans:
      "Helvetica Neue",
      Helvetica,
      Arial,
      system-ui,
      -apple-system,
      sans-serif;

    First typography redesign pass (superseded by the Gaya
    Italic / Serial A / DM Mono system below — kept here, unused,
    in case that intermediate system is ever wanted back):

    --font-expressive: "Bricolage Grotesque", Arial, Helvetica, sans-serif;
    --font-body: "Inter", Arial, Helvetica, sans-serif;
    --font-technical: "Inter", Arial, Helvetica, sans-serif;
  */
  --font-sans:
    "Helvetica Neue",
    Helvetica,
    Arial,
    system-ui,
    -apple-system,
    sans-serif;

  /*
    Final three-role typography system. Gaya and Serial A are both
    local/self-hosted (see @font-face above, italic-only for Gaya);
    DM Mono loads via a Google Fonts <link> in index.html <head>.
    Each has its own system fallback chain, so the site never
    depends on a font loading successfully for legibility.
  */
  --font-display: "Gaya Trial", Georgia, "Times New Roman", serif;
  --font-editorial: "Serial A Trial", Georgia, "Times New Roman", serif;
  --font-functional: "DM Mono", "Courier New", monospace;
  --font-body: "DM Mono", "Courier New", monospace;
  --font-technical: "DM Mono", "Courier New", monospace;

  --ease-quick-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-cubic-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-cubic-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
  --ease-power-2: cubic-bezier(0.8, 0, 0.2, 1);
  --ease-power-4: cubic-bezier(0.76, 0, 0.24, 1);
  --ease-editorial: cubic-bezier(0.75, 0.25, 0.25, 0.75);

  --duration-fast: 220ms;
  --duration-medium: 520ms;
  --duration-long: 900ms;

  --header-height: 76px;

  --page-gutter:
    clamp(
      20px,
      2.1vw,
      42px
    );

  --grid-gutter:
    clamp(
      12px,
      1.3vw,
      26px
    );

  --section-spacing:
    clamp(
      80px,
      11vw,
      180px
    );

  --content-max-width: 1920px;

  --z-header: 100;
  --z-menu-backdrop: 190;
  --z-menu: 200;
  --z-dialog: 300;
}


/* ============================================================
   02. GLOBAL RESET
   ============================================================ */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  min-width: 320px;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  scrollbar-width: none;
  scroll-behavior: smooth;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

html::-webkit-scrollbar {
  display: none;
}

body {
  min-height: 100%;
  margin: 0;
  overflow-x: hidden;
  background: var(--color-paper);
}

body.menu-open,
body.dialog-open,
body.home-locked {
  overflow: hidden;
}

button,
input,
textarea,
select {
  font: inherit;
}

button {
  padding: 0;
  border: 0;
  color: inherit;
  background: none;
}

button:not(:disabled),
a {
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

p,
h1,
h2,
h3,
h4,
h5,
h6,
ol,
ul,
figure,
blockquote {
  margin: 0;
}

ol,
ul {
  padding: 0;
  list-style: none;
}

dialog {
  padding: 0;
  border: 0;
}

[hidden] {
  display: none !important;
}

::selection {
  color: var(--color-paper);
  background: var(--color-ink);
}

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 5px;
}


/* ============================================================
   03. ACCESSIBILITY UTILITIES
   ============================================================ */

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  white-space: nowrap !important;
  border: 0 !important;
  clip: rect(0 0 0 0) !important;
  clip-path: inset(50%) !important;
}

.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 1000;
  padding: 12px 16px;
  color: var(--color-paper);
  background: var(--color-ink);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-quick-out);
}

.skip-link:focus {
  transform: translateY(0);
}

.noscript-message {
  position: fixed;
  inset: auto 20px 20px 20px;
  z-index: 999;
  padding: 20px;
  color: var(--color-white);
  background: var(--color-ink);
}


/* ============================================================
   04. SHARED CONTAINERS + TYPOGRAPHY
   ============================================================ */

.page-container {
  width: min(
    calc(100% - (var(--page-gutter) * 2)),
    var(--content-max-width)
  );
  margin-inline: auto;
}

.section-eyebrow {
  font-size:
    clamp(
      10px,
      0.7vw,
      12px
    );
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.display-heading {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-synthesis: none;
  line-height: 0.87;
  letter-spacing: -0.065em;
  overflow-wrap: anywhere;
  text-transform: uppercase;
}

/*
  color: the main page-title color for Broadcast Media
  (#broadcast-view-title), About Me (#about-view-title), and the
  Design Projects Project Index heading (#project-index-title) —
  the only three headings using this class.
*/
.display-heading--large {
  max-width: 12ch;
  color: var(--accent-bright);
  font-size:
    clamp(
      64px,
      11vw,
      190px
    );
}

/*
  Utility for small paragraph metadata and body text blocks (bullet
  points, resume timelines, muted lists) — swaps the label-weight
  --text-muted (blue) for the higher-contrast --text-muted-strong so
  actual reading copy stays legible on the Lavender Mist canvas.
*/
.text-fine {
  color: var(--text-muted-strong);
}

.animated-underline {
  position: relative;
  display: inline-block;
}

.animated-underline::before,
.animated-underline::after {
  position: absolute;
  right: 0;
  bottom: -0.2em;
  left: 0;
  height: 1px;
  content: "";
  background: currentColor;
  transition:
    transform 500ms var(--ease-editorial);
}

.animated-underline::before {
  transform: scaleX(1);
  transform-origin: right center;
}

.animated-underline::after {
  transform: scaleX(0);
  transform-origin: left center;
}

@media (hover: hover) {
  .animated-underline:hover::before {
    transform: scaleX(0);
  }

  .animated-underline:hover::after {
    transform: scaleX(1);
    transition-delay: 100ms;
  }
}

/*
  Root cause of "links turn blue": the global `a { color: inherit; }`
  rule (element-selector specificity) is weaker than the browser's
  own default `a:visited` rule (pseudo-class specificity), so any
  link that has no other author color rule of its own — the menu
  email link and the About Me contact links, which only carry
  .animated-underline and set no color — fell back to the browser's
  arbitrary default visited color once actually clicked in real
  browsing history, even at rest (not hovered). .resume-sidebar__name
  is unaffected (it already has its own explicit :visited override)
  and is intentionally left on dark text, not blue, per its existing
  design.

  Fix: pin :visited back to the same dark-ink resting color as an
  unvisited link, so nothing is ever blue at rest — then apply the
  intentional accent-soft blue only on :hover/:focus-visible. The
  :visited rule is deliberately declared BEFORE the hover/focus rule
  below: both have equal specificity, so on a link that is both
  visited and hovered, the later rule (hover/focus, blue) correctly
  wins over the earlier one (visited, dark ink) by source order.

  Scoped to `a.animated-underline` only, not the shared class's
  <button> uses (VIEW PROJECT INDEX, RETURN TO INDEX), so this never
  recolors non-link controls. #2F4F8F on the lavender surfaces these
  links sit on measures ~4.52:1 — a pass at 4.5:1 normal text.
*/
a.animated-underline:visited {
  color: var(--color-ink);
}

a.animated-underline:hover,
a.animated-underline:focus-visible {
  color: var(--accent-soft);
}


/* ============================================================
   05. FIXED HEADER
   ============================================================ */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--header-height);
  color: var(--text-main);
  background: rgba(236, 194, 219, 0.8);
  pointer-events: none;
  transition:
    color 700ms var(--ease-editorial);
}

.site-header[data-header-theme="light"] {
  color: var(--color-white);
}

.site-header__inner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  width: 100%;
  height: 100%;
  padding:
    22px
    var(--page-gutter)
    0;
}

.brand-button,
.menu-trigger {
  pointer-events: auto;
}

.brand-button {
  display: grid;
  justify-items: start;
  color: inherit;
  text-align: left;
}

.brand-button__name {
  font-size:
    clamp(
      11px,
      0.9vw,
      14px
    );
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.brand-button__descriptor {
  margin-top: 6px;
  font-size:
    clamp(
      8px,
      0.58vw,
      10px
    );
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.12em;
  opacity: 0.72;
  text-transform: uppercase;
}

.menu-trigger {
  position: relative;
  color: inherit;
  font-size:
    clamp(
      11px,
      0.9vw,
      14px
    );
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.menu-trigger::after {
  position: absolute;
  right: 0;
  bottom: -6px;
  left: 0;
  height: 1px;
  content: "";
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 400ms var(--ease-editorial);
}

@media (hover: hover) {
  .menu-trigger:hover::after {
    transform: scaleX(1);
  }
}


/* ============================================================
   06. MENU OVERLAY + VERTICAL DRAWER
   ============================================================ */

.menu-shell {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu-backdrop);
  visibility: hidden;
  pointer-events: none;
  transition:
    visibility 0s linear var(--duration-long);
}

.menu-shell.is-open {
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

.menu-backdrop {
  position: absolute;
  inset: 0;
  z-index: var(--z-menu-backdrop);
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.52);
  opacity: 0;
  transition:
    opacity
    var(--duration-medium)
    var(--ease-power-2);
}

.menu-shell.is-open .menu-backdrop {
  opacity: 1;
}

.menu-drawer {
  position: absolute;
  inset: 0 0 0 auto;
  z-index: var(--z-menu);
  width: min(720px, 72vw);
  height: 100%;
  overflow-y: auto;
  color: var(--color-ink);
  background: var(--color-paper);
  transform: translate3d(100%, 0, 0);
  transition:
    transform
    680ms
    var(--ease-power-2);
}

.menu-shell.is-open .menu-drawer {
  transform: translate3d(0, 0, 0);
}

.menu-drawer__inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding:
    calc(var(--header-height) + 38px)
    var(--page-gutter)
    32px;
}

.menu-drawer__eyebrow {
  margin-bottom:
    clamp(
      70px,
      12vh,
      140px
    );
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.menu-navigation__list {
  display: grid;
}

.menu-navigation__item {
  overflow: hidden;
  border-top: 1px solid var(--color-line);
}

.menu-navigation__item:last-child {
  border-bottom: 1px solid var(--color-line);
}

.menu-navigation__link {
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr);
  align-items: end;
  width: 100%;
  /*
    Horizontal padding is present in every state (not just when the
    dark active fill appears), so the row's box size never changes
    between unselected/hover/active/focus — only the background
    color toggles, with no layout shift.
  */
  padding:
    clamp(
      18px,
      2.2vw,
      34px
    )
    16px;
  /* Unselected tab: existing dark-purple text token, not the accent. */
  color: var(--text-main);
  background: transparent;
  text-align: left;
  transform: translate3d(0, 115%, 0);
  transition:
    color 320ms var(--ease-cubic-out),
    background 320ms var(--ease-cubic-out),
    transform 680ms var(--ease-power-2);
}

.menu-shell.is-open .menu-navigation__link {
  transform: translate3d(0, 0, 0);
}

.menu-shell.is-open
  .menu-navigation__item:nth-child(1)
  .menu-navigation__link {
  transition-delay: 80ms;
}

.menu-shell.is-open
  .menu-navigation__item:nth-child(2)
  .menu-navigation__link {
  transition-delay: 130ms;
}

.menu-shell.is-open
  .menu-navigation__item:nth-child(3)
  .menu-navigation__link {
  transition-delay: 180ms;
}

.menu-shell.is-open
  .menu-navigation__item:nth-child(4)
  .menu-navigation__link {
  transition-delay: 230ms;
}

/*
  Active/hover/focus state: solid dark-ink fill behind the whole row
  (not just the letters) so the hot-pink text/index never sits
  directly on the lavender drawer background. The large label uses
  --accent-bright (~4.12:1, a pass at the 3:1 large-text threshold);
  the small index number below overrides to --accent-bright-readable
  (~5.08:1, a pass at 4.5:1) since 10px text doesn't qualify as large.
*/
.menu-navigation__link.is-active,
.menu-navigation__link:hover,
.menu-navigation__link:focus-visible {
  color: var(--accent-bright);
  background: var(--color-ink);
}

/*
  The global :focus-visible rule outlines in currentColor, which
  would be bright yellow here — yellow against the lavender area
  just outside this row fails contrast the same way the plain text
  did. Pinning the outline to dark ink keeps the focus ring legible
  against the drawer background regardless of the row's own fill.
*/
.menu-navigation__link:focus-visible {
  outline-color: var(--color-ink);
}

/*
  Small index label ("01"/"02"/...) — no color of its own by
  default, so it inherits the parent link's dark-purple text color
  and stays unselected-colored until the row is active/hover/focus.
*/
.menu-navigation__index {
  align-self: start;
  padding-top: 0.55em;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

/*
  Active/hover/focus override: the parent link switches to
  --accent-bright (~4.12:1 on dark ink), which is fine for its own
  large text but fails 4.5:1 at this label's 10px size — so the
  index number specifically uses --accent-bright-readable instead
  (~5.08:1, a pass).
*/
.menu-navigation__link.is-active .menu-navigation__index,
.menu-navigation__link:hover .menu-navigation__index,
.menu-navigation__link:focus-visible .menu-navigation__index {
  color: var(--accent-bright-readable);
}

.menu-navigation__text {
  font-family: var(--font-display);
  font-style: italic;
  font-size:
    clamp(
      34px,
      4.7vw,
      78px
    );
  font-weight: 400;
  font-synthesis: none;
  line-height: 0.9;
  letter-spacing: -0.055em;
  overflow-wrap: anywhere;
  text-transform: uppercase;
}

.menu-drawer__footer {
  display: flex;
  justify-content: space-between;
  gap: 30px;
  margin-top: auto;
  padding-top:
    clamp(
      60px,
      10vh,
      120px
    );
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}


/* ============================================================
   07. APPLICATION VIEW TRANSITIONS
   ============================================================ */

.app-view {
  min-height: 100vh;
  opacity: 0;
}

.app-view.is-active {
  animation:
    view-enter
    640ms
    var(--ease-cubic-out)
    both;
}

@keyframes view-enter {
  from {
    opacity: 0;
    transform: translate3d(0, 18px, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}


/* ============================================================
   08. DESIGN PROJECTS HERO
   ============================================================

   One cinematic hero for the whole Design Projects view (not one
   per category). Bottom-anchored content over a solid dark field,
   matching the page-intro pattern used by Broadcast/Resume/About
   but full-height and with the larger hero type scale.
   ============================================================ */

.design-hero {
  position: relative;
  display: grid;
  align-content: end;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  padding-top:
    calc(var(--header-height) + 28px);
  padding-bottom:
    clamp(
      24px,
      3vw,
      48px
    );
  color: var(--color-white);
  background: var(--color-ink);
  isolation: isolate;
}

.design-hero__background {
  position: absolute;
  inset: 0;
  z-index: -2;
  cursor: default;
}

/*
  Every slide is stacked on top of the others (position: absolute,
  inset: 0) and crossfades via opacity — .is-active is toggled by
  the carousel controller in the module script. A single-image hero
  just renders one <img>, already .is-active, with no JS wiring.
*/
.design-hero__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 600ms var(--ease-cubic-out);
}

.design-hero__image.is-active {
  opacity: 1;
}

.design-hero__overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.3) 0%,
      rgba(0, 0, 0, 0.08) 34%,
      rgba(0, 0, 0, 0.14) 58%,
      rgba(0, 0, 0, 0.45) 100%
    );
}

.design-hero__content {
  position: relative;
  z-index: 2;
  display: grid;
  gap:
    clamp(
      28px,
      4vw,
      56px
    );
}

.design-hero__title {
  margin-left: -0.03em;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(72px, 10vw, 180px);
  font-weight: 400;
  font-synthesis: none;
  line-height: 0.84;
  letter-spacing: -0.045em;
  overflow-wrap: anywhere;
  text-transform: uppercase;
  text-wrap: balance;
}

/*
  Resume reuses .design-hero__title only for its type scale, not the
  full hero component — this targets the Resume heading by ID
  specifically so Design Projects' own "DESIGN PROJECTS" title
  (which also uses .design-hero__title) stays unaffected/unchanged.
*/
#resume-view-title {
  color: var(--accent-bright);
}

.design-hero__footer {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 40px;
}

.design-hero__metadata {
  display: flex;
  gap:
    clamp(
      34px,
      5vw,
      90px
    );
}

.metadata-block {
  display: grid;
  gap: 9px;
}

.metadata-block__label {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.14em;
  opacity: 0.72;
  text-transform: uppercase;
}

.metadata-block__value {
  font-size:
    clamp(
      14px,
      1.25vw,
      21px
    );
  font-weight: 500;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.design-hero__scroll-button {
  font-size:
    clamp(
      10px,
      0.75vw,
      12px
    );
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}


/* ============================================================
   09. PROJECT DOSSIERS
   ============================================================

   Every design project renders sequentially as its own dossier:
   a cream intro block (title/subtitle/meta/description) followed
   immediately by that project's own asymmetrical media grid. No
   category grouping, no repeated category heading per dossier.
   ============================================================ */

.project-dossier {
  position: relative;
  padding:
    var(--section-spacing)
    0;
  color: var(--color-ink);
  background: var(--color-paper);
}

.project-dossier:nth-of-type(even) {
  background: var(--color-paper-deep);
}

.project-dossier__intro {
  max-width: min(72ch, 100%);
  margin-bottom:
    clamp(
      56px,
      8vw,
      120px
    );
  padding:
    clamp(
      28px,
      4vw,
      48px
    );
  background: var(--bg-card);
}

.project-dossier__number {
  margin-bottom: 18px;
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
}

.project-dossier__title {
  font-family: var(--font-editorial);
  font-size:
    clamp(
      32px,
      4.4vw,
      68px
    );
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.045em;
  text-transform: uppercase;
}

.project-dossier__subtitle {
  margin-top: 14px;
  color: var(--text-main);
  font-size:
    clamp(
      13px,
      1vw,
      16px
    );
  font-weight: 500;
}

.project-dossier__meta {
  margin-top: 10px;
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.project-dossier__description {
  max-width: min(60ch, 100%);
  margin-top: 24px;
  color: var(--text-muted-strong);
  font-size:
    clamp(
      14px,
      1.05vw,
      17px
    );
  line-height: 1.55;
}

.project-grid,
.media-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap:
    clamp(
      58px,
      8vw,
      150px
    )
    var(--grid-gutter);
  align-items: start;
}

.project-card,
.broadcast-card {
  grid-column:
    auto /
    span var(--desktop-span, 4);
  min-width: 0;
  margin-top:
    calc(
      var(--vertical-offset, 0) *
      1vw
    );
}

.project-card__media,
.broadcast-card__media {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: var(--media-ratio, auto);
  overflow: hidden;
  background: var(--bg-card);
}

.project-card__media img,
.broadcast-card__media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition:
    transform
    850ms
    var(--ease-editorial);
}

@media (hover: hover) {
  .project-card:hover .project-card__media img,
  .broadcast-card:hover .broadcast-card__media img {
    transform: scale(1.018);
  }
}

.broadcast-card__information {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  margin-top: 14px;
}

.broadcast-card__index {
  display: block;
  margin-bottom: 7px;
  color: var(--color-muted);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.1em;
}

.broadcast-card__title {
  display: block;
  max-width: 18ch;
  font-family: var(--font-editorial);
  font-size:
    clamp(
      16px,
      1.4vw,
      24px
    );
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: -0.03em;
  text-transform: uppercase;
}

.broadcast-card__meta {
  display: grid;
  flex: 0 0 auto;
  gap: 5px;
  color: var(--color-muted);
  font-size: 9px;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: 0.08em;
  text-align: right;
  text-transform: uppercase;
}

/*
  Design-project cards are now buttons wrapping a media frame, with
  the title revealed as an on-image overlay instead of text below —
  one card per mediaItems entry, not per project.
*/
.project-card__button {
  display: block;
  width: 100%;
  color: inherit;
  text-align: left;
}

.project-card__overlay {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px;
  color: var(--color-white);
  background: linear-gradient(to top, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0));
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease-cubic-out);
}

@media (hover: hover) {
  .project-card:hover .project-card__overlay,
  .project-card__button:focus-visible .project-card__overlay {
    opacity: 1;
  }
}

@media (hover: none) {
  .project-card__overlay {
    opacity: 1;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0));
  }
}

.project-card__overlay-title {
  font-size:
    clamp(
      13px,
      1.1vw,
      18px
    );
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.project-card__overlay-project {
  color: rgba(255, 255, 255, 0.72);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/*
  Optional image-credit/technical-line caption — shared by the
  masonry grid card and the full-screen image dialog
  (createMediaCaptionMarkup). Renders only the lines a mediaItem
  actually has data for; empty when a media item carries none of
  these optional fields, which is true of every current media item.
*/
.media-caption {
  margin-top: 14px;
}

.media-caption__figure-label {
  color: var(--accent-soft);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.media-caption__title {
  margin-top: 4px;
  color: var(--text-main);
  font-family: var(--font-editorial);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.media-caption__technical {
  margin-top: 4px;
  color: var(--accent-soft);
  font-size: 12px;
  font-weight: 500;
}

.media-caption__text {
  margin-top: 6px;
  max-width: min(42ch, 100%);
  color: var(--text-main);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.55;
}

.media-caption__credit {
  margin-top: 4px;
  color: var(--text-muted-strong);
  font-size: 11px;
  font-weight: 400;
}

.project-dossier__closing {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px 40px;
  margin-top:
    clamp(
      56px,
      8vw,
      120px
    );
  padding-top:
    clamp(
      28px,
      4vw,
      40px
    );
  border-top: 1px solid var(--color-line);
}

.project-dossier__closing-label {
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.project-dossier__closing-final {
  color: var(--text-muted-strong);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.project-dossier__closing-index {
  flex: 0 0 auto;
  color: var(--text-main);
  font-family: var(--font-editorial);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}


/* ============================================================
   10. EMPTY STATES
   ============================================================ */

.empty-state {
  grid-column: 1 / -1;
  min-height: 42vh;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 14px;
  border-top: 1px solid var(--color-line);
  border-bottom: 1px solid var(--color-line);
  text-align: center;
}

.empty-state__label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.empty-state__copy {
  max-width: min(52ch, 100%);
  color: var(--text-muted-strong);
  font-size: 14px;
  line-height: 1.5;
}


/* ============================================================
   11. DESIGN PROJECT INDEX
   ============================================================ */

/*
  Project Index is now the first thing in the Design Projects view
  (the name hero moved to its own separate Home view), so its own
  top padding has to clear the fixed header directly — nothing above
  it does that anymore.
*/
.design-index {
  padding:
    calc(var(--header-height) + var(--section-spacing))
    0
    var(--section-spacing);
  color: var(--color-paper);
  background: var(--color-ink);
}

/*
  Belt-and-suspenders for the scrollIntoView()-based paths (RETURN TO
  INDEX from a dossier) on top of the padding-top above (which
  already covers the plain scrollTo(0,0) paths: nav menu, GO TO
  PROJECT INDEX) — scroll-margin-top is honored automatically by
  scrollIntoView, no JS offset math needed.
*/
#project-index {
  scroll-margin-top: var(--header-height);
}

.design-index__header {
  margin-bottom:
    clamp(
      65px,
      9vw,
      140px
    );
}

.design-index__header .section-eyebrow {
  margin-bottom: 22px;
}

.project-index-list {
  border-top: 1px solid var(--color-line-light);
}

.project-index-row {
  display: grid;
  grid-template-columns:
    60px
    minmax(0, 1fr)
    minmax(130px, 0.25fr)
    110px;
  align-items: center;
  width: 100%;
  padding:
    clamp(
      17px,
      2.1vw,
      32px
    )
    0;
  border-bottom: 1px solid var(--color-line-light);
  color: rgba(255, 255, 255, 0.62);
  text-align: left;
  transition:
    color
    var(--duration-fast)
    var(--ease-cubic-out);
}

.project-index-row:hover,
.project-index-row:focus-visible {
  color: var(--color-white);
}

.project-index-row__number,
.project-index-row__typology,
.project-index-row__year {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: color var(--duration-fast) var(--ease-cubic-out);
}

/*
  Active Project Index state — --accent-bright-readable, not the
  large-title --accent-bright. 10px bold on #2A1E2D: --accent-bright
  measures ~4.12:1 (fails the 4.5:1 normal-text threshold this small
  numeral needs); --accent-bright-readable measures ~5.08:1 (passes).
*/
.project-index-row:hover .project-index-row__number,
.project-index-row:focus-visible .project-index-row__number {
  color: var(--accent-bright-readable);
}

.project-index-row__title {
  padding-right: 30px;
  font-family: var(--font-editorial);
  font-size:
    clamp(
      22px,
      3vw,
      52px
    );
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.05em;
  text-transform: uppercase;
}

.project-index-row__year {
  text-align: right;
}


/* ============================================================
   12. SHARED PAGE INTRODUCTIONS
   ============================================================ */

.page-intro {
  min-height:
    clamp(
      520px,
      76vh,
      900px
    );
}

.page-intro--dark {
  color: var(--color-white);
  background: var(--color-ink);
}

.page-intro__inner {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: inherit;
  padding:
    calc(var(--header-height) + 70px)
    0
    clamp(
      55px,
      7vw,
      110px
    );
}

.page-intro__inner .section-eyebrow {
  margin-bottom: 22px;
}

.page-intro__description {
  max-width: min(48ch, 100%);
  margin-top:
    clamp(
      32px,
      4vw,
      60px
    );
  font-size:
    clamp(
      16px,
      1.4vw,
      23px
    );
  line-height: 1.5;
  overflow-wrap: break-word;
}


/* ============================================================
   13. BROADCAST MEDIA GRID
   ============================================================ */

.media-archive {
  padding:
    var(--section-spacing)
    0;
  background: var(--color-paper);
}

.broadcast-card__button {
  display: block;
  width: 100%;
  color: inherit;
  text-align: left;
}

.broadcast-card__media {
  background: var(--bg-card);
}

.broadcast-card__play {
  position: absolute;
  right: 14px;
  bottom: 14px;
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  color: var(--color-white);
  background: rgba(0, 0, 0, 0.76);
  border-radius: 50%;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.1em;
  transition:
    color var(--duration-fast) var(--ease-cubic-out),
    background var(--duration-fast) var(--ease-cubic-out),
    transform var(--duration-fast) var(--ease-cubic-out);
}

@media (hover: hover) {
  .broadcast-card__button:hover .broadcast-card__play {
    color: var(--color-ink);
    background: var(--accent-bright);
    transform: scale(1.08);
  }
}

/*
  Keyboard-focus mirror of the hover state above — intentionally not
  gated by (hover: hover) since focus can land here on any device.
  Dark-ink text on the hot-pink fill measures ~4.12:1 (the stronger
  of the two existing text tokens against this pink; white measures
  ~3.85:1) — passes the 3:1 meaningful-control threshold, falls just
  short of the strict 4.5:1 normal-text threshold at this badge's
  9px label size. Flagged, not altered further per instruction. The
  global :focus-visible outline is untouched, so focus is never
  conveyed by this color change alone.
*/
.broadcast-card__button:focus-visible .broadcast-card__play {
  color: var(--color-ink);
  background: var(--accent-bright);
  transform: scale(1.08);
}

/*
  Flat corner marker for broadcastVideos entries with
  studentEmmyWinner: true. Solid (not translucent) background so its
  three short lines stay legible over any thumbnail photo. Top-right,
  not top-left: the Raider 305 posters already carry a baked-in
  month badge ("MARCH" / "JANUARY") in the top-left corner of the
  image itself, and .broadcast-card__play already owns bottom-right —
  top-right is the only corner free on every participating card.
*/
.broadcast-card__emmy-stamp {
  position: absolute;
  top: 14px;
  right: 14px;
  display: grid;
  gap: 1px;
  padding: 7px 10px;
  color: var(--color-white);
  background: var(--accent-soft);
  font-size: 9px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: 0.09em;
  text-align: right;
  text-transform: uppercase;
}

.broadcast-card__external-link {
  display: inline-block;
  margin-top: 12px;
  color: var(--color-ink);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}


/* ============================================================
   14. VIDEO DIALOG
   ============================================================ */

.video-dialog {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  color: var(--color-white);
  background: transparent;
}

.video-dialog::backdrop {
  background: rgba(0, 0, 0, 0.82);
  backdrop-filter: blur(10px);
}

.video-dialog[open] {
  display: grid;
  place-items: center;
  animation:
    dialog-fade
    320ms
    var(--ease-cubic-out)
    both;
}

@keyframes dialog-fade {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.video-dialog__surface {
  width: min(
    calc(100% - (var(--page-gutter) * 2)),
    1500px
  );
  max-height: calc(100vh - 40px);
  padding: 24px;
  overflow-y: auto;
  color: var(--text-main);
  background: var(--bg-card);
}

.video-dialog__header,
.video-dialog__footer {
  display: flex;
  justify-content: space-between;
  gap: 30px;
}

.video-dialog__header {
  align-items: flex-start;
  padding-bottom: 18px;
}

.video-dialog__eyebrow,
.video-dialog__footer,
.video-dialog__close {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.video-dialog__eyebrow {
  margin-bottom: 8px;
  color: rgba(42, 30, 45, 0.6);
}

.video-dialog__title {
  max-width: 28ch;
  font-family: var(--font-editorial);
  font-size:
    clamp(
      22px,
      2.8vw,
      48px
    );
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.05em;
  text-transform: uppercase;
}

.video-dialog__close {
  color: rgba(42, 30, 45, 0.7);
  transition:
    color
    var(--duration-fast)
    var(--ease-cubic-out);
}

.video-dialog__close:hover,
.video-dialog__close:focus-visible {
  color: var(--text-main);
}

.video-dialog__frame {
  position: relative;
  width: 100%;
  aspect-ratio: var(--video-ratio, 16 / 9);
  overflow: hidden;
  background: #000;
}

.video-dialog__frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.video-dialog__placeholder {
  display: grid;
  place-content: center;
  gap: 12px;
  width: 100%;
  height: 100%;
  padding: 30px;
  color: rgba(42, 30, 45, 0.72);
  text-align: center;
}

.video-dialog__placeholder p:first-child {
  color: var(--text-main);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.1em;
}

.video-dialog__placeholder p:last-child {
  font-size: 13px;
}

.video-dialog__footer {
  padding-top: 16px;
  color: rgba(42, 30, 45, 0.62);
}

.video-dialog__awards {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--color-line);
}

.video-dialog__awards-label {
  margin-bottom: 14px;
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.video-dialog__awards-list {
  display: grid;
  gap: 10px;
  color: var(--text-muted-strong);
  font-size: 13px;
  line-height: 1.4;
}

.video-dialog__awards-list li {
  position: relative;
  padding-left: 16px;
}

.video-dialog__awards-list li::before {
  position: absolute;
  top: 0.6em;
  left: 0;
  width: 5px;
  height: 1px;
  content: "";
  background: currentColor;
}

/* ============================================================
   14b. IMAGE DIALOG
   ============================================================

   Opened by masonry cards in the design-project grid. Same
   show/close/backdrop mechanics as the video dialog, but lighter —
   no iframe, no aspect-locked frame, just an enlarged image.
   ============================================================ */

.image-dialog {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  color: var(--text-main);
  background: transparent;
}

.image-dialog::backdrop {
  background: rgba(0, 0, 0, 0.82);
  backdrop-filter: blur(10px);
}

.image-dialog[open] {
  display: grid;
  place-items: center;
  animation:
    dialog-fade
    320ms
    var(--ease-cubic-out)
    both;
}

.image-dialog__surface {
  width: min(
    calc(100% - (var(--page-gutter) * 2)),
    1200px
  );
  max-height: calc(100vh - 40px);
  padding: 24px;
  overflow-y: auto;
  color: var(--text-main);
  background: var(--bg-card);
}

.image-dialog__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 30px;
  padding-bottom: 18px;
}

.image-dialog__header-controls {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 20px;
}

.image-dialog__eyebrow {
  margin-bottom: 8px;
  color: rgba(42, 30, 45, 0.6);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.image-dialog__title {
  max-width: 28ch;
  font-family: var(--font-editorial);
  font-size:
    clamp(
      22px,
      2.8vw,
      48px
    );
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.05em;
  text-transform: uppercase;
}

.image-dialog__close {
  color: rgba(42, 30, 45, 0.7);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition:
    color
    var(--duration-fast)
    var(--ease-cubic-out);
}

.image-dialog__close:hover,
.image-dialog__close:focus-visible {
  color: var(--text-main);
}

.image-dialog__zoom {
  color: rgba(42, 30, 45, 0.7);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition:
    color
    var(--duration-fast)
    var(--ease-cubic-out);
}

.image-dialog__zoom:hover,
.image-dialog__zoom:focus-visible,
.image-dialog__zoom[aria-pressed="true"] {
  color: var(--text-main);
}

.image-dialog__frame {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--bg-alt);
}

.image-dialog__frame img {
  width: 100%;
  height: auto;
  max-height: 74vh;
  object-fit: contain;
  touch-action: none;
  transform-origin: center;
  cursor: zoom-in;
}

.image-dialog__frame img.is-zoomed {
  cursor: zoom-out;
}

.image-dialog__nav {
  position: absolute;
  top: 50%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  color: var(--text-main);
  background: rgba(253, 251, 247, 0.86);
  border-radius: 50%;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.08em;
  transform: translateY(-50%);
  transition:
    background
    var(--duration-fast)
    var(--ease-cubic-out);
}

.image-dialog__nav:hover,
.image-dialog__nav:focus-visible {
  background: var(--color-white);
}

.image-dialog__nav--prev {
  left: 12px;
}

.image-dialog__nav--next {
  right: 12px;
}

.image-dialog__counter {
  margin-top: 14px;
  color: rgba(42, 30, 45, 0.6);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-align: center;
  text-transform: uppercase;
}


/* ============================================================
   14c. PROJECT CHAPTER OPENER
   ============================================================

   Momentary full-viewport card shown only when opening an
   individual Design Project from the Project Index. Not a dialog —
   pointer-events: none throughout so it never blocks the smooth
   scroll happening underneath it. Skipped entirely under reduced
   motion (see the JS guard), so no reduced-motion override is
   needed here.
   ============================================================ */

.chapter-opener {
  position: fixed;
  inset: 0;
  z-index: var(--z-dialog);
  display: grid;
  place-items: center;
  padding: 24px;
  color: var(--color-white);
  text-align: center;
  background: var(--color-ink);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms var(--ease-cubic-out);
}

.chapter-opener.is-visible {
  opacity: 1;
}

/*
  The editorial blue (--accent-soft) fails contrast on dark ink
  (~1.99:1), so this dark-surface label uses --color-paper instead —
  the same lavender-tinted light text already used as the default
  Project Index color on this identical #2A1E2D background
  (~9.02:1, a strong pass at 12px).
*/
.chapter-opener__number {
  color: var(--color-paper);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.chapter-opener__title {
  max-width: 20ch;
  margin-top: 14px;
  color: var(--accent-bright);
  font-family: var(--font-display);
  font-style: italic;
  font-size:
    clamp(
      36px,
      6vw,
      84px
    );
  font-weight: 400;
  font-synthesis: none;
  line-height: 0.95;
  letter-spacing: -0.04em;
  overflow-wrap: anywhere;
  text-transform: uppercase;
}

/*
  The editorial blue (--accent-soft) fails contrast on dark ink
  (~1.99:1), so this dark-surface label uses --color-paper instead —
  the same lavender-tinted light text already used as the default
  Project Index color on this identical #2A1E2D background
  (~9.02:1, a strong pass at 11px).
*/
.chapter-opener__meta {
  margin-top: 16px;
  color: var(--color-paper);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}


/* ============================================================
   15. RESUME VIEW
   ============================================================ */

.resume-layout {
  padding:
    0
    0
    var(--section-spacing);
  background: var(--color-paper);
}

.resume-layout__grid {
  display: grid;
  grid-template-columns:
    repeat(12, minmax(0, 1fr));
  gap: var(--grid-gutter);
  border-top: 1px solid var(--color-line);
}

.resume-sidebar {
  grid-column: 1 / span 4;
  padding:
    clamp(
      34px,
      4vw,
      70px
    )
    0;
}

.resume-sidebar__identity {
  padding-right:
    clamp(
      20px,
      3vw,
      52px
    );
}

/*
  Now an <a> (links to LinkedIn) instead of a <p> — display:block
  restores the layout an inline anchor wouldn't have on its own.
  No underline in any state; the global :focus-visible outline rule
  already provides a non-underline keyboard focus indicator.
*/
.resume-sidebar__name {
  display: block;
  color: var(--text-main);
  font-size:
    clamp(
      22px,
      2.5vw,
      40px
    );
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  text-decoration: none;
}

.resume-sidebar__name:hover,
.resume-sidebar__name:focus,
.resume-sidebar__name:visited {
  color: var(--text-main);
  text-decoration: none;
}

.resume-sidebar__summary {
  max-width: min(38ch, 100%);
  margin-top:
    clamp(
      22px,
      3vw,
      34px
    );
  font-size:
    clamp(
      14px,
      1vw,
      17px
    );
  line-height: 1.5;
}

.resume-sidebar-section {
  margin-top:
    clamp(
      46px,
      6vw,
      82px
    );
}

/*
  Sidebar list labels (SOFTWARE/SKILLS/LANGUAGES) stay on Inter —
  small utility labels parallel to the list content beneath them,
  not editorial section headings like .resume-section__title below.
*/
.resume-sidebar-section__title {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.resume-section__title {
  font-family: var(--font-editorial);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.resume-sidebar-section__group {
  margin-top: 18px;
}

.resume-sidebar-section__group:first-of-type {
  margin-top: 0;
}

.resume-sidebar-section__group-title {
  margin-top: 18px;
  color: var(--text-main);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.resume-sidebar-section__list {
  margin-top: 18px;
  /*
    Software/Skills/Languages are body-list content, not decorative
    metadata — kept on --text-main (dark charcoal) rather than the
    accent color per the "no ochre in body text" rule.
  */
  color: var(--text-main);
  font-size: 13px;
  line-height: 1.25;
  columns: 2;
  column-gap: 20px;
}

.resume-sidebar-section__list li {
  break-inside: avoid;
  margin-bottom: 9px;
}

.resume-sidebar-section__group-title + .resume-sidebar-section__list {
  margin-top: 12px;
}

.resume-main {
  grid-column: 5 / -1;
  border-left: 1px solid var(--color-line);
}

.resume-section {
  display: grid;
  grid-template-columns:
    minmax(120px, 2fr)
    minmax(0, 7fr);
  gap: var(--grid-gutter);
  padding:
    clamp(
      34px,
      4vw,
      70px
    )
    0
    clamp(
      50px,
      7vw,
      100px
    )
    var(--grid-gutter);
  border-bottom: 1px solid var(--color-line);
}

.resume-section__entries {
  display: grid;
}

.resume-entry {
  display: grid;
  grid-template-columns:
    minmax(90px, 0.25fr)
    minmax(0, 1fr);
  gap: var(--grid-gutter);
  padding:
    0
    0
    clamp(
      38px,
      5vw,
      72px
    );
}

.resume-entry:last-child {
  padding-bottom: 0;
}

.resume-entry__date {
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.resume-entry__role {
  max-width: 26ch;
  font-family: var(--font-editorial);
  font-size:
    clamp(
      20px,
      2.1vw,
      34px
    );
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.05em;
  text-transform: uppercase;
}

.resume-entry__subtitle {
  margin-top: 9px;
  color: var(--text-main);
  font-size:
    clamp(
      13px,
      1vw,
      16px
    );
  font-weight: 500;
}

/*
  Location subtitle — editorial blue token, sits directly beneath
  the role/program subtitle. 12px on lavender measures ~4.52:1,
  a pass at the 4.5:1 normal-text threshold.
*/
.resume-entry__location {
  margin-top: 4px;
  color: var(--accent-soft);
  font-size: 12px;
}

.resume-entry__bullets {
  display: grid;
  gap: 10px;
  max-width: min(66ch, 100%);
  margin-top: 20px;
  color: var(--text-muted-strong);
  font-size:
    clamp(
      13px,
      0.95vw,
      15px
    );
  line-height: 1.5;
}

.resume-entry__bullets li {
  position: relative;
  padding-left: 16px;
}

.resume-entry__bullets li::before {
  position: absolute;
  top: 0.67em;
  left: 0;
  width: 5px;
  height: 1px;
  content: "";
  background: currentColor;
}

/*
  Compact sections (Selected Awards, Honor Society Memberships,
  Clubs and Affiliations) drop the date/role/bullets entry layout
  in favor of a single-column heading + flat list — no dates to
  align, so the two-column .resume-section grid isn't used here.
*/
.resume-section--compact {
  display: block;
}

.resume-section--compact .resume-section__header {
  margin-bottom:
    clamp(
      20px,
      2.5vw,
      32px
    );
}

.resume-compact-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 24px;
  /* Honor Societies / Clubs are body-list content — same reasoning
     as .resume-sidebar-section__list above: --text-main, not accent. */
  color: var(--text-main);
  font-size: 13px;
  line-height: 1.3;
}

.resume-award-group {
  margin-top:
    clamp(
      28px,
      3.5vw,
      44px
    );
}

.resume-award-group:first-child {
  margin-top: 0;
}

.resume-award-group__title {
  margin-bottom: 14px;
  color: var(--text-main);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.03em;
}

.resume-award-group__list {
  display: grid;
  gap: 10px;
  max-width: min(66ch, 100%);
  color: var(--text-muted-strong);
  font-size:
    clamp(
      13px,
      0.95vw,
      15px
    );
  line-height: 1.5;
}

.resume-award-group__list li {
  position: relative;
  padding-left: 16px;
}

.resume-award-group__list li::before {
  position: absolute;
  top: 0.6em;
  left: 0;
  width: 5px;
  height: 1px;
  content: "";
  background: currentColor;
}


/* ============================================================
   16. ABOUT VIEW
   ============================================================ */

.about-layout {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr)
    minmax(0, 1fr);
  min-height: 100vh;
  background: var(--color-paper);
}

.about-layout__media {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  overflow: hidden;
  background: var(--color-paper-deep);
}

.about-layout__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.about-layout__content {
  min-width: 0;
}

.about-layout__content-inner {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  /*
    Top/bottom padding is symmetric now that the eyebrow/title live
    in their own .page-intro header above .about-layout — this
    section no longer sits directly under the fixed site-header, so
    it no longer needs header-height clearance of its own.
  */
  padding:
    var(--section-spacing)
    var(--page-gutter);
}

.about-copy {
  margin-top:
    clamp(
      50px,
      7vw,
      100px
    );
}

.about-copy__body {
  display: grid;
  gap: 26px;
}

.about-copy__paragraph {
  max-width: min(54ch, 100%);
  font-size:
    clamp(
      17px,
      1.6vw,
      27px
    );
  line-height: 1.5;
  letter-spacing: -0.018em;
  overflow-wrap: break-word;
}

.about-copy__paragraph:first-child {
  font-size:
    clamp(
      24px,
      2.6vw,
      44px
    );
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.04em;
}

/*
  Single column now that Disciplines is gone and only Contact
  remains — was a 2-column grid to hold both sections side by side.
*/
.about-copy__details {
  max-width: 32ch;
  margin-top:
    clamp(
      70px,
      10vw,
      130px
    );
  padding-top: 24px;
  border-top: 1px solid var(--color-line);
}

.about-detail__title {
  margin-bottom: 18px;
  font-family: var(--font-editorial);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.about-detail__list {
  display: grid;
  gap: 9px;
  color: var(--text-muted-strong);
  font-size: 13px;
  line-height: 1.3;
}

/*
  Personal colophon — an imprint-style credit block, deliberately
  separate from .about-copy__details (Contact) above it: no social
  links, no duplicated email/phone, just who built the site and
  what it's built with. Compact and understated by design — this is
  not another resume section.
*/
.about-colophon {
  padding:
    clamp(60px, 8vw, 100px)
    var(--page-gutter)
    clamp(48px, 6vw, 80px);
  border-top: 1px solid var(--color-line);
  background: var(--color-paper);
}

.about-colophon__inner {
  max-width: min(46ch, 100%);
}

/*
  10px on lavender measures ~4.52:1, a pass at the 4.5:1
  normal-text threshold.
*/
.about-colophon__label {
  color: var(--accent-soft);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.about-colophon__name {
  margin-top: 8px;
  color: var(--text-main);
  font-size:
    clamp(
      15px,
      1.3vw,
      18px
    );
  font-weight: 500;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

.about-colophon__tech {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 22px;
  color: var(--text-muted-strong);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.about-colophon__updated {
  margin-top: 28px;
}

.about-colophon__updated .about-colophon__label {
  margin-bottom: 6px;
}

.about-colophon__value {
  color: var(--text-main);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
}


/* ============================================================
   17. LARGE TABLET
   ============================================================ */

@media (max-width: 1100px) {
  .menu-drawer {
    width: min(760px, 82vw);
  }

  .project-grid,
  .media-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .project-card,
  .broadcast-card {
    grid-column:
      auto /
      span var(--tablet-span, 3);
  }

  .resume-sidebar {
    grid-column: 1 / span 4;
  }

  .resume-main {
    grid-column: 5 / -1;
  }

  .resume-section {
    grid-template-columns: 1fr;
  }

  .resume-entry {
    grid-template-columns:
      110px
      minmax(0, 1fr);
  }
}


/* ============================================================
   18. MOBILE LANDSCAPE / TABLET
   ============================================================ */

@media (max-width: 767px) {
  :root {
    --header-height: 64px;
  }

  .site-header__inner {
    padding-top: 18px;
  }

  .brand-button__descriptor {
    display: none;
  }

  .menu-drawer {
    width: 100%;
  }

  .menu-drawer__inner {
    padding-top:
      calc(var(--header-height) + 42px);
  }

  .menu-navigation__link {
    grid-template-columns: 38px minmax(0, 1fr);
  }

  .menu-navigation__text {
    font-size:
      clamp(
        34px,
        10vw,
        58px
      );
  }

  .menu-drawer__footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }

  .design-hero {
    padding-top:
      calc(var(--header-height) + 24px);
  }

  .design-hero__footer {
    align-items: flex-end;
  }

  .design-hero__metadata {
    flex-direction: column;
    gap: 20px;
  }

  .project-dossier__intro {
    padding:
      clamp(
        20px,
        6vw,
        32px
      );
  }

  .project-grid,
  .media-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap:
      clamp(
        48px,
        15vw,
        90px
      );
  }

  .project-card,
  .broadcast-card {
    grid-column:
      auto /
      span var(--mobile-span, 2);
    margin-top: 0;
  }

  .broadcast-card__information {
    gap: 14px;
  }

  .project-index-row {
    grid-template-columns:
      44px
      minmax(0, 1fr)
      78px;
  }

  .project-index-row__typology {
    display: none;
  }

  .page-intro {
    min-height: 72vh;
  }

  .broadcast-card__play {
    width: 54px;
    height: 54px;
  }

  .resume-layout__grid {
    display: block;
  }

  .resume-sidebar {
    padding:
      clamp(
        34px,
        9vw,
        58px
      )
      0;
    border-bottom: 1px solid var(--color-line);
  }

  .resume-main {
    border-left: 0;
  }

  .resume-section {
    display: block;
    padding:
      clamp(
        34px,
        9vw,
        58px
      )
      0;
  }

  .resume-section__header {
    margin-bottom: 42px;
  }

  .resume-entry {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .resume-section--compact {
    padding:
      clamp(
        34px,
        9vw,
        58px
      )
      0;
  }

  .resume-compact-list {
    grid-template-columns: 1fr;
  }

  .resume-sidebar-section__list {
    columns: 1;
  }

  .about-layout {
    display: block;
  }

  .about-layout__media {
    position: relative;
    height: 72vh;
  }

  .about-layout__content-inner {
    min-height: auto;
  }
}


/* ============================================================
   19. SMALL MOBILE
   ============================================================ */

@media (max-width: 479px) {
  /*
    QA fix: at the 64px floor, "BROADCAST" (and other 9+ character
    titles using this class) overflowed the viewport on narrow
    phones — no override existed below 480px. Mirrors the same fix
    already in place for .design-hero__title.
  */
  .display-heading--large {
    font-size: clamp(40px, 15vw, 64px);
  }

  .design-hero__title {
    font-size: clamp(48px, 15vw, 72px);
    line-height: 0.9;
  }

  .design-hero__footer {
    display: grid;
    gap: 26px;
  }

  .design-hero__scroll-button {
    justify-self: start;
  }

  .broadcast-card__information {
    display: grid;
  }

  .broadcast-card__meta {
    justify-items: start;
    text-align: left;
  }

  .project-index-row {
    grid-template-columns:
      34px
      minmax(0, 1fr);
  }

  .project-index-row__year {
    display: none;
  }

  .video-dialog__surface {
    width: calc(100% - 24px);
  }

  .video-dialog__header {
    gap: 14px;
  }

  .video-dialog__footer {
    flex-direction: column;
    gap: 6px;
  }

  .project-dossier__closing {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
}


/* ============================================================
   20. CONTEXTUAL CURSOR
   ============================================================

   A limited image-inspection affordance, not a sitewide navigation
   system: this pill only appears over elements carrying
   [data-cursor-label] — currently just Design Project media cards,
   labeled OPEN. Every other card, row, and button on the site keeps
   the plain native cursor. `cursor: none` on labeled elements is
   scoped to html.cursor-fx-ready — a class the controller script
   only adds once it has successfully initialized — so a JS failure
   never leaves the native cursor suppressed.
   ============================================================ */

.custom-cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 400;
  pointer-events: none;
  transform: translate3d(-100px, -100px, 0);
}

.custom-cursor__pill {
  display: block;
  padding: 0;
  transform: translate(-50%, -50%) scale(0.6);
  color: var(--color-ink);
  background: var(--accent-bright);
  border-radius: 999px;
  opacity: 0;
  transition:
    opacity var(--duration-fast) var(--ease-cubic-out),
    transform var(--duration-fast) var(--ease-cubic-out),
    padding var(--duration-fast) var(--ease-cubic-out);
  white-space: nowrap;
}

.custom-cursor__pill.is-visible {
  padding: 8px 14px;
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}

.custom-cursor__label {
  font-family: var(--font-functional);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/*
  Only devices that report an accurate, hover-capable pointer ever
  get `cursor: none` on a labeled element — everything else (touch,
  coarse pointers) keeps its native pointer at all times, and the
  pill itself is display:none there as a second safeguard.
*/
@media (hover: none), (pointer: coarse) {
  .custom-cursor {
    display: none;
  }
}

html.cursor-fx-ready [data-cursor-label] {
  cursor: none;
}


/* ============================================================
   21. REDUCED MOTION
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }

}


/* ============================================================
   22. PRINT
   ============================================================ */

@media print {
  .site-header,
  .menu-shell,
  .video-dialog,
  .app-view:not(.app-view--resume) {
    display: none !important;
  }

  .app-view--resume {
    display: block !important;
    opacity: 1 !important;
  }

  .page-intro {
    min-height: auto;
  }

  .page-intro__inner {
    min-height: auto;
    padding: 30px 0;
  }

  .resume-layout__grid {
    display: block;
  }

  .resume-sidebar,
  .resume-main {
    border: 0;
  }
}
