/* ==========================================================================
   Data by Toren — styles.css

   The pages were designed in Claude Design and carry their layout as inline
   styles against the tokens below. This file therefore holds only:
     1. the design-system tokens (copied verbatim from design-system/tokens/*)
     2. document base styles
     3. the four design-system components the pages instantiate
        (Button, Tag, Card, Badge) — ported from
        design-system/components/**/*.jsx so they render without the
        Claude Design runtime.

   Keeping tokens inline here means the site stays self-contained: three files
   plus images, nothing extra to upload. Do NOT deploy design-system/ or
   FromClaudeDesign/ to the web root.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1a. Fonts  (design-system/tokens/fonts.css)
   -------------------------------------------------------------------------- */
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:400;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/space-grotesk/files/space-grotesk-latin-400-normal.woff2) format('woff2')}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/space-grotesk/files/space-grotesk-latin-500-normal.woff2) format('woff2')}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:600;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/space-grotesk/files/space-grotesk-latin-600-normal.woff2) format('woff2')}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/space-grotesk/files/space-grotesk-latin-700-normal.woff2) format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/inter/files/inter-latin-400-normal.woff2) format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/inter/files/inter-latin-500-normal.woff2) format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/inter/files/inter-latin-600-normal.woff2) format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/inter/files/inter-latin-700-normal.woff2) format('woff2')}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-400-normal.woff2) format('woff2')}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff2) format('woff2')}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(https://cdn.jsdelivr.net/npm/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-600-normal.woff2) format('woff2')}

/* --------------------------------------------------------------------------
   1b. Tokens  (design-system/tokens/colors|typography|spacing.css)
   -------------------------------------------------------------------------- */
:root{
  --navy-900:#16304A;--navy-800:#1F3F5C;--navy-700:#2A5478;--navy-600:#336897;--navy-500:#4880B3;
  --navy-400:#6B9FCC;--navy-300:#96BEE0;--navy-200:#C3DBEF;--navy-100:#E1EDF7;--navy-50:#F1F7FC;
  --gray-900:#12161B;--gray-800:#1F262D;--gray-700:#333C46;--gray-600:#4B5560;--gray-500:#69747F;
  --gray-400:#8A94A0;--gray-300:#B2BAC2;--gray-200:#D8DDE2;--gray-100:#EBEEF1;--gray-50:#F7F8FA;
  --white:#FFFFFF;
  --teal-600:#178F81;--teal-500:#1FA898;--teal-400:#4CC0B2;--teal-300:#7FD3C7;--teal-100:#DCF3EF;
  --amber-500:#C68A2E;--amber-100:#F6EAD3;
  --red-500:#C0392F;--red-100:#F7E1DE;
  --green-500:#2E8B5C;--green-100:#DEF0E5;

  --bg-page:var(--white);
  --bg-subtle:var(--gray-50);
  --bg-muted:var(--gray-100);
  --bg-inverse:var(--navy-900);
  --surface-card:var(--white);
  --surface-card-border:var(--gray-200);
  --surface-raised:var(--white);

  --fg-primary:var(--gray-900);
  --fg-secondary:var(--gray-600);
  --fg-tertiary:var(--gray-500);
  --fg-inverse:var(--white);
  --fg-inverse-secondary:var(--navy-200);
  --fg-link:var(--navy-600);
  --fg-link-hover:var(--navy-700);

  --brand-primary:var(--navy-700);
  --brand-primary-hover:var(--navy-800);
  --brand-primary-active:var(--navy-900);
  --brand-secondary:var(--teal-500);
  --brand-accent:var(--teal-600);

  --border-default:var(--gray-200);
  --border-strong:var(--gray-300);
  --border-focus:var(--navy-500);

  --state-success:var(--green-500);--state-success-bg:var(--green-100);
  --state-warning:var(--amber-500);--state-warning-bg:var(--amber-100);
  --state-error:var(--red-500);--state-error-bg:var(--red-100);
  --state-info:var(--navy-500);--state-info-bg:var(--navy-50);

  --data-1:var(--navy-600);--data-2:var(--teal-500);--data-3:var(--navy-300);
  --data-4:var(--teal-300);--data-5:var(--gray-400);

  --font-display:'Space Grotesk',system-ui,sans-serif;
  --font-body:'Inter',system-ui,sans-serif;
  --font-mono:'IBM Plex Mono','SF Mono',monospace;

  --text-display-xl:4.5rem;
  --text-display-l:3.25rem;
  --text-display-m:2.25rem;
  --text-heading-l:1.5rem;
  --text-heading-m:1.25rem;
  --text-heading-s:1.0625rem;
  --text-body-l:1.125rem;
  --text-body-m:1rem;
  --text-body-s:0.875rem;
  --text-caption:0.75rem;
  --text-mono-m:0.9375rem;
  --text-mono-s:0.8125rem;

  --lh-tight:1.1;
  --lh-heading:1.25;
  --lh-body:1.55;
  --lh-mono:1.5;

  --tracking-tight:-0.02em;
  --tracking-normal:0;
  --tracking-wide:0.06em;

  --weight-regular:400;--weight-medium:500;--weight-semibold:600;--weight-bold:700;

  --space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:20px;--space-6:24px;
  --space-8:32px;--space-10:40px;--space-12:48px;--space-16:64px;--space-20:80px;
  --space-24:96px;--space-32:128px;

  --radius-xs:6px;--radius-sm:8px;--radius-md:12px;--radius-lg:18px;--radius-xl:24px;--radius-full:999px;

  --shadow-sm:0 1px 2px 0 rgba(16,42,68,0.06);
  --shadow-md:0 4px 12px -2px rgba(16,42,68,0.10),0 2px 4px -2px rgba(16,42,68,0.06);
  --shadow-lg:0 12px 32px -8px rgba(16,42,68,0.16),0 4px 8px -4px rgba(16,42,68,0.08);
  --shadow-focus:0 0 0 3px var(--navy-100);
  --shadow-inset:inset 0 1px 2px rgba(16,42,68,0.08);

  --ease-standard:cubic-bezier(.4,0,.2,1);
  --ease-out:cubic-bezier(0,0,.2,1);
  --ease-bounce:cubic-bezier(.34,1.56,.64,1);
  --duration-fast:120ms;--duration-base:200ms;--duration-slow:340ms;

  --container-max:1200px;
  --border-width:1px;
}

/* --------------------------------------------------------------------------
   2. Base  (from the pages' own <helmet> block, plus a light reset)
   -------------------------------------------------------------------------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; -webkit-text-size-adjust:100%; }
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{ animation-duration:.01ms !important; transition-duration:.01ms !important; }
}
body{
  margin:0;
  background:var(--bg-page);
  font-family:var(--font-body);
  color:var(--fg-primary);
  line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased;
}
/* height:auto is load-bearing — without it an HTML height attribute beats
   aspect-ratio and cropped images render at their intrinsic height. */
img{ max-width:100%; height:auto; }
a{ color:var(--fg-link); text-decoration:none; }
a:hover{ color:var(--fg-link-hover); }
:focus-visible{ outline:2px solid var(--border-focus); outline-offset:3px; border-radius:var(--radius-xs); }

.skip-link{
  position:absolute; left:-9999px; top:0; z-index:100;
  background:var(--brand-primary); color:var(--fg-inverse);
  padding:var(--space-3) var(--space-4);
  border-radius:0 0 var(--radius-xs) 0;
  font-size:var(--text-body-s); font-weight:var(--weight-semibold);
}
.skip-link:focus{ left:0; }

/* --------------------------------------------------------------------------
   3. Button   (ported from design-system/components/core/Button.jsx)
   -------------------------------------------------------------------------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center;
  font-family:var(--font-body);
  font-weight:var(--weight-semibold);
  border-radius:var(--radius-sm);
  border:var(--border-width) solid transparent;
  cursor:pointer; text-decoration:none;
  transition:background var(--duration-fast) var(--ease-standard),
             color var(--duration-fast) var(--ease-standard),
             border-color var(--duration-fast) var(--ease-standard),
             box-shadow var(--duration-fast) var(--ease-standard),
             transform var(--duration-fast) var(--ease-standard);
}
.btn:active{ transform:scale(.97); }

.btn-sm{ padding:var(--space-2) 14px; font-size:var(--text-body-s); gap:6px; }
.btn-md{ padding:10px 18px;            font-size:var(--text-body-m); gap:var(--space-2); }
.btn-lg{ padding:13px var(--space-6);  font-size:var(--text-body-l); gap:10px; }

.btn-primary{ background:var(--brand-primary); color:var(--fg-inverse); }
.btn-primary:hover{ background:var(--brand-primary-hover); color:var(--fg-inverse); box-shadow:var(--shadow-md); }

.btn-secondary{ background:var(--white); color:var(--brand-primary); border-color:var(--border-strong); }
.btn-secondary:hover{ background:var(--bg-subtle); color:var(--brand-primary); }

.btn-ghost{ background:transparent; color:var(--fg-primary); }
.btn-ghost:hover{ background:var(--bg-subtle); color:var(--fg-primary); }

/* --------------------------------------------------------------------------
   4. Tag   (ported from design-system/components/data-display/Tag.jsx)
   Outlined pill with a colored dot; --tag-dot is set per instance.
   -------------------------------------------------------------------------- */
.tag{
  display:inline-flex; align-items:center; gap:6px;
  padding:5px var(--space-2) 5px var(--space-3);
  border-radius:var(--radius-full);
  background:var(--white);
  border:var(--border-width) solid var(--border-default);
  font-size:var(--text-body-s);
  color:var(--fg-primary);
  white-space:nowrap;
}
.tag::before{
  content:""; flex:none;
  width:7px; height:7px; border-radius:var(--radius-full);
  background:var(--tag-dot, var(--navy-600));
}

/* --------------------------------------------------------------------------
   5. Card   (ported from design-system/components/data-display/Card.jsx)
   -------------------------------------------------------------------------- */
/* A column so the media keeps its natural height and the body takes whatever
   is left. Never size the body with height:calc(100% - <media height>) — that
   breaks the moment the artwork's aspect ratio changes, and `overflow:hidden`
   then silently clips the links row off the bottom. */
.card{
  display:flex;
  flex-direction:column;
  background:var(--surface-card);
  border:var(--border-width) solid var(--surface-card-border);
  border-radius:var(--radius-lg);
  box-shadow:var(--shadow-sm);
  overflow:hidden;
}
.card > :first-child{ flex:none; }   /* media */
.card > :last-child{ flex:1; }       /* body — fills the rest of the card */
/* The homepage project tiles lift on hover. That was Claude Design component
   state; it is CSS here so the pages need no runtime. (The thumbnails used to
   start desaturated and colour in on hover; removed 2026-09-24 at Toren's call.) */
.card-hover{
  transition:box-shadow var(--duration-base) var(--ease-standard),
             transform var(--duration-base) var(--ease-standard);
}
.card-hover:hover{ box-shadow:var(--shadow-lg); transform:translateY(-2px); }

/* --------------------------------------------------------------------------
   6. Skills intro — text beside the bar-chart figure
   Lives here rather than inline because it is the one block on the site that
   needs a breakpoint: the two columns are explicit, so without this they never
   collapse and the text column gets crushed (135px wide on a 375px phone).
   -------------------------------------------------------------------------- */
.skills-intro{
  display:grid;
  grid-template-columns:minmax(0,1fr) 192px;
  gap:80px;
  align-items:stretch;
  margin-bottom:var(--space-8);
}
@media (max-width:900px){
  .skills-intro{ grid-template-columns:1fr; gap:var(--space-8); }
  .skills-intro > figure{ width:192px; }
}

/* --------------------------------------------------------------------------
   6b. Media row — a 180px square image beside text (About, Contact)
   Same trap as .skills-intro: two explicit columns never collapse on their own.
   Before this class existed, About's text column measured 124px wide and 2,107px
   tall on a 375px phone. Stacks below 640px, where the text column would drop
   under ~370px.
   -------------------------------------------------------------------------- */
.media-row{
  display:grid;
  grid-template-columns:180px minmax(0,1fr);
  gap:40px;
  align-items:start;
}
@media (max-width:640px){
  .media-row{ grid-template-columns:1fr; gap:var(--space-6); }
}

/* --------------------------------------------------------------------------
   7. Case-study diagrams
   Inline SVG rather than a raster export: it scales crisply, themes from the
   tokens below (so it follows any palette change), weighs ~2 KB, and adds no
   file to deploy. Every label is real project structure — nothing invented.
   -------------------------------------------------------------------------- */
.case-diagram{
  margin:var(--space-8) 0 0;
  padding:var(--space-6);
  border:var(--border-width) solid var(--surface-card-border);
  border-radius:var(--radius-lg);
  background:var(--surface-card);
  box-shadow:var(--shadow-sm);
}
/* Below ~640px the labels would scale into illegibility, so the figure scrolls
   rather than shrinking the type past readability. */
.case-diagram{ overflow-x:auto; }
.case-diagram svg{ display:block; width:100%; min-width:640px; height:auto; }
.case-diagram figcaption{
  font-size:var(--text-body-s); color:var(--fg-tertiary);
  margin-top:var(--space-4); text-align:center; line-height:var(--lh-body);
}

/* diagram primitives */
.case-diagram .dg-cap{
  font-family:var(--font-mono); font-size:11px;
  text-transform:uppercase; letter-spacing:var(--tracking-wide);
  fill:var(--fg-tertiary); font-weight:var(--weight-semibold);
}
.case-diagram .dg-t{
  font-family:var(--font-body); font-size:13px;
  fill:var(--fg-primary); text-anchor:middle;
}
.case-diagram .dg-strong{ font-weight:var(--weight-semibold); }
.case-diagram .dg-sub{ font-size:12px; fill:var(--fg-secondary); }
.case-diagram .dg-src rect{ fill:var(--bg-subtle); stroke:var(--border-default); }
/* Marks an input that is maintained by hand rather than pulled from a feed. */
.case-diagram .dg-src rect.dg-manual{ stroke:var(--border-strong); stroke-dasharray:5 4; }
.case-diagram .dg-board rect{ fill:var(--white); stroke:var(--border-default); }
.case-diagram .dg-pipe{ fill:var(--navy-50); stroke:var(--navy-200); }
.case-diagram .dg-out{ fill:var(--teal-100); stroke:var(--teal-300); }
.case-diagram .dg-line path{ fill:none; stroke:var(--border-strong); stroke-width:1.5; }

/* --------------------------------------------------------------------------
   8. Badge   (ported from design-system/components/data-display/Badge.jsx)
   -------------------------------------------------------------------------- */
.badge{
  display:inline-flex; align-items:center;
  padding:3px 10px;
  border-radius:var(--radius-full);
  font-size:var(--text-caption);
  font-weight:var(--weight-semibold);
  letter-spacing:var(--tracking-wide);
  text-transform:uppercase;
  background:var(--bg-muted); color:var(--fg-secondary);
}
.badge-info{ background:var(--state-info-bg); color:var(--state-info); }
.badge-success{ background:var(--state-success-bg); color:var(--state-success); }
.badge-warning{ background:var(--state-warning-bg); color:var(--state-warning); }
.badge-error{ background:var(--state-error-bg); color:var(--state-error); }
