/* Portfolio stylesheet. Original fdc24d8 navy / blue / off-white / burnt-orange
   palette in the drawing-sheet layout. Ordered so each selector has one home:
   1 tokens · 2 base · 3 shell (sheet, header) · 4 homepage · 5 buttons and
   sections · 6 cards · 7 About and footer · 8 project pages · 9 media and
   embeds · 10 carousel and viewer · 11 photo compositions · 12 thermofluid
   models · 13 responsive (760, 640, 480, 380) · 14 reduced motion. */

/* 1 · Tokens */
:root {
  --ink:#142e43; --muted:#526577; --blue:#164e73; --paper:#fcfcfa;
  --line:#d8dfe3; --wash:#edf2f4; --accent:#b44716;
  --white:#fff; --card-surface:#faf9f7; --footer:#123a5a;
  --footer-muted:#b9c2cc; --footer-copy:#d8e4ec; --footer-note:#d2dde4;
  --footer-rule:#2c4964; --footer-link:#f0a868; --footer-link-soft:rgba(240,168,104,.4);
  --blue-hover:#23668f; --blue-border:#6c96b0; --accent-deep:#b23c08; --accent-muted:#9b6348;
  --line-on-blue:#ffffff66; --line-on-blue-soft:#ffffff40; --viewer-backdrop:rgba(8,20,30,.94);
  --status-good:#236334; --status-warn:#865215; --status-bad:#a32c27;
  --focus:#f0a868;
  --display:'Space Grotesk',system-ui,sans-serif;
  --body:'Inter','Helvetica Neue',Arial,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,monospace;
  --text-body:1.0625rem; --text-secondary:1rem; --text-support:.875rem; --text-label:.75rem;
  --frame:22px;
  --space-xs:8px; --space-sm:12px; --space-md:16px; --space-lg:20px;
  --space-xl:24px; --space-2xl:32px; --space-3xl:40px;
  --radius-sm:3px; --motion-fast:.18s ease;
}

/* 2 · Base */
* {box-sizing:border-box}
html {scroll-behavior:smooth;scroll-padding-top:110px}
body {margin:0;background:var(--paper);color:var(--ink);font:var(--text-body)/1.65 var(--body);-webkit-font-smoothing:antialiased}
a {color:var(--blue);text-decoration:none;text-underline-offset:.22em}
a:hover {color:var(--accent)}
p a,small a {text-decoration:underline}
button,a {-webkit-tap-highlight-color:transparent}
button {font:inherit;cursor:pointer;transition:transform var(--motion-fast),opacity var(--motion-fast)}
button:hover {transform:translateY(-1px)}
button:active {transform:translateY(1px);opacity:.88}
:focus-visible {outline:3px solid var(--focus,var(--accent));outline-offset:5px}
img,video,iframe {display:block;max-width:100%}
img {height:auto}
figure {margin:2rem 0}
h1,h2,h3,h4,p {margin:0 0 1.1rem}
h1,h2,h3 {font-family:var(--display);line-height:1.15;letter-spacing:-.015em;overflow-wrap:anywhere}
h1 {font-size:clamp(1.875rem,5.4vw,3.375rem);font-weight:700;line-height:1.06;letter-spacing:-.022em}
h2 {font-size:clamp(1.5rem,3.4vw,2.125rem);font-weight:600}
h3 {font-size:1.125rem;line-height:1.3;font-weight:600}
h4 {font:500 var(--text-label)/1.6 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
small,.small {font-size:var(--text-support);color:var(--muted)}
main p,main li {overflow-wrap:anywhere}
.skip {position:fixed;top:-100px;left:1rem;padding:.8rem;background:var(--paper);z-index:100}
.skip:focus {top:1rem}
.fragment-alias {display:block;scroll-margin-top:110px;width:0;height:0}

/* 3 · Drawing-sheet shell and header */
.sheet {position:relative;border:1px solid var(--line);margin:var(--frame);background:var(--paper)}
.sheet-content {position:relative}
.zones {position:absolute;top:0;bottom:0;width:var(--frame);display:flex;flex-direction:column;justify-content:space-around;align-items:center;font:9px var(--mono);letter-spacing:.08em;color:var(--muted);opacity:.55;pointer-events:none;user-select:none}
.zones.l {left:calc(var(--frame) * -1)}
.zones.r {right:calc(var(--frame) * -1)}
.wrap {max-width:1120px;margin:0 auto;padding:0 clamp(20px,5vw,56px)}
.site-header {position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;padding:16px clamp(20px,5vw,56px);border-bottom:1px solid var(--line);background:var(--paper)}
.brand {font:700 .9375rem var(--display);letter-spacing:.16em;text-transform:uppercase;color:var(--ink);white-space:nowrap;overflow-wrap:anywhere}
.brand span {color:var(--accent);margin-left:.35em}
.site-header .brand:hover,.site-header .brand:focus-visible,
.site-header .brand:hover span,.site-header .brand:focus-visible span {color:var(--accent)}
/* Non-home pages: the brand rests in the inactive nav treatment but keeps its identity on hover. */
.site-header .brand-inactive {font:400 .9375rem var(--display);letter-spacing:.16em;color:var(--muted);white-space:nowrap}
.site-header .brand-inactive span {color:var(--accent-muted)}
.site-header .brand-inactive:hover,.site-header .brand-inactive:focus-visible {color:var(--ink)}
.site-header nav {display:flex;gap:clamp(12px,2vw,24px);flex-wrap:wrap}
.site-header nav a {position:relative;display:inline-flex;align-items:center;min-height:44px;padding:8px 0;font:400 .8125rem/1.7 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);border-bottom:1.5px solid transparent}
.site-header nav a:hover,.site-header nav a[aria-current] {color:var(--ink);border-bottom-color:var(--accent)}
.site-header nav a[aria-current="location"] {color:var(--blue);font-weight:600;border-bottom:2px solid var(--accent)}
/* Decorative separators between links; hidden on the mobile grid. */
.site-header nav a+a::before {content:"";height:1em;border-inline-start:1px solid var(--line);position:absolute;left:calc(clamp(12px,2vw,24px) / -2)}

