/* ============================================================
   Components: one BEM block per section of this file.
   Only semantic tokens. Components never know about modes.
   ============================================================ */

@layer components {
  /* icon */
  .icon {
    inline-size: var(--icon-size);
    block-size: var(--icon-size);
    flex-shrink: 0;
  }

  /* button */
  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2xs);
    min-block-size: 3rem;
    padding-inline: var(--space-m);
    font-family: var(--font-body);
    font-size: var(--text-s);
    font-weight: var(--weight-bold);
    line-height: 1;
    text-decoration: none;
    /* Long labels wrap on narrow phones instead of pushing the page wider. */
    max-inline-size: 100%;
    text-align: center;
    border: var(--border-width) solid transparent;
    border-radius: var(--radius-m);
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease-out),
      background-color var(--duration-fast) var(--ease-out),
      translate var(--duration-base) var(--ease-spring);

    @media (hover: hover) {
      &:hover {
        translate: 0 -2px;
      }
    }
  }

  .button--primary {
    color: var(--color-on-invert);
    background-color: var(--color-invert);

    @media (hover: hover) {
      &:hover {
        color: var(--color-on-accent);
        background-color: var(--color-accent);
      }
    }
  }

  .button--outline {
    color: var(--color-text);
    border-color: var(--color-border-strong);

    @media (hover: hover) {
      &:hover {
        color: var(--color-on-invert);
        background-color: var(--color-invert);
      }
    }
  }

  .button--accent {
    color: var(--color-on-accent);
    background-color: var(--color-accent);

    @media (hover: hover) {
      &:hover {
        background-color: var(--color-accent-hover);
      }
    }
  }

  /* Solid light button for coloured panels. */
  .button--light {
    color: var(--color-text);
    background-color: var(--color-surface);

    &:focus-visible {
      outline-color: var(--color-on-panel);
    }

    @media (hover: hover) {
      &:hover {
        color: var(--color-on-accent);
        background-color: var(--color-accent);
      }
    }
  }

  /* Outline button placed on a coloured panel. */
  .button--on-panel {
    color: var(--color-on-panel);
    border-color: var(--color-on-panel);

    &:focus-visible {
      outline-color: var(--color-on-panel);
    }

    @media (hover: hover) {
      &:hover {
        color: var(--color-panel);
        background-color: var(--color-on-panel);
      }
    }
  }

  .button--small {
    min-block-size: var(--target-min);
    padding-inline: var(--space-s);
  }

  /* bubble: speech-bubble label above headings */
  .bubble {
    --bubble-bg: var(--color-invert);
    --bubble-fg: var(--color-on-invert);

    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    inline-size: fit-content;
    padding: var(--space-3xs) var(--space-xs);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    line-height: 1.5;
    color: var(--bubble-fg);
    background-color: var(--bubble-bg);
    border-radius: var(--radius-s);

    &::after {
      content: '';
      position: absolute;
      inset-block-start: calc(100% - 1px);
      inset-inline-start: var(--space-xs);
      inline-size: var(--space-xs);
      block-size: var(--space-2xs);
      background-color: var(--bubble-bg);
      clip-path: polygon(0 0, 100% 0, 0 100%);
    }
  }

  .bubble--on-panel {
    --bubble-bg: var(--color-panel-chip);
    --bubble-fg: var(--color-on-panel-chip);
  }

  /* logo-burst */
  .logo-burst {
    position: relative;
    display: grid;
    place-items: center;
    inline-size: clamp(4rem, 3rem + 4vw, 4.75rem);
    aspect-ratio: 1;
    font-family: var(--font-display);
    font-size: var(--text-m);
    font-weight: var(--weight-heavy);
    letter-spacing: var(--tracking-tight);
    color: var(--color-on-accent);
    text-decoration: none;
    isolation: isolate;
    rotate: calc(var(--tilt-m) * -1);
    transition: rotate var(--duration-slow) var(--ease-spring);

    &::before {
      content: '';
      position: absolute;
      inset: 0;
      z-index: -1;
      background-color: var(--color-accent);
      clip-path: var(--shape-burst);
      transition: background-color var(--duration-slow) var(--ease-out);
    }

    @media (hover: hover) {
      &:hover {
        rotate: var(--tilt-l);
      }
    }
  }

  /* mode-switch: segmented control */
  .mode-switch {
    display: inline-flex;
    padding: var(--space-3xs);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-pill);
  }

  .mode-switch__option {
    min-block-size: calc(var(--target-min) - 2 * var(--space-3xs));
    padding-inline: clamp(var(--space-xs), 2vw, var(--space-s));
    font-size: var(--text-s);
    font-weight: var(--weight-medium);
    background: none;
    border: 0;
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: color var(--duration-base) var(--ease-out),
      background-color var(--duration-base) var(--ease-out);

    &[aria-pressed='true'] {
      font-weight: var(--weight-bold);
      color: var(--color-on-invert);
      background-color: var(--color-invert);
    }

    @media (hover: hover) {
      &[aria-pressed='false']:hover {
        background-color: var(--color-hover-tint);
      }
    }
  }

  /* nav-toggle + site-nav */
  .nav-toggle {
    display: grid;
    place-items: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    background: none;
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-m);
    cursor: pointer;
  }

  .site-nav {
    position: absolute;
    inset-block-start: calc(100% + var(--space-2xs));
    inset-inline: var(--frame);
    padding: var(--space-xs);
    background-color: var(--color-surface);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-l);

    &[data-state='closed'] {
      display: none;
    }
  }

  .site-nav__list {
    display: grid;
    gap: var(--space-3xs);
    padding: 0;
    list-style: none;

    & .button {
      margin-block-start: var(--space-2xs);
    }
  }

  .site-nav__link {
    display: flex;
    align-items: center;
    min-block-size: var(--target-min);
    padding-inline: var(--space-xs);
    font-size: var(--text-s);
    font-weight: var(--weight-medium);
    text-decoration: none;
    border-radius: var(--radius-s);

    @media (hover: hover) {
      &:hover {
        background-color: var(--color-hover-tint);
      }
    }
  }

  @media (width >= 56em) {
    .nav-toggle {
      display: none;
    }

    .site-nav,
    .site-nav[data-state='closed'] {
      position: static;
      display: block;
      padding: 0;
      background: none;
      border: 0;
    }

    .site-nav__list {
      display: flex;
      align-items: center;

      & .button {
        margin-block-start: 0;
        margin-inline-start: var(--space-2xs);
      }
    }
  }

  /* tag-list: technology chips */
  .tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    padding: 0;
    list-style: none;

    & li {
      padding: var(--space-3xs) var(--space-xs);
      font-size: var(--text-xs);
      font-weight: var(--weight-medium);
      line-height: 1.4;
      border: var(--border-width) solid var(--color-panel-line);
      border-radius: var(--radius-pill);
    }
  }

  /* project-card */
  .project-grid {
    display: grid;
    gap: var(--space-2xl) var(--space-l);
    padding: 0;
    list-style: none;
  }

  .project-card {
    position: relative;
    display: grid;
    align-content: start;
    gap: var(--space-m);
    border-radius: var(--radius-l);

    &:has(.project-card__link:focus-visible) {
      outline: var(--focus-width) solid var(--color-on-panel);
      outline-offset: var(--space-xs);
    }

    @media (hover: hover) {
      &:hover .project-card__media img {
        scale: 1.04;
      }

      &:hover .project-card__arrow {
        color: var(--color-on-accent);
        background-color: var(--color-accent);
        rotate: calc(var(--tilt-l) * -3.75);
      }
    }
  }

  .project-card__media {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius-l);

    & img {
      inline-size: 100%;
      block-size: 100%;
      object-fit: cover;
      transition: scale var(--duration-slow) var(--ease-out);
    }
  }

  .project-card__body {
    display: grid;
    gap: var(--space-xs);
    padding-inline-end: var(--space-xl);
  }

  .project-card__meta {
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
  }

  .project-card__title {
    font-size: var(--text-xl);
    line-height: 1.05;
  }

  .project-card__link {
    text-decoration: none;

    &::after {
      content: '';
      position: absolute;
      inset: 0;
      z-index: 1;
    }

    &:focus-visible {
      outline: none;
    }
  }

  .project-card__desc {
    max-inline-size: var(--measure);
    font-size: var(--text-s);
  }

  .project-card__arrow {
    position: absolute;
    inset-block-start: var(--space-s);
    inset-inline-end: var(--space-s);
    display: grid;
    place-items: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    color: var(--color-on-panel-chip);
    background-color: var(--color-panel-chip);
    border-radius: var(--radius-pill);
    transition: rotate var(--duration-base) var(--ease-spring),
      background-color var(--duration-fast) var(--ease-out);
  }

  @media (width >= 48em) {
    .project-grid {
      grid-template-columns: repeat(2, 1fr);
    }

    .project-card--featured {
      grid-column: 1 / -1;
    }
  }

  @media (width >= 64em) {
    .project-card--featured {
      grid-template-columns: 7fr 5fr;
      align-items: center;
      gap: var(--space-xl);

      & .project-card__title {
        font-size: var(--text-2xl);
        line-height: var(--leading-tight);
      }

      & .project-card__desc {
        font-size: var(--text-m);
      }

      & .project-card__arrow {
        inset-block: auto 0;
        inset-inline-end: 0;
      }
    }
  }

  /* gallery: graphic design works */
  .gallery {
    columns: 1;
    column-gap: var(--space-l);
    padding: 0;
    list-style: none;
  }

  .gallery__item {
    margin-block-end: var(--space-xl);
    break-inside: avoid;
  }

  .gallery__link {
    display: grid;
    gap: var(--space-xs);
    text-decoration: none;
    border-radius: var(--radius-l);

    & img {
      inline-size: 100%;
      border-radius: var(--radius-l);
      transition: rotate var(--duration-base) var(--ease-spring),
        scale var(--duration-base) var(--ease-spring);
    }

    &:focus-visible {
      outline-color: var(--color-on-panel);
    }

    @media (hover: hover) {
      &:hover img {
        rotate: calc(var(--tilt-s) * -1);
        scale: 1.02;
      }
    }
  }

  .gallery__caption {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2xs);
    font-size: var(--text-s);

    & strong {
      font-family: var(--font-display);
      font-size: var(--text-l);
      font-weight: var(--weight-heavy);
      letter-spacing: var(--tracking-tight);
    }
  }

  @media (width >= 40em) {
    .gallery {
      columns: 2;
    }
  }

  @media (width >= 64em) {
    .gallery {
      columns: 3;
    }
  }

  /* timeline: experience */
  .timeline {
    padding: 0;
    list-style: none;
  }

  .timeline__item {
    display: grid;
    gap: var(--space-3xs) var(--space-m);
    padding-block: var(--space-m);
    border-block-start: var(--border-width) solid var(--color-border-strong);
  }

  .timeline__when {
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
  }

  .timeline__role {
    font-weight: var(--weight-bold);
  }

  .timeline__where {
    font-weight: var(--weight-regular);
    color: var(--color-text-muted);

    &::before {
      content: '@ ';
    }
  }

  .timeline__desc {
    margin-block-start: var(--space-3xs);
    font-size: var(--text-s);
    color: var(--color-text-muted);
  }

  @media (width >= 40em) {
    .timeline__item {
      grid-template-columns: 7.5rem 1fr;
    }

    .timeline__when {
      padding-block-start: var(--space-3xs);
    }
  }

  /* skills: tool list */
  .skills {
    display: grid;
  }

  .skills__row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3xs) var(--space-s);
    padding-block: var(--space-xs);
    border-block-start: var(--border-width) solid var(--color-border);

    & dt {
      font-weight: var(--weight-bold);
    }

    & dd {
      margin: 0;
      font-size: var(--text-s);
      color: var(--color-text-muted);
    }
  }

  /* quote */
  .quote {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: var(--weight-heavy);
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-tight);
  }

  .quote__mark {
    padding-inline: 0.15em;
    color: var(--color-on-accent);
    background-color: var(--color-accent);
    border-radius: 0.2em;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
    transition: background-color var(--duration-slow) var(--ease-out);
  }

  /* scribble-link */
  .scribble-link {
    inline-size: fit-content;
    font-size: var(--text-s);
    font-weight: var(--weight-bold);
    text-decoration: underline wavy;
    text-decoration-thickness: 1.5px;
    text-underline-offset: 0.35em;

    @media (hover: hover) {
      &:hover {
        text-decoration-style: solid;
      }
    }
  }

  /* social */
  .social {
    display: flex;
    gap: var(--space-2xs);
    padding: 0;
    list-style: none;
  }

  .social__link {
    display: grid;
    place-items: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    border: var(--border-width) solid currentColor;
    border-radius: var(--radius-m);
    transition: rotate var(--duration-base) var(--ease-spring),
      background-color var(--duration-fast) var(--ease-out);

    &:focus-visible {
      outline-color: currentColor;
    }

    @media (hover: hover) {
      &:hover {
        color: var(--color-panel);
        background-color: var(--color-on-panel);
        rotate: calc(var(--tilt-m) * -1);
      }
    }
  }

  /* sticker: decorative die-cut stickers */
  .sticker {
    display: inline-grid;
    place-items: center;
    font-family: var(--font-display);
    font-weight: var(--weight-heavy);
    line-height: 1;
    letter-spacing: var(--tracking-tight);
    white-space: nowrap;
    user-select: none;
    rotate: var(--r, 0deg);
  }

  /* Small label stuck on an image corner. */
  .sticker--tag {
    position: absolute;
    inset-block-start: var(--space-s);
    inset-inline-start: var(--space-s);
    z-index: 1;
    padding: var(--space-2xs) var(--space-xs);
    font-size: var(--text-s);
    color: var(--color-sticker-ink);
    border: var(--sticker-edge) solid var(--color-sticker-edge);
    border-radius: var(--radius-m);
    rotate: calc(var(--tilt-m) * -1);
  }

  .sticker--crimson {
    background-color: var(--color-sticker-crimson);
  }

  .sticker--yellow {
    background-color: var(--color-sticker-yellow);
  }

  /* Starburst with an outline: ::before = edge, ::after = fill. */
  .sticker--burst {
    position: relative;
    inline-size: var(--sticker-size);
    aspect-ratio: 1;
    padding: var(--space-s);
    font-size: var(--text-l);
    text-align: center;
    color: var(--color-on-accent);
    isolation: isolate;

    &::before,
    &::after {
      content: '';
      position: absolute;
      z-index: -1;
      clip-path: var(--shape-burst);
    }

    &::before {
      inset: calc(var(--sticker-edge) * -1.4);
      background-color: var(--color-sticker-edge);
    }

    &::after {
      inset: 0;
      background-color: var(--color-accent);
      transition: background-color var(--duration-slow) var(--ease-out);
    }
  }

  .sticker--bubble {
    padding: var(--space-s) var(--space-m);
    font-size: var(--text-xl);
    color: var(--color-sticker-plum);
    background-color: var(--color-sticker-pink);
    border: var(--sticker-edge) solid var(--color-sticker-edge);
    border-radius: var(--radius-l) var(--radius-l) var(--radius-l) var(--radius-s);
  }

  .sticker svg {
    inline-size: var(--sticker-size);
    block-size: var(--sticker-size);
    overflow: visible;
  }

  .sticker__edge {
    fill: var(--color-sticker-edge);
    stroke: var(--color-sticker-edge);
    stroke-width: 12;
    stroke-linejoin: round;
  }

  .sticker__fill-ink { fill: var(--color-sticker-ink); }
  .sticker__fill-cream { fill: var(--color-sticker-edge); }
  .sticker__fill-crimson { fill: var(--color-sticker-crimson); }
  .sticker__fill-pink { fill: var(--color-sticker-pink); }
  .sticker__fill-blue { fill: var(--color-sticker-blue); }
  .sticker__fill-plum { fill: var(--color-sticker-plum); }
  .sticker__fill-yellow { fill: var(--color-sticker-yellow); }

  .sticker__line,
  .sticker__shine,
  .sticker__axis {
    fill: none;
    stroke-linecap: round;
    stroke-width: 6;
  }

  .sticker__line { stroke: var(--color-sticker-ink); }
  .sticker__shine { stroke: var(--color-sticker-edge); }
  .sticker__axis--x { stroke: var(--color-sticker-red); }
  .sticker__axis--y { stroke: var(--color-sticker-green); }
  .sticker__axis--z { stroke: var(--color-sticker-blue); }

  /* video: YouTube facade (poster + play), iframe on click */
  .video {
    position: relative;
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    color: var(--color-on-invert);
    background-color: var(--color-invert);
    border-radius: var(--radius-l);

    & img,
    & iframe {
      inline-size: 100%;
      block-size: 100%;
      object-fit: cover;
      border: 0;
    }

    & img {
      transition: scale var(--duration-slow) var(--ease-out);
    }

    @media (hover: hover) {
      &:hover img {
        scale: 1.03;
      }

      &:hover .video__play {
        scale: 1.1;
      }
    }
  }

  .video__play {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    inline-size: calc(var(--target-min) * 1.75);
    block-size: calc(var(--target-min) * 1.75);
    margin: auto;
    color: var(--color-on-accent);
    background-color: var(--color-accent);
    border: var(--sticker-edge) solid var(--color-sticker-edge);
    border-radius: var(--radius-pill);
    transition: scale var(--duration-base) var(--ease-spring);

    & .icon {
      --icon-size: 2rem;
    }
  }

  /* feature-list: strengths, roles, mechanics */
  .feature-list {
    display: grid;
    padding: 0;
    list-style: none;
  }

  .feature-list__item {
    display: grid;
    gap: var(--space-3xs);
    padding-block: var(--space-s);
    border-block-start: var(--border-width) solid var(--color-border-strong);
  }

  .feature-list__title {
    font-family: var(--font-display);
    font-size: var(--text-l);
    font-weight: var(--weight-heavy);
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-tight);
  }

  .feature-list__desc {
    font-size: var(--text-s);
    color: var(--color-text-muted);
  }

  /* todo: content still to be filled in, marked "(z)" */
  .todo {
    padding-inline: var(--space-3xs);
    font-weight: var(--weight-bold);
    color: var(--color-todo-fg);
    background-color: var(--color-todo-bg);
    border-radius: var(--radius-s);
    outline: var(--border-width) dashed var(--color-todo-fg);
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
  }

  .todo-block {
    display: grid;
    place-content: center;
    gap: var(--space-2xs);
    min-block-size: 12rem;
    padding: var(--space-l);
    font-weight: var(--weight-bold);
    text-align: center;
    color: var(--color-todo-fg);
    background-color: var(--color-todo-bg);
    border: var(--border-width) dashed var(--color-todo-fg);
    border-radius: var(--radius-l);

    & small {
      font-size: var(--text-s);
      font-weight: var(--weight-regular);
    }
  }

  /* project-group: shipped vs. jams/side projects */
  .project-group + .project-group {
    margin-block-start: var(--space-2xl);
  }

  .project-group__title {
    margin-block-end: var(--space-m);
    padding-block-end: var(--space-xs);
    font-size: var(--text-l);
    border-block-end: var(--border-width) solid var(--color-panel-line);
  }

  .project-card__role {
    font-size: var(--text-s);

    & b {
      font-weight: var(--weight-bold);
    }
  }

  /* Smaller cards for jams and side projects: less weight, same click target. */
  .project-grid--compact {
    gap: var(--space-xl) var(--space-l);

    & .project-card {
      gap: var(--space-s);
    }

    & .project-card__title {
      font-size: var(--text-l);
    }

    & .project-card__body {
      gap: var(--space-2xs);
      padding-inline-end: 0;
    }

    & .project-card__arrow {
      inline-size: var(--space-xl);
      block-size: var(--space-xl);
      inset-block-start: var(--space-xs);
      inset-inline-end: var(--space-xs);
    }
  }

  @media (width >= 64em) {
    .project-grid--compact {
      grid-template-columns: repeat(3, 1fr);
    }
  }

  /* viewer: project preview dialog */
  .viewer {
    inline-size: min(100% - 2 * var(--frame), var(--container));
    max-inline-size: none;
    block-size: min(100dvh - 2 * var(--frame), 60rem);
    max-block-size: none;
    margin: auto;
    padding: 0;
    color: var(--color-text);
    background-color: var(--color-surface);
    border: 0;
    border-radius: var(--radius-panel);

    &[open] {
      display: grid;
      grid-template-rows: auto 1fr;
      animation: viewer-in var(--duration-base) var(--ease-out);
    }

    &::backdrop {
      background-color: var(--color-scrim);
    }
  }

  .viewer__bar {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-m);
    border-block-end: var(--border-width) solid var(--color-border);
  }

  .viewer__title {
    flex: 1;
    min-inline-size: 0;
    overflow: hidden;
    font-family: var(--font-display);
    font-size: var(--text-l);
    font-weight: var(--weight-heavy);
    letter-spacing: var(--tracking-tight);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .viewer__open {
    display: none;
    align-items: center;
    gap: var(--space-3xs);
    font-size: var(--text-s);
    font-weight: var(--weight-medium);

    & .icon {
      --icon-size: 1rem;
    }
  }

  .viewer__close {
    display: grid;
    place-items: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    color: var(--color-on-invert);
    background-color: var(--color-invert);
    border: 0;
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: rotate var(--duration-base) var(--ease-spring);

    @media (hover: hover) {
      &:hover {
        rotate: 90deg;
      }
    }
  }

  .viewer__stage {
    position: relative;
    display: grid;
    place-items: center;
    min-block-size: 0;
    overflow: auto;
    background-color: var(--color-page);
    border-end-start-radius: var(--radius-panel);
    border-end-end-radius: var(--radius-panel);

    & iframe {
      inline-size: 100%;
      block-size: 100%;
      border: 0;
    }

    & img {
      max-block-size: 100%;
      padding: var(--space-m);
      object-fit: contain;
    }
  }

  .viewer__loader {
    position: absolute;
    inset: 0;
    margin: auto;
    inline-size: var(--space-xl);
    block-size: var(--space-xl);
    border: var(--focus-width) solid var(--color-border);
    border-block-start-color: var(--color-text);
    border-radius: var(--radius-pill);
    animation: spin 0.8s linear infinite;

    [data-state='ready'] > & {
      display: none;
    }
  }

  @media (width >= 48em) {
    .viewer__open {
      display: inline-flex;
    }
  }

  @keyframes viewer-in {
    from {
      opacity: 0;
      translate: 0 var(--space-l);
    }
  }

  @keyframes spin {
    to {
      rotate: 360deg;
    }
  }
}