/* 4 · Homepage: intro, process line, title block and availability */
.home-intro {padding:clamp(40px,6vw,72px) 0 32px;text-align:center}
.eyebrow {font:400 11px/1.8 var(--mono);letter-spacing:.22em;text-transform:uppercase;color:var(--muted);margin-bottom:22px}
.home-intro h1 {font-size:clamp(2.125rem,6.7vw,4.75rem);margin:0 0 32px;letter-spacing:-.035em}
.home-intro h1 em {font-style:normal;color:var(--accent)}
.design-process {display:flex;justify-content:center;flex-wrap:wrap;gap:var(--space-xs) var(--space-sm);list-style:none;padding:0;margin:0 0 var(--space-3xl);font-size:clamp(.9375rem,1.7vw,1.25rem);line-height:1.5}
.design-process li {position:relative}
.design-process li+li::before {content:'→';color:var(--accent);margin-right:12px}
.design-process strong {color:var(--accent);font-weight:600}
.drawing-block {border:2px solid var(--blue);background:var(--paper)}
/* Title block and credentials share one four-column grid with aligned label/value rows. */
.title-grid,.credentials {display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:auto auto;margin:0;background:var(--paper);color:var(--ink)}
.title-grid {border-bottom:2px solid var(--blue)}
.title-grid>div,.credentials>div {display:grid;grid-row:span 2;grid-template-rows:subgrid;padding:0;min-width:0}
.title-grid>div+div,.credentials>div+div {border-left:1px solid var(--line)}
.title-grid dt,.credentials dt {font:500 var(--text-label)/1.6 var(--mono);letter-spacing:.1em;text-transform:uppercase;margin:0;padding:10px 12px;align-content:center;background:var(--blue);color:var(--paper);border-bottom:1px solid var(--line-on-blue-soft);overflow-wrap:anywhere}
.title-grid dd,.credentials dd {font:400 var(--text-support)/1.6 var(--mono);margin:0;padding:12px;align-content:start;background:var(--paper);color:var(--ink);overflow-wrap:anywhere}
.availability {padding-top:8px;padding-bottom:32px;text-align:center}
.availability .eyebrow {margin:0;font-size:var(--text-support);letter-spacing:.04em;line-height:1.9}

/* 5 · Buttons and portfolio sections */
.button {display:inline-flex;align-items:center;gap:var(--space-md);font:600 var(--text-support)/1.5 var(--display);letter-spacing:.03em;padding:var(--space-sm) var(--space-xl);border:1.5px solid var(--blue);background:var(--blue);color:var(--white);text-decoration:none;overflow-wrap:anywhere;transition:transform var(--motion-fast),opacity var(--motion-fast)}
.button:hover,.button:focus-visible {background:var(--ink);border-color:var(--ink);color:var(--white);transform:translateY(-1px)}
.button:active {transform:translateY(1px);opacity:.88}
.button.secondary {background:transparent;color:var(--blue)}
.button.secondary:hover,.button.secondary:focus-visible {background:var(--blue);color:var(--paper);border-color:var(--blue)}
.button:disabled,.button:disabled:hover {background:transparent;border-color:var(--line);color:var(--muted);transform:none;cursor:not-allowed}
.button-detail {font-size:var(--text-label)}
.document-actions {display:flex;justify-content:center;align-items:center;flex-wrap:wrap;gap:12px;width:100%;margin:24px 0}
.document-actions .button {justify-content:center;text-align:center}
.source-section>.document-actions {max-width:none}
.portfolio-section {padding:clamp(40px,5vw,64px) 0;border-top:1px solid var(--line)}
.band {background:var(--wash)}
.sec-head {display:flex;align-items:flex-start;gap:18px;margin-bottom:8px;flex-wrap:wrap}
.sec-head h2 {margin:0}
.sht {margin-top:3px;font:400 var(--text-label)/1.65 var(--mono);letter-spacing:.16em;color:var(--accent);border:1px solid var(--accent);padding:3px 9px;white-space:nowrap}
.sec-lede {color:var(--muted);max-width:64ch;margin:12px 0 34px;font-size:16px}

/* 6 · Project cards: restrained border/lift hover, one native link per card */
.grid {display:grid;gap:var(--space-lg);grid-template-columns:repeat(auto-fit,minmax(min(272px,100%),1fr))}
.card {position:relative;display:flex;min-width:0;border:1px solid var(--line);background:var(--card-surface);transition:transform var(--motion-fast),opacity var(--motion-fast)}
.card:hover,.card:focus-within {border-color:var(--accent-deep);transform:translateY(-3px)}
.card:active {transform:translateY(-1px);opacity:.94}
.card .fragment-alias {position:absolute;top:0}
.card-link {display:flex;flex-direction:column;flex:1;min-width:0;color:var(--ink);transition:opacity var(--motion-fast)}
.card-link:hover,.card-link:focus-visible {background:transparent;color:var(--ink)}
.card-link:active {opacity:.92}
.card-link:focus-visible {outline:3px solid var(--accent);outline-offset:5px}
.card figure {margin:0;border-bottom:1px solid var(--line);background:var(--white);overflow:hidden}
.card picture {display:block}
.card figure img {width:100%;aspect-ratio:16/10;object-fit:contain;background:var(--white)}
/* Trim the supplied PNG's white margins, retaining the model and its shadow. */
.card figure img.tetrahedron-thumbnail {transform:scale(1.18) translateY(-4%)}
.card-body {padding:18px var(--space-lg);flex:1;display:flex;flex-direction:column;min-width:0;overflow-wrap:anywhere}
.card-body h3 {margin:0}
.card-body p {color:var(--muted);font-size:1rem;margin:10px 0 0;flex:1}
.card-body .meta,.card-body small {font:400 var(--text-support)/1.6 var(--mono);letter-spacing:.02em;color:var(--muted);margin-top:6px;padding:0;border:0;flex:0}
.card-link:hover .card-body p,.card-link:hover .card-body small,.card-link:focus-visible .card-body p,.card-link:focus-visible .card-body small {color:var(--muted)}
.card-cta {display:flex;justify-content:flex-start;gap:.35em;margin:0 20px 18px;padding-top:4px;font:600 var(--text-support)/1.5 var(--display);color:var(--blue)}
.card-body .card-cta {margin:20px 0 0}
.card-link:hover .card-cta,.card-link:focus-visible .card-cta {color:var(--accent-deep)}
.featured-card {margin-top:28px}
.featured-card .card-link {display:grid;grid-template-columns:minmax(0, .8fr) minmax(0, 1.2fr);align-items:stretch}
.featured-card figure {position:relative;border:0;min-height:0;background:transparent;align-self:center;overflow:visible}
.featured-card figure img {position:static;inset:0;height:auto;width:100%;aspect-ratio:1217/1293;object-fit:contain;object-position:center;background:transparent}
.featured-card .card-body {justify-content:center;padding:24px}
.featured-card h3 {font-size:clamp(1.375rem,2.8vw,1.875rem)}
.featured-card .card-body p {flex:0;margin-top:10px}
.featured-card .card-body .meta {margin-top:6px}

/* 7 · About, qualifications table and contact footer */
.about-intro {margin:28px 0 0}
.about-intro>.copy {max-width:none}
.about-intro .resume-action {margin:28px 0 0;text-align:center}
/* Homepage About & Contact: email directly beneath the resume button. */
.about-intro .about-email {margin:18px 0 0;text-align:center;font-size:1rem}
.about-intro .about-email a {display:inline-block;min-height:44px;line-height:44px;color:var(--accent-deep);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.18em;overflow-wrap:anywhere}
.about-intro .about-email a:hover,.about-intro .about-email a:focus-visible {color:var(--ink)}
.case-content:has(>.about-intro) {padding-bottom:40px}
.case-content:has(>.about-intro)>.source-section {padding:0;border:0}
.case-content:has(>.about-intro)>.source-section>small {margin:0}
.qualification-scroll {overflow-x:auto;max-width:100%}
.revtable {width:100%;border-collapse:collapse;margin-top:28px;font:400 var(--text-support)/1.65 var(--mono);color:var(--ink)}
.revtable caption {text-align:left;font-size:var(--text-label);letter-spacing:.08em;text-transform:uppercase;color:var(--blue);margin-bottom:12px}
.revtable th,.revtable td {border:1px solid var(--line);padding:12px;text-align:left;vertical-align:top}
.revtable thead th {background:var(--blue);color:var(--paper);font-weight:500;letter-spacing:.08em;text-transform:uppercase;font-size:var(--text-label)}
.revtable tbody th {font-weight:500;color:var(--blue)}
.revtable tbody tr:nth-child(even) {background:var(--wash)}
.revtable td:nth-child(2),.revtable th:first-child,.revtable th:last-child,.revtable td:last-child {white-space:nowrap}
.revtable td:last-child {width:3em}
.site-footer {--contact-gap:18px;position:relative;background:var(--footer);color:var(--card-surface);padding:clamp(48px,6vw,72px) 0 34px}
.site-footer h2 {color:var(--card-surface);margin:0}
.site-footer p {overflow-wrap:anywhere}
.site-footer :focus-visible {outline-color:var(--footer-link)}
.site-footer .contact-row {display:flex;flex-direction:column;align-items:flex-start}
.site-footer .contact-row p {color:var(--footer-muted);max-width:64ch;margin:12px 0 var(--contact-gap);font-size:16px}
.site-footer .contact-link {display:block;margin:0;min-height:0;border:0;color:var(--footer-link);font-size:1rem;line-height:1.65;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.18em;overflow-wrap:anywhere}
.site-footer .contact-link:hover {color:var(--white);border:0}
.site-footer .foot-note {display:flex;justify-content:space-between;align-items:center;gap:var(--space-md);flex-wrap:wrap;margin:var(--contact-gap) 0 0;padding-top:var(--contact-gap);border-top:1px solid var(--footer-rule);font:400 var(--text-label)/1.65 var(--mono);letter-spacing:.12em;color:var(--footer-muted);text-transform:uppercase}
.site-footer .foot-note>span:last-child {text-align:right}
.footer-zone {position:absolute;top:50%;transform:translateY(-50%);width:var(--frame);text-align:center;font:9px var(--mono);letter-spacing:.08em;color:var(--muted);opacity:.55;pointer-events:none;user-select:none}
.footer-zone.l {left:calc(var(--frame) * -1)}
.footer-zone.r {right:calc(var(--frame) * -1)}
/* Homepage: the availability line and revision note already appear above, so the footer is heading and email only. */
.site-footer.footer-compact {padding:clamp(28px,4vw,40px) 0 30px}
.site-footer.footer-compact .contact-row h2 {margin-bottom:var(--contact-gap)}

/* 8 · Project pages: hero, sections, contribution lists, galleries, navigation */
.intro {max-width:1120px;margin:auto;padding:24px clamp(20px,5vw,56px) 28px}
.intro h1 {max-width:22ch}
.lead {max-width:60ch;font-size:1.125rem;color:var(--muted)}
.project-tags {font:400 var(--text-support)/1.65 var(--mono);color:var(--muted);margin:8px 0 0}
.hero-media {max-width:1008px;margin:0 auto 40px;padding:0 20px}
.hero-media img {width:100%;max-height:640px;object-fit:contain;background:transparent}
.project-hero {display:grid;grid-template-columns:1fr 1fr;gap:32px;align-items:center;max-width:1120px;margin:20px auto 32px;padding:0 clamp(20px,5vw,56px)}
.project-hero .intro {padding:0;margin:0;min-width:0}
.project-hero .hero-media {margin:0;padding:0;min-width:0;width:100%}
.project-hero .hero-media img {max-height:480px}
.project-hero .lead {font-size:1.0625rem;margin-bottom:0}
.case-content {max-width:1120px;margin:auto;padding:0 clamp(20px,5vw,56px)}
.case-content>.source-section:first-of-type {border-top:0}
.source-section {padding:40px 0;border-top:0}
.source-section>.copy,.source-section>p {max-width:70ch}
.source-section h2 {margin:1.5rem 0;max-width:30ch}
.source-section h2:first-child {margin-top:0}
.source-section h3 {margin:1.5rem 0 1rem}
.source-section>small {display:block;margin:1.2rem 0}
.source-section figure {background:transparent}
.source-section figure img {width:100%;max-height:850px;object-fit:contain}
.source-section:has(>h2):not(:has(>p,>figure,>div)) {padding-bottom:16px}
.source-section:has(>.gallery) {padding-top:20px}
.gallery {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px;margin:2rem 0}
.gallery figure {margin:0}
.gallery img,.gallery .motion video {width:100%;height:360px;object-fit:contain}
.image-link {display:block;cursor:zoom-in}
figcaption {font:400 var(--text-support)/1.5 var(--body);color:var(--muted);text-align:center;padding:10px 12px;margin:0;background:transparent}
.project-credits {font:italic 400 var(--text-support)/1.65 var(--body);color:var(--muted)}
.project-credits>small {font:inherit;display:block;margin:4px 0}
.project-nav {display:flex;justify-content:space-between;gap:2rem;max-width:1008px;margin:24px auto;padding:24px 20px 0;border-top:1px solid var(--line);font-size:var(--text-support)}
.project-nav a {display:inline-flex;align-items:center;min-height:44px;padding:12px 16px;border:1px solid var(--blue);max-width:48%}
.project-nav a:hover,.project-nav a:focus-visible {background:var(--blue);color:var(--paper)}
.project-nav a[rel="next"] {margin-left:auto;text-align:right}
/* Decision subtitles sit before the media-row rules so a row heading keeps margin 0 (same specificity). */
.warman-page .decision-subtitle {font:500 1.125rem/1.4 var(--mono);color:var(--muted);margin:0 0 16px}
/* Two-column media rows (Warman) and their heading/copy/media alignment. */
.media-row {display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:32px;align-items:start}
.media-row.media-first {grid-template-columns:minmax(0,1fr) minmax(0,2fr)}
.media-first .row-media {grid-column:1;grid-row:1}
.media-first .row-copy {grid-column:2;grid-row:1}
.row-copy,.row-media {min-width:0}
.media-row figure,.media-row .youtube {margin:0}
.row-copy h2:first-of-type {margin-top:0}
.row-copy > :last-child {margin-bottom:0}
.row-copy .track-figure {margin-top:24px}
.row-copy .track-figure img {max-height:none}
.body-aligned {row-gap:16px}
.body-aligned>.row-heading {grid-column:1;grid-row:1;margin:0}
.body-aligned>.row-copy {grid-column:1;grid-row:2}
.body-aligned>.row-media {grid-column:2;grid-row:2}
.body-aligned.media-first>.row-heading {grid-column:2}
.body-aligned.media-first>.row-copy {grid-column:2;grid-row:2}
.body-aligned.media-first>.row-media {grid-column:1;grid-row:2}
.report-column {text-align:center}
.report-column .track-figure {margin:0 0 16px}
.report-column .track-figure img {width:100%;height:auto;max-height:none}
.report-column p {margin:12px 0 0}
.report-column .button {justify-content:center}
/* Warman (bespoke legacy page) */
.warman-page .source-section {border-top:0;padding:24px 0}
.warman-page .source-section:has(>.gallery) {padding-top:0}
.warman-page .source-section:has(>h2):not(:has(>p,>figure,>div)) {padding-bottom:0}
.warman-page .highlight-row {display:block}
.warman-page .full-width-copy>.copy {max-width:none}
.warman-page .comparison-row {display:block}
.warman-page .comparison-row .row-media {margin-top:24px}
.warman-page .project-tags {font-family:var(--body)}
.warman-page .contribution-section {display:block}
.warman-page .contribution-section>.row-heading {margin:0 0 16px}
.warman-page .contribution-section .track-figure {max-width:680px;margin:24px auto 0}
.warman-page .decision-heading {padding-bottom:0}
.warman-page .decision-heading h2 {margin:0}
.warman-page .decision-heading+.source-section {padding-top:16px}
.warman-page .heading-full-width>.row-heading {grid-column:1 / -1}
.warman-page .media-followup {padding-top:0;padding-bottom:24px}
.warman-page .media-followup>.gallery {margin:0}
.warman-page .media-followup .carousel picture {display:block;width:100%}
.warman-page .media-followup .carousel img {width:100%;height:auto;max-height:480px;object-fit:contain;object-position:center top}
.warman-page .media-row {padding-bottom:24px}
.warman-page .media-row .row-copy>:last-child {margin-bottom:0}
.warman-page .body-aligned.media-first {grid-template-columns:minmax(0,800fr) minmax(0,1021fr)}
.warman-page .body-aligned .row-media video {height:auto;width:100%;object-fit:contain}
/* Contract shared by templates/design-project.html and drawing-project.html. */
.compact-project .project-hero {margin-bottom:16px}
.compact-project .contribution-section {padding-top:20px;padding-bottom:12px}
.compact-project .contribution-section h2 {margin:0 0 16px}
.compact-project .contribution-section>p:last-child {margin-bottom:0}
.compact-project .source-section:has(>.gallery) {padding-top:12px;padding-bottom:0}
.compact-project .source-section>.gallery {margin:0}
.compact-project .source-section.project-video-section {padding:24px 0 8px}
.compact-project .document-actions {margin:24px 0}
.project-page .hero-media>figure {margin:0}
.project-page .source-section>p {max-width:none}
.project-page .contribution-list,.warman-page .contribution-list {list-style:none;padding:0;margin:0;max-width:none}
.project-page .contribution-list li,.warman-page .contribution-list li {position:relative;padding-left:1.5rem;margin:0 0 .8rem}
.project-page .contribution-list li::before,.warman-page .contribution-list li::before {content:'—';position:absolute;left:0;color:var(--accent)}
.project-page .contribution-list li:last-child,.warman-page .contribution-list li:last-child {margin-bottom:0}
.project-page .contribution-list ul {padding:12px 0 0 20px;list-style:none}
.project-page .source-section.project-gallery {padding:24px 0 0}
.project-page .project-gallery>h2 {margin:0 0 16px}
.project-page .project-gallery>.gallery {margin:0}
/* Drawing intros have no title-side media; all sheets live in their galleries. */
.drawing-project .project-hero {display:block}
.drawing-project .intro,.drawing-project .intro .lead {max-width:none}
/* Analysis pages: bounded, readable calculation views. */
.calculation-results {display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin:24px 0}
.calculation-results dt {font-size:var(--text-support)}
.calculation-results dd {margin:8px 0 0;font-weight:600;font-size:1.125rem;overflow-wrap:anywhere}

/* 9 · Motion video and the opt-in YouTube embed */
.motion {position:relative}
.motion video {width:100%;height:auto;max-height:640px;object-fit:contain;background:transparent}
.motion video[controls] {cursor:default}
/* Hero animations cap lower than gallery motion; must follow .motion video (same specificity). */
.project-hero .motion {margin:0}
.project-hero video {width:100%;height:auto;max-height:480px;object-fit:contain}
.youtube {position:relative;margin:2rem 0;max-width:1000px}
.youtube-load {position:relative;display:block;width:100%;border:0;padding:0;background:transparent}
.youtube-load span {position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--ink);color:var(--white);padding:1rem 1.5rem}
.youtube .video-window {display:flex;align-items:center;justify-content:center;width:100%;aspect-ratio:16/9;background:var(--ink);cursor:pointer}
.youtube .video-window span {position:static;transform:none;max-width:100%;overflow-wrap:anywhere;background:var(--blue);color:var(--white);border:1px solid var(--blue-border);padding:14px 20px;font:600 var(--text-support)/1.5 var(--display)}
.youtube .video-window:hover span {background:var(--blue-hover)}
.youtube.is-loading::after {content:'Loading video…';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);padding:var(--space-sm) var(--space-lg);background:var(--ink);color:var(--white);pointer-events:none;animation:loading-pulse 1.2s ease-in-out infinite alternate}
@keyframes loading-pulse {from {opacity:.55;transform:translate(-50%,-50%) scale(.98)}to {opacity:1;transform:translate(-50%,-50%) scale(1)}}
.youtube iframe {border:0;width:100%;aspect-ratio:16/9}
.highlight-row .youtube iframe {display:block}
.youtube .small {margin:.8rem 0}
/* Centred embeds override the default embed width; order matters against .youtube above. */
.centred-video {width:100%;max-width:800px;margin:0 auto}
.centred-video iframe {display:block}
.lifecycle-video {margin-top:24px}
.youtube-fallback {margin:var(--space-sm) 0 0;font-size:var(--text-support);color:var(--muted);text-align:center}
.youtube-fallback a {color:var(--accent-deep)}
.youtube-fallback .youtube-retry {margin-left:var(--space-xs);padding:8px 14px;font-size:var(--text-support);cursor:pointer}
.youtube noscript p {margin:var(--space-sm) 0 0;text-align:center}

/* 10 · Carousel (progressive enhancement) and the enlarged viewer dialog */
/* Every slide occupies the same grid cell, so a carousel is always as tall as its tallest
   slide and the page below it never moves between slides. Hidden slides stay laid out
   (visibility, not display) so their size still counts. Subgrid rows give all slides one
   shared image row and one shared caption row: each image centres in the common image area
   and every caption starts on the same line. Without subgrid support the figure keeps its
   own rows and only the caption line may shift. */
.carousel.is-ready {display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto;gap:0}
.carousel.is-ready > figure {grid-area:1 / 1 / 3 / 2;display:grid;grid-template-rows:subgrid;margin:0}
.carousel.is-ready > figure[hidden] {visibility:hidden}
.carousel.is-ready > figure > :first-child {align-self:center}
.carousel.is-ready > figure > figcaption {align-self:start}
.carousel.is-ready > .carousel-controls {grid-row:3}
.carousel .image-link {display:flex;justify-content:center;align-items:center}
.carousel.is-ready picture,.carousel.is-ready .image-link {display:block;width:100%}
/* A definite width lets the width/height attributes reserve the slide's height before the
   file loads (an unloaded image has no natural size, so width:auto collapses to 0 and the
   slide jumps when it arrives). object-fit centres the picture inside the reserved box;
   the auto margins centre the narrower ratio-sized Tactile sketches. */
.carousel.is-ready img {display:block;margin-inline:auto;width:100%;height:auto;max-height:480px;object-fit:contain}
/* The browser draws the alt text inside the reserved box until the file arrives. Keep it invisible
   while loading so the box stays blank, and show it centred only when media.js marks a failed load. */
.carousel.is-ready img {font:400 var(--text-support)/1.5 var(--body);text-align:center;align-content:center;color:transparent}
.carousel.is-ready img.is-broken {color:var(--muted)}
.carousel.is-ready .motion video {height:clamp(240px,45vw,480px);max-height:none}
.carousel video[role="button"] {cursor:zoom-in}
.carousel-controls {display:flex;align-items:center;justify-content:center;gap:16px;margin-top:12px}
.carousel-controls button,.image-viewer button {font:500 var(--text-support)/1.4 var(--body);min-width:44px;min-height:44px;border:1px solid var(--blue);background:var(--paper);color:var(--blue);cursor:pointer;padding:8px 12px}
.carousel-controls button:hover {background:var(--blue);color:var(--paper)}
.carousel-status {font-size:var(--text-support);color:var(--muted);min-width:5ch;text-align:center}
/* External classes keep scan trimming compatible with the production CSP. The clip is relative to the
   element box, so these three carousel images keep a picture-sized box: a definite width from each
   sketch's own ratio (1055x1491 portrait, 1491x1055 landscape) reserves space before load without a jump. */
.crop-sketch-rough {clip-path:inset(0 1% 0 0)}
.crop-sketch-interaction {clip-path:inset(1%)}
.crop-sketch-isometric {clip-path:inset(1% 0 0 1%)}
.carousel.is-ready {--slide-max-height:480px}
.carousel.is-ready img.crop-sketch-isometric {width:min(100%,calc(var(--slide-max-height) * 1055 / 1491))}
.carousel.is-ready img.crop-sketch-interaction,.carousel.is-ready img.crop-sketch-rough {width:min(100%,calc(var(--slide-max-height) * 1491 / 1055))}
.image-viewer {max-width:none;max-height:none;width:100vw;height:100dvh;padding:20px;border:0;background:transparent;color:white;overflow:hidden}
.image-viewer::backdrop {background:var(--viewer-backdrop)}
.image-viewer[open] {display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding-top:76px;padding-bottom:24px}
.image-viewer :focus-visible {outline-color:var(--footer-link)}
.image-viewer button {align-self:flex-start;flex-shrink:0}
.image-viewer img,.image-viewer video {max-width:100%;max-height:calc(100dvh - 200px);width:auto;height:auto;object-fit:contain;min-height:0;background:transparent}
.image-viewer img[hidden],.image-viewer video[hidden] {display:none}
.image-viewer p {font-size:var(--text-support);line-height:1.4;text-align:center;margin:0;color:var(--white);max-width:75ch;flex-shrink:0}
.image-viewer .viewer-stage {position:relative;display:flex;justify-content:center;align-items:center;width:fit-content;max-width:100%;min-height:0;flex-shrink:1}
.image-viewer .viewer-stage>button {position:absolute;right:0;left:auto;bottom:100%;margin-bottom:8px}
.image-viewer .viewer-stage>img,.image-viewer .viewer-stage>video {max-height:calc(100dvh - 240px);max-width:100%;width:auto;height:auto}
.image-viewer .viewer-controls {display:flex;align-items:center;justify-content:center;gap:16px;flex-shrink:0}
.image-viewer .viewer-controls[hidden] {display:none}
.image-viewer .viewer-controls button {align-self:center}
.image-viewer .viewer-controls span {font:400 var(--text-support)/1.5 var(--mono);min-width:5ch;text-align:center}
body:has(.image-viewer[open]) {overflow:hidden}

/* 11 · Photo compositions keep original photos intact; the same elements enter the viewer. */
.media-layout {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;width:min(100%,800px);margin:auto}
.media-layout.reference-grid {grid-template-columns:repeat(2,minmax(0,1fr));width:min(100%,800px);align-items:center;gap:4px}
.media-layout.single-photo {grid-template-columns:1fr;width:min(100%,640px)}
.media-layout .photo-frame {display:block;position:relative;overflow:hidden;min-width:0;aspect-ratio:4/3}
.media-layout.reference-grid .photo-frame {aspect-ratio:auto}
.media-layout.portrait-pair .photo-frame {aspect-ratio:1355/1800}
.media-layout .photo-frame.crop-neolt {aspect-ratio:1800/1355}
.media-layout .photo-frame.crop-window {aspect-ratio:1138.2/1332}
/* The picture element must fill the frame, or the image's height:100% resolves against an
   auto-height wrapper and a portrait photo overflows the clipped 4:3 frame. */
.carousel .media-layout .photo-frame picture,.viewer-composite .photo-frame picture {display:block;width:100%;height:100%}
.carousel .media-layout .photo-frame img,.viewer-composite .photo-frame img {display:block;width:100%;height:100%;max-width:none;max-height:none;object-fit:contain}
.carousel .reference-grid .photo-frame img,.viewer-composite .reference-grid .photo-frame img {height:auto}
.carousel .media-layout .crop-neolt img,.viewer-composite .crop-neolt img {position:absolute;width:125%;height:125%;left:-25%;top:-25%;object-fit:fill}
.carousel .media-layout .crop-window img,.viewer-composite .crop-window img {position:absolute;width:119.047619%;height:135.135135%;left:0;top:0;object-fit:fill}
.viewer-stage.has-composite {width:min(100%,1000px)}
.viewer-composite {max-height:calc(100dvh - 220px);overflow:auto;width:100%}
.viewer-composite[hidden] {display:none}
.viewer-composite .media-layout {width:100%}

/* 12 · Interactive thermofluid models: controls left, live plots right */
.model-layout {display:grid;grid-template-columns:minmax(230px,.75fr) minmax(0,1.25fr);gap:32px;align-items:start;margin-top:24px}
.model-controls {border:1px solid var(--line);padding:20px;min-width:0}
.model-input label,.model-controls dt {font-size:var(--text-support);font-weight:400;display:block}
.model-input output,.model-controls dd {display:block;margin:8px 0 0;font-family:var(--body);font-weight:600;font-size:1.125rem}
.model-input input {display:block;width:100%;min-height:44px;accent-color:var(--blue)}
.model-input+.model-input {margin-top:16px}
.model-controls .calculation-results {display:grid;grid-template-columns:1fr;gap:16px;margin:20px 0}
.model-status {font-size:var(--text-support);min-height:3.2em;margin:16px 0}
.pipeline-interactive .model-controls {min-height:360px}
.model-reset {font:inherit;font-size:var(--text-support);padding:10px 12px;min-height:44px;background:transparent;border:1px solid var(--line);color:var(--ink);cursor:pointer}
.model-reset:hover {background:var(--wash)}
.model-plots {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.model-plots:empty {min-height:180px;border:1px solid var(--line);display:grid;place-items:center;color:var(--muted)}
.model-plots:empty::before {content:'Loading chart…';animation:loading-pulse 1.2s ease-in-out infinite alternate}
.model-plots svg {display:block;width:100%;height:auto;overflow:visible}
#heat-plot {grid-template-columns:1fr}
.plot-title {font:600 13px var(--body);fill:var(--ink)}
.plot-tick {font:400 11px var(--body);fill:var(--muted)}
.plot-grid {stroke:var(--line);stroke-width:1}
.plot-curve {fill:none;stroke:var(--blue);stroke-width:2.5}
.plot-cursor {stroke:var(--blue);stroke-dasharray:3 4;opacity:.6}
.plot-current {fill:var(--blue);stroke:var(--paper);stroke-width:1}
.plot-reference {fill:var(--paper);stroke:var(--accent);stroke-width:2}
.heat-curve-gas {stroke:var(--accent)}
.heat-point-gas {fill:var(--accent)}
.heat-chart-key {font-size:var(--text-support);text-align:center;margin:8px 0}
.heat-chart-key .water {color:var(--blue)}
.heat-chart-key .gas {color:var(--accent)}
.plot-legend {font-size:var(--text-support);text-align:center;margin:12px 0 0;display:flex;justify-content:center;gap:24px}
.legend-current {color:var(--blue)}
.legend-reference {color:var(--accent)}
.flow-regime {font-size:var(--text-support);white-space:nowrap}
.flow-regime.laminar {color:var(--status-good)}
.flow-regime.transitional {color:var(--status-warn)}
.flow-regime.turbulent {color:var(--status-bad)}

/* 12b · Interactive CAD viewer: poster until asked, then a WebGL canvas in the same box. */
.cad-viewer,.cad-switch {--cad-cube-size:128px;--cad-cube-margin:12px}
.cad-viewer {position:relative;margin:24px 0 0}
.cad-stage {position:relative;aspect-ratio:16/9;background:var(--wash);border:1px solid var(--line);display:grid;place-items:center;overflow:hidden}
.cad-stage picture {display:block;width:100%;height:100%}
.cad-stage img {width:100%;height:100%;object-fit:contain;display:block}
.cad-stage canvas {position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none;cursor:grab}
.cad-stage canvas:active {cursor:grabbing}
.cad-stage canvas:focus-visible {outline:3px solid var(--blue);outline-offset:-3px}
/* The centring translate has to be repeated in every state, or .button's hover transform
   replaces it and the button jumps half its width to the right. */
.cad-load {position:absolute;bottom:16px;left:50%;transform:translateX(-50%);z-index:1}
.cad-load:hover,.cad-load:focus-visible {transform:translateX(-50%) translateY(-1px)}
.cad-load:active {transform:translateX(-50%) translateY(1px)}
.cad-home {position:absolute;top:var(--cad-cube-margin);right:calc(var(--cad-cube-margin) + var(--cad-cube-size) + 8px);width:34px;height:34px;padding:0;display:grid;place-items:center;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-sm);color:var(--blue);z-index:2}
.cad-home svg {width:19px;height:19px;fill:currentColor}
.cad-home:hover {background:var(--wash);color:var(--accent)}
.cad-stage.cad-cube-over canvas {cursor:pointer}
.cad-stage.cad-cube-drag canvas {cursor:grabbing}
/* The view cube's face-view arrows, over the cube's corner of the canvas (cad-viewcube.js draws the cube there). */
.cad-cube-arrows {position:absolute;top:var(--cad-cube-margin);right:var(--cad-cube-margin);width:var(--cad-cube-size);height:var(--cad-cube-size);display:none;pointer-events:none;z-index:2}
.cad-cube-arrows.is-shown {display:block}
.cad-cube-arrow {color:var(--blue-border);cursor:pointer}
.cad-cube-arrow:hover {color:var(--blue)}
/* One viewer for several models (cad-viewer.js, .cad-switch): the figures share one grid cell and the ones not shown stay laid out but invisible, so the set keeps its tallest figure's height and the page never moves when the reader switches; the radio buttons sit under the view cube. */
.cad-switch.is-ready {position:relative;display:grid;margin:24px 0 0}
.cad-switch.is-ready > .cad-viewer {grid-area:2 / 1;margin:0}
.cad-switch.is-ready > .cad-viewer[hidden] {display:block;visibility:hidden}
.cad-switch .cad-controls:empty {min-height:48px}
.cad-switcher {position:absolute;top:calc(var(--cad-cube-margin) + var(--cad-cube-size) + 5px);right:calc(var(--cad-cube-margin) + 1px);z-index:2;display:flex;flex-direction:column;gap:2px;padding:6px 12px;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-sm);font-size:var(--text-support)}
.cad-switcher label {display:flex;align-items:center;gap:8px;min-height:28px;cursor:pointer;white-space:nowrap}
.cad-switcher input {margin:0;accent-color:var(--blue)}
.cad-viewer.is-loading .cad-load {opacity:.6}
.cad-controls {margin:12px 0 0;display:flex;flex-direction:column;gap:12px;align-items:center;flex-wrap:wrap}
.cad-actions {margin:12px 0 0;display:flex;gap:12px;flex-wrap:wrap;justify-content:center}
/* A behaviour's choice of view (the tetrahedron's magnetic encoding): one row of radio buttons beside its actions. */
.cad-options {display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:0 16px;margin:0;padding:0;border:0;font-size:var(--text-support)}
.cad-options legend {float:left;margin:0 4px 0 0;padding:0;font-weight:600}
.cad-options label {display:flex;align-items:center;gap:8px;min-height:44px;cursor:pointer;white-space:nowrap}
.cad-options input {margin:0;accent-color:var(--blue)}
.cad-explode {display:flex;align-items:center;gap:10px;font-size:var(--text-support)}
.cad-explode input {min-height:44px;min-width:160px;accent-color:var(--blue)}
.cad-explode output {font-variant-numeric:tabular-nums;min-width:3.2em}
.cad-behaviour {margin:16px 0 0;border:1px solid var(--line);padding:16px}
.cad-behaviour-title {margin:0 0 12px;font-size:var(--text-support);font-weight:600}
.cad-behaviour-status {margin:0 0 12px;font-size:var(--text-support);line-height:1.4;color:var(--muted)}
.cad-behaviour-actions {display:flex;flex-wrap:wrap;gap:8px}
/* A behaviour's joint sliders (the Warman crane): a label, the slider and its reading per row, two rows side by side where there is room. */
.cad-joints {display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:0 20px;margin:0 0 12px}
.cad-joints label {display:flex;align-items:center;gap:10px;font-size:var(--text-support)}
.cad-joints span {min-width:6.5em}
.cad-joints input {flex:1;min-width:0;min-height:44px;accent-color:var(--blue)}
.cad-joints output {min-width:4em;text-align:right;font-variant-numeric:tabular-nums}
.cad-status {font-size:var(--text-support);line-height:1.4;color:var(--muted);margin:8px 0 0;min-height:1.4em;text-align:center}
.cad-viewer figcaption {margin-top:12px;text-align:center}

/* 13 · Responsive. One block per breakpoint, widest first, so narrower blocks win. */
@media(max-width:760px) {
  html {scroll-padding-top:20px}
  .fragment-alias {scroll-margin-top:20px}
  /* The view cube shrinks with the stage; cad-viewcube.js reads this same value. */
  .cad-viewer,.cad-switch {--cad-cube-size:88px;--cad-cube-margin:8px}
  /* No room under the cube on a phone-sized stage: the model buttons sit above the stage instead. */
  .cad-switcher {position:static;grid-area:1 / 1;flex-direction:row;flex-wrap:wrap;justify-content:center;gap:0 16px;margin:0 0 4px;padding:0;border:0;background:none}
  .cad-switcher label {min-height:44px}
  /* The joint sliders get the row's width: the label goes above its slider and reading. */
  .cad-joints label {flex-wrap:wrap;gap:0 10px}
  .cad-joints span {flex-basis:100%;min-width:0;margin-top:4px}
  .cad-home {width:30px;height:30px}
  .cad-home svg {width:17px;height:17px}
  /* Header becomes a brand row plus a two-column link grid with 44px targets. */
  .site-header {display:block;position:relative;gap:10px;padding:12px 20px 16px}
  .site-header .brand {display:inline-flex;align-items:center;min-height:44px;margin-bottom:8px}
  .site-header .brand,.site-header .brand-inactive {white-space:normal;max-width:100%}
  .site-header nav {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;width:100%}
  .site-header nav a {justify-content:center;text-align:center;min-height:44px;padding:10px 8px;font-family:var(--display);font-size:var(--text-support);font-weight:400;line-height:1.4;letter-spacing:0;text-transform:none;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--wash)}
  .site-header nav a+a::before {display:none}
  .site-header nav a[aria-current="location"] {background:var(--blue);color:var(--paper);border:1px solid var(--blue);box-shadow:inset 0 -3px var(--accent);font-weight:600}
  .site-header nav a:hover,.site-header nav a:focus-visible {border-color:var(--accent)}
  /* Homepage */
  .design-process {flex-direction:column;align-items:center;gap:8px;margin-bottom:28px}
  .design-process li+li::before {content:"↓";display:inline-block;width:16px;margin-right:8px}
  .title-grid,.credentials {grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(4,auto)}
  .title-grid>div:nth-child(3),.credentials>div:nth-child(3) {border-left:0}
  .title-grid>div:nth-child(n+3) {border-top:1px solid var(--line-on-blue)}
  .credentials>div:nth-child(n+3) {border-top:1px solid var(--line)}
  .featured-card .card-link {grid-template-columns:1fr}
  .featured-card figure {width:100%}
  .document-actions .button {max-width:100%}
  .site-footer .foot-note>span:last-child {text-align:left}
  /* Project pages */
  .project-hero,.media-row,.media-row.media-first {grid-template-columns:1fr;gap:24px}
  .body-aligned {row-gap:16px}
  .media-first .row-media,.media-first .row-copy {grid-column:auto;grid-row:auto}
  .body-aligned>.row-heading,.body-aligned>.row-copy,.body-aligned>.row-media,.body-aligned.media-first>.row-heading,.body-aligned.media-first>.row-copy,.body-aligned.media-first>.row-media {grid-column:1;grid-row:auto}
  .warman-page .heading-full-width>.row-heading {grid-column:1}
  .warman-page .body-aligned.media-first {grid-template-columns:1fr}
  .warman-page .body-aligned:not(.media-first) .row-media video {width:75.875%;margin-inline:auto;display:block}
  .project-hero .hero-media img {max-height:380px}
  .gallery {grid-template-columns:1fr}
  .gallery img,.gallery .motion video {height:auto;max-height:600px}
  .carousel.is-ready {--slide-max-height:360px}
  .carousel.is-ready img {max-height:360px}
  .carousel.is-ready .motion video {height:320px}
  .project-page .source-section.project-gallery {padding-top:20px}
  .project-nav {flex-direction:column;gap:12px;margin:24px 20px;padding:24px 0 0}
  .project-nav a {max-width:100%;width:100%}
  .project-nav a[rel="next"] {margin:0;justify-content:flex-end}
  .calculation-results {grid-template-columns:1fr;gap:12px}
  .model-layout {grid-template-columns:1fr;gap:20px}
  .model-plots {grid-template-columns:1fr}
  .image-viewer .viewer-controls {flex-wrap:wrap}
}
@media(max-width:640px) {
  :root {--frame:12px}
  .zones,.footer-zone {display:none}
  .home-intro h1 {margin:0 0 28px}
  .revtable th,.revtable td {padding:8px 5px;overflow-wrap:anywhere}
  .revtable td:nth-child(2) {white-space:normal;min-width:4.5em}
  .revtable thead th {font-size:var(--text-label);letter-spacing:0}
}
@media(max-width:480px) {
  .image-viewer {padding:12px}
  .image-viewer .viewer-controls {gap:12px}
}
@media(max-width:380px) {
  .title-grid,.credentials {grid-template-columns:1fr;grid-template-rows:repeat(8,auto)}
  .title-grid>div+div,.credentials>div+div {border-left:0}
}

/* 14 · Reduced motion: no smooth scrolling, transitions or loading pulses (video autoplay is handled in media.js). */
@media(prefers-reduced-motion:reduce) {
  html {scroll-behavior:auto}
  *,*:before,*:after {transition:none!important;animation:none!important}
}
