/* ==========================================================================
   Dex Cimino — Portfolio V30
   Theming rule: every accent-tinted graphic is a CSS mask painted with
   background-color. No filter() color hacks — masks give the exact hex and
   background-color transitions cleanly (no mid-transition color flash).
   ========================================================================== */

:root{
  --accent:#9EE02B;
  --page-bg:#0b0d12; /* base dark: page fill, .bg base, and the docked hex rim */
  --sidebar-bg:#090c11;
  --panel:#151a1f;
  --line:rgba(255,255,255,.11);
  --muted:#aeb6bd;
  --icon-idle:#8d959c;
  --text:#f1f3f4;
  --gutter:clamp(92px,11.2vw,190px); /* hero copy's left edge; every section below aligns to it */
  --sidebar:72px;
  --sidebar-open:238px;
  --radius:18px;
  --copy-size:18px;
  --accent-ease:.26s cubic-bezier(.22,.61,.36,1);
  --swatch:34px;
  --swatch-step:40px;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth;background:var(--page-bg);color-scheme:dark}
/* body must NOT paint a background: it would cover the fixed .bg layer
   (body backgrounds paint above negative-z-index children). html owns the fill. */
body{margin:0;color:var(--text);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;overflow-x:hidden}
a{color:inherit;text-decoration:none}
button{font:inherit}
img{max-width:100%}
::selection{background:rgba(255,255,255,.18);color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:6px}
.skip-link{position:fixed;top:-60px;left:12px;z-index:200;padding:10px 16px;border-radius:8px;background:var(--accent);color:var(--accent-ink,#080a0b);font-size:12px;font-weight:900;letter-spacing:.06em;transition:top .2s ease}
.skip-link:focus{top:12px}

/* ==========================================================================
   ICON SYSTEM
   One mechanism for every SVG that needs to take a color. The mask carries the
   shape, background-color carries the color, so the color is always exact.
   Asset paths live here (not in inline styles) so they resolve off this file.
   ========================================================================== */
.icon{
  display:block;
  flex:0 0 auto;
  background-color:currentColor;
  -webkit-mask:var(--icon) center / contain no-repeat;
  mask:var(--icon) center / contain no-repeat;
  /* Color is driven by whatever owns `color` above this node, so the accent
     crossfade stays one easing curve instead of two chained ones. */
  transition:transform .2s cubic-bezier(.22,.61,.36,1),opacity .2s ease;
}

/* Masks are baked as data: URIs because mask-image is CORS-fetched — external
   URLs silently fail when the site is opened via file:// (double-click).
   The SVG files in assets/ are still the masters: edit one, then run
   `python tools/bake_icons.py` to regenerate this block. */
/* >>> GENERATED ICONS — do not edit by hand.
   Source SVGs listed per line; regenerate with: python tools/bake_icons.py >>> */
:root{--cimino-mask:url("data:image/svg+xml,%3Csvg id='Layer_2' data-name='Layer 2' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 301.5547 31.6781'%3E %3Cg id='Layer_1-2' data-name='Layer 1'%3E %3Cg%3E %3Cpath d='M27.9941,31.2484H7.8418c-.5156,0-1.0708-.0605-1.665-.1826-.5947-.1216-1.1816-.3115-1.7617-.5693s-1.1353-.5908-1.665-.999c-.5303-.4082-.999-.9023-1.4072-1.4824s-.7344-1.2529-.9775-2.0195c-.2437-.7661-.3652-1.6289-.3652-2.5889v-15.125c0-.5156.0605-1.0703.1826-1.665.1216-.5942.3115-1.1816.5693-1.7617s.5942-1.1348,1.0098-1.665c.415-.5298.9131-.999,1.4932-1.4072s1.2495-.7339,2.0088-.9775c.7588-.2432,1.6182-.3652,2.5781-.3652h20.1523v5.5859H7.8418c-.7305,0-1.2891.1934-1.6758.5801s-.5801.96-.5801,1.7188v15.082c0,.7163.1968,1.2715.5908,1.665.3936.394.9487.5908,1.665.5908h20.1523v5.5859Z' fill='%23fff'/%3E %3Cpath d='M65.3081,31.2484h-5.5859V.4398h5.5859v30.8086Z' fill='%23fff'/%3E %3Cpath d='M134.0967,31.2484h-5.6289V12.9008l-9.9043,17.4238c-.2437.4443-.584.7808-1.0205,1.0098-.437.229-.9062.3438-1.4072.3438-.4873,0-.9419-.1147-1.3643-.3438-.4229-.229-.7559-.5654-.999-1.0098l-9.9473-17.4238v18.3477h-5.5859V2.8246c0-.6445.1895-1.2173.5693-1.7188.3794-.501.877-.8379,1.4932-1.0098.3008-.0713.6016-.0967.9023-.0752s.5908.0859.8701.1934.5332.2578.7627.4512c.229.1934.4224.4263.5801.6982l12.7188,22.1074,12.7188-22.1074c.3291-.5439.7842-.9307,1.3643-1.1602.5801-.229,1.1851-.2646,1.8154-.1074.6016.1719,1.0957.5088,1.4824,1.0098.3867.5015.5801,1.0742.5801,1.7188v28.4238Z' fill='%23fff'/%3E %3Cpath d='M172.6143,31.2484h-5.5859V.4398h5.5859v30.8086Z' fill='%23fff'/%3E %3Cpath d='M236.3325,28.8637c0,.4014-.0752.7734-.2256,1.1172s-.3511.6411-.6016.8916c-.251.251-.5479.4473-.8916.5908-.3438.1431-.709.2148-1.0957.2148-.3438,0-.6914-.0645-1.042-.1934-.3511-.1289-.6626-.3364-.9346-.623l-20.4102-21.3125v21.6992h-5.5859V2.8246c0-.5728.1611-1.0918.4834-1.5576.3223-.4653.7339-.8125,1.2354-1.042.5298-.2148,1.0742-.2686,1.6328-.1611s1.0381.3691,1.4395.7842l20.4102,21.291V.4398h5.5859v28.4238Z' fill='%23fff'/%3E %3Cpath d='M301.5547,18.7875c0,1.8765-.3223,3.6025-.9668,5.1777-.6445,1.5757-1.54,2.9365-2.6855,4.082s-2.5029,2.0376-4.0713,2.6748-3.2764.9561-5.124.9561h-7.5625c-1.8477,0-3.5596-.3188-5.1348-.9561-1.5757-.6372-2.9365-1.5288-4.082-2.6748-1.146-1.1455-2.0449-2.5063-2.6963-4.082-.6519-1.5752-.9775-3.3013-.9775-5.1777v-5.8867c0-1.8618.3257-3.584.9775-5.167.6514-1.5825,1.5503-2.9434,2.6963-4.082,1.1455-1.1387,2.5063-2.0303,4.082-2.6748,1.5752-.6445,3.2871-.9668,5.1348-.9668h7.5625c1.8477,0,3.5557.3223,5.124.9668s2.9253,1.5361,4.0713,2.6748c1.1455,1.1387,2.041,2.4995,2.6855,4.082.6445,1.583.9668,3.3052.9668,5.167v5.8867ZM295.9688,12.9008c0-1.1025-.1758-2.1016-.5264-2.9971-.3511-.895-.8452-1.6611-1.4824-2.2988-.6377-.6372-1.4038-1.1313-2.2988-1.4824-.8955-.3506-1.8799-.5264-2.9541-.5264h-7.5625c-1.0889,0-2.0806.1758-2.9756.5264-.8955.3511-1.665.8452-2.3096,1.4824-.6445.6377-1.1426,1.4038-1.4932,2.2988-.3511.8955-.5264,1.8945-.5264,2.9971v5.8867c0,1.103.1753,2.1021.5264,2.9971.3506.8955.8486,1.6616,1.4932,2.2988.6445.6377,1.4141,1.1318,2.3096,1.4824.895.3511,1.8867.5264,2.9756.5264h7.5195c1.0884,0,2.0801-.1753,2.9756-.5264.895-.3506,1.665-.8447,2.3096-1.4824.6445-.6372,1.1421-1.4033,1.4932-2.2988.3506-.895.5264-1.894.5264-2.9971v-5.8867Z' fill='%23fff'/%3E %3C/g%3E %3C/g%3E %3C/svg%3E")} /* src: assets/logos/CIMINO.svg */
[data-icon="brand"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cpath fill='%23fff' d='M15 7h27l15 25-15 25H15L4 45l9-7 8 9h15l9-15-9-15H21l-8 9-9-7Z'/%3E%3C/svg%3E")} /* src: assets/icons/brand-mark.svg */
[data-icon="home"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M3 10.5 12 3l9 7.5v10a.5.5 0 0 1-.5.5H15v-7H9v7H3.5a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E")} /* src: assets/icons/home.svg */
[data-icon="work"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M4 4h6v6H4zm10 0h6v6h-6zM4 14h6v6H4zm10 0h6v6h-6z'/%3E%3C/svg%3E")} /* src: assets/icons/work.svg */
[data-icon="games"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' fill-rule='evenodd' d='M8.55 6.4h6.9a6.75 6.75 0 0 1 6.62 5.45l.66 3.36a3.2 3.2 0 0 1-5.72 2.5l-1.4-1.86H8.39l-1.4 1.86a3.2 3.2 0 0 1-5.72-2.5l.66-3.36A6.75 6.75 0 0 1 8.55 6.4Zm-1.4 3.15v1.6h-1.6v1.9h1.6v1.6h1.9v-1.6h1.6v-1.9h-1.6v-1.6h-1.9Zm9.1.3a1.35 1.35 0 1 0 0 2.7 1.35 1.35 0 0 0 0-2.7Zm2.6 2.75a1.35 1.35 0 1 0 0 2.7 1.35 1.35 0 0 0 0-2.7Z'/%3E%3C/svg%3E")} /* src: assets/icons/games.svg */
[data-icon="ai"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='m12 2 1.5 5.1L18 9l-4.5 1.9L12 16l-1.5-5.1L6 9l4.5-1.9ZM5 13l1 3 3 1-3 1-1 3-1-3-3-1 3-1Zm14-1 1 2 2 1-2 1-1 2-1-2-2-1 2-1Z'/%3E%3C/svg%3E")} /* src: assets/icons/ai.svg */
[data-icon="about"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM5 20a7 7 0 0 1 14 0Z'/%3E%3C/svg%3E")} /* src: assets/icons/about.svg */
[data-icon="resume"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='1.8' stroke-linejoin='round' d='M6 2h8l4 4v16H6zm8 0v5h4M9 11h6M9 15h6M9 19h4'/%3E%3C/svg%3E")} /* src: assets/icons/resume.svg */
[data-icon="contact"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' d='M4 5h16v11H8l-4 3V5Zm3 4h10M7 12h7'/%3E%3C/svg%3E")} /* src: assets/icons/contact.svg */
[data-icon="download"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M12 3v12m-5-5 5 5 5-5M5 20h14'/%3E%3C/svg%3E")} /* src: assets/icons/download.svg */
[data-icon="arrow-ne"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E")} /* src: assets/icons/arrow-ne.svg */
[data-icon="arrow-right"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' d='M4 12h15M13 6l6 6-6 6'/%3E%3C/svg%3E")} /* src: assets/icons/arrow-right.svg */
[data-icon="tick"]{--icon:url("data:image/svg+xml,%3Csvg id='Layer_2' data-name='Layer 2' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 15.3841 18.1113'%3E %3Cg id='Layer_1-2' data-name='Layer 1'%3E %3Cpath d='M7.1872,18.1113H0v-6.3529L11.7584,0h3.6257v7.3476s-5.9188,5.7103-7.2664,7.2664-.9305,3.4973-.9305,3.4973Z' fill='%23fff'/%3E %3C/g%3E %3C/svg%3E")} /* src: assets/icons/tick_mark.svg */
[data-icon="play"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' stroke='%23fff' stroke-width='3.4' stroke-linejoin='round' d='M8.4 5.9v12.2L18.2 12Z'/%3E%3C/svg%3E")} /* src: assets/icons/play.svg */
[data-icon="youtube"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' fill-rule='evenodd' d='M23.5 6.19a3.02 3.02 0 0 0-2.12-2.14C19.5 3.54 12 3.54 12 3.54s-7.5 0-9.38.51A3.02 3.02 0 0 0 .5 6.19C0 8.07 0 12 0 12s0 3.93.5 5.81a3.02 3.02 0 0 0 2.12 2.14c1.88.51 9.38.51 9.38.51s7.5 0 9.38-.51a3.02 3.02 0 0 0 2.12-2.14C24 15.93 24 12 24 12s0-3.93-.5-5.81ZM9.55 15.57V8.43L15.82 12l-6.27 3.57Z'/%3E%3C/svg%3E")} /* src: assets/icons/social/youtube.svg */
[data-icon="instagram"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' fill-rule='evenodd' d='M12 2.16c3.2 0 3.58.01 4.85.07 1.17.05 1.8.25 2.23.41.56.22.96.48 1.38.9.42.42.68.82.9 1.38.16.42.36 1.06.41 2.23.06 1.27.07 1.65.07 4.85s-.01 3.58-.07 4.85c-.05 1.17-.25 1.8-.41 2.23-.22.56-.48.96-.9 1.38-.42.42-.82.68-1.38.9-.42.16-1.06.36-2.23.41-1.27.06-1.65.07-4.85.07s-3.58-.01-4.85-.07c-1.17-.05-1.8-.25-2.23-.41-.56-.22-.96-.48-1.38-.9-.42-.42-.68-.82-.9-1.38-.16-.42-.36-1.06-.41-2.23-.06-1.27-.07-1.65-.07-4.85s.01-3.58.07-4.85c.05-1.17.25-1.8.41-2.23.22-.56.48-.96.9-1.38.42-.42.82-.68 1.38-.9.42-.16 1.06-.36 2.23-.41C8.42 2.17 8.8 2.16 12 2.16ZM12 0C8.74 0 8.33.01 7.05.07c-1.28.06-2.15.26-2.91.56-.79.3-1.46.72-2.13 1.38C1.35 2.68.93 3.35.63 4.14c-.3.76-.5 1.63-.56 2.91C.01 8.33 0 8.74 0 12s.01 3.67.07 4.95c.06 1.28.26 2.15.56 2.91.3.79.72 1.46 1.38 2.13.67.67 1.34 1.08 2.13 1.38.76.3 1.63.5 2.91.56C8.33 23.99 8.74 24 12 24s3.67-.01 4.95-.07c1.28-.06 2.15-.26 2.91-.56.79-.3 1.46-.71 2.13-1.38.67-.67 1.08-1.34 1.38-2.13.3-.76.5-1.63.56-2.91.06-1.28.07-1.69.07-4.95s-.01-3.67-.07-4.95c-.06-1.28-.26-2.15-.56-2.91-.3-.79-.71-1.46-1.38-2.13C21.32 1.35 20.65.93 19.86.63c-.76-.3-1.63-.5-2.91-.56C15.67.01 15.26 0 12 0Zm0 5.84a6.16 6.16 0 1 0 0 12.32 6.16 6.16 0 0 0 0-12.32ZM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8Zm7.85-10.41a1.44 1.44 0 1 1-2.88 0 1.44 1.44 0 0 1 2.88 0Z'/%3E%3C/svg%3E")} /* src: assets/icons/social/instagram.svg */
[data-icon="linkedin"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' fill-rule='evenodd' d='M22.23 0H1.77C.79 0 0 .77 0 1.73v20.54C0 23.23.79 24 1.77 24h20.46c.98 0 1.77-.77 1.77-1.73V1.73C24 .77 23.21 0 22.23 0ZM7.12 20.45H3.56V9h3.56v11.45ZM5.34 7.43a2.06 2.06 0 1 1 0-4.13 2.06 2.06 0 0 1 0 4.13Zm15.11 13.02h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.42v1.56h.05c.47-.9 1.63-1.85 3.37-1.85 3.6 0 4.26 2.37 4.26 5.46v6.28Z'/%3E%3C/svg%3E")} /* src: assets/icons/social/linkedin.svg */
[data-icon="github"]{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' fill-rule='evenodd' d='M12 .3a12 12 0 0 0-3.79 23.39c.6.11.82-.26.82-.58l-.02-2.04c-3.34.73-4.04-1.6-4.04-1.6-.55-1.39-1.34-1.76-1.34-1.76-1.08-.75.08-.73.08-.73 1.21.09 1.84 1.24 1.84 1.24 1.07 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.13-.3-.54-1.52.11-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.28-1.23 3.28-1.23.65 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.81 5.62-5.48 5.92.43.36.81 1.1.81 2.22l-.01 3.29c0 .31.21.69.82.57A12 12 0 0 0 12 .3Z'/%3E%3C/svg%3E")} /* src: assets/icons/social/github.svg */
/* <<< GENERATED ICONS <<< */

/* ==========================================================================
   BACKGROUND — flat diagonal composition (per reference)
   position:absolute (not fixed) so the whole scene scrolls with the page.
   All shapes are FLAT solid colors at -28°. Grays are theme-constant; the
   accent wedge is pure var(--accent) so it exactly matches every other accent
   element and crossfades on theme change.
   The accent wedge is anchored to the TOP-RIGHT: its top edge is the line from
   (100vw, 92px) descending left at 28°. The hero's front band reuses the same
   anchor so both stay colinear at any viewport width.
   ========================================================================== */
.bg{position:absolute;inset:0;overflow:hidden;z-index:-5;background:var(--page-bg);pointer-events:none}
/* Front wedge shares .bg's box exactly (both absolute/inset:0 against the ICB)
   and the same viewBox, so the two lime shapes can never drift apart. z -2 puts
   it over the mascot (-3) but still under every in-flow section. */
.bg-front{position:absolute;inset:0;overflow:hidden;z-index:-3;pointer-events:none}
.bg svg,.bg-front svg{position:absolute;inset:0;width:100%;height:100%;display:block;isolation:isolate}
/* Every lime stop in both layers. One declaration = one crossfade, same as the
   mask-and-background-color trick used everywhere else. */
.accent-stop{stop-color:var(--accent);transition:stop-color var(--accent-ease)}
.grain{position:absolute;inset:0;opacity:.035;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.45'/%3E%3C/svg%3E");background-size:180px 180px}

/* ==========================================================================
   SIDEBAR
   Icons inherit the link's `color`, so hover/active/accent changes are one
   color transition instead of four separate rules.
   ========================================================================== */
.sidebar{position:fixed;inset:0 auto 0 0;width:var(--sidebar);z-index:30;background:var(--sidebar-bg);border-right:1px solid color-mix(in srgb,var(--accent) 62%,transparent);transition:width .24s cubic-bezier(.22,.61,.36,1),border-color var(--accent-ease);overflow:hidden;display:flex;flex-direction:column}
.sidebar:hover,.sidebar:focus-within{width:var(--sidebar-open)}

.brand{height:86px;display:grid;place-items:center;border-bottom:1px solid var(--line);color:var(--accent);transition:color var(--accent-ease)}
.brand-mark{width:38px;height:38px}
.brand:hover .brand-mark{transform:scale(1.08)}

.nav{padding:18px 0;display:grid;gap:4px}
.nav-link,.resume-mini,.contact-mini{
  height:54px;display:flex;align-items:center;gap:18px;padding:0 22px;
  white-space:nowrap;color:var(--icon-idle);position:relative;
  transition:color var(--accent-ease),background var(--accent-ease);
}
.nav-icon{width:24px;height:24px}
.nav-trail{width:15px;height:15px;margin-left:auto;opacity:0;transform:translateX(-6px)}
.nav-text{opacity:0;transform:translateX(-8px);transition:opacity .2s ease,transform .2s ease;text-transform:uppercase;letter-spacing:.06em;font-weight:750;font-size:14px;color:#c3cad0}
.sidebar:hover .nav-text,.sidebar:focus-within .nav-text{opacity:1;transform:none}
.sidebar:hover .nav-trail,.sidebar:focus-within .nav-trail{opacity:.75;transform:none}

.nav-link:hover,.nav-link.active,
.resume-mini:hover,.resume-mini.active,
.contact-mini:hover{color:var(--accent);background:color-mix(in srgb,var(--accent) 7%,transparent)}
.nav-link:hover .nav-text,.nav-link.active .nav-text,
.resume-mini:hover .nav-text,.resume-mini.active .nav-text,
.contact-mini:hover .nav-text{color:var(--accent)}
.nav-link:hover .nav-icon,.nav-link.active .nav-icon,
.resume-mini:hover .nav-icon,.contact-mini:hover .nav-icon{transform:scale(1.06)}
.resume-mini:hover .nav-trail{opacity:1;transform:translateY(2px)}
.nav-link.active::after,.resume-mini.active::after{content:"";position:absolute;right:0;top:8px;bottom:8px;width:3px;background:var(--accent);transition:background-color var(--accent-ease)}

.side-bottom{margin-top:auto;border-top:1px solid var(--line)}
.contact-mini{border-top:1px solid rgba(255,255,255,.07);border-bottom:1px solid rgba(255,255,255,.07)}
.profile-mini{min-height:136px;padding:14px 16px 13px;display:flex;flex-direction:column;justify-content:center;gap:12px;white-space:nowrap}
.profile-mini .profile-photo{width:42px;height:42px;min-width:42px;border-radius:11px;object-fit:cover;border:1px solid var(--line)}
.profile-mini strong{font-size:14px;letter-spacing:.025em;color:var(--accent);transition:color var(--accent-ease)}
.profile-mini small{font-size:12px;letter-spacing:.025em;color:var(--muted)}
.profile-row{display:flex;align-items:center;gap:14px}
.profile-copy{display:grid;gap:4px;opacity:0;transform:translateX(-7px);transition:opacity .2s ease,transform .2s ease}
.sidebar:hover .profile-copy,.sidebar:focus-within .profile-copy{opacity:1;transform:none}

.social-mini{width:100%;display:grid;grid-template-columns:repeat(4,1fr);align-items:center;gap:6px;opacity:0;transform:translateY(5px);transition:opacity .2s ease,transform .2s ease;pointer-events:none}
.sidebar:hover .social-mini,.sidebar:focus-within .social-mini{opacity:1;transform:none;pointer-events:auto}
.social-mini a{height:30px;display:grid;place-items:center;border-radius:8px;color:var(--icon-idle);transition:background var(--accent-ease),color var(--accent-ease),transform .18s ease}
.social-mini a:hover{background:color-mix(in srgb,var(--accent) 10%,transparent);color:var(--accent);transform:translateY(-2px)}
.social-mini .icon{width:17px;height:17px}

/* ==========================================================================
   SHELL
   ========================================================================== */
.site-shell{margin-left:var(--sidebar);min-height:100vh}
.topbar{height:62px;display:flex;align-items:center;justify-content:flex-end;padding:0 clamp(24px,4vw,72px);position:relative;z-index:10}

/* ==========================================================================
   ACCENT PICKER
   Two states: an inline horizontal row at the top of the page, and a docked
   vertical disclosure once that row scrolls away. In docked mode the active
   hex is the toggle; the rest cascade out of it, offset by --row.
   ========================================================================== */
.accent-picker{position:relative;display:flex;align-items:center;gap:12px;transform:translate(-18px,13px);z-index:60}
.accent-label{font-size:12px;color:#aab1b7;letter-spacing:.13em;white-space:nowrap;transition:opacity .18s ease}
.accent-swatches{display:flex;align-items:center;gap:6px}

.swatch{
  width:var(--swatch);height:var(--swatch);padding:0;border:0;background:none;cursor:pointer;
  display:grid;place-items:center;
  transition:transform var(--accent-ease),opacity .2s ease;
}
.swatch svg{display:block;width:100%;height:100%;overflow:visible;transition:transform .34s cubic-bezier(.22,.61,.36,1)}
/* Widths are user units (CSS px == user units inside the viewBox), so the whole
   swatch scales with --swatch instead of needing non-scaling-stroke. */
.swatch path{transition:fill .2s ease,stroke .2s ease,stroke-width .2s ease}
/* Outer perimeter rim — off by default (the inline row sits on the dark
   topbar), switched on for the docked toggle below. Never filled. */
.swatch .halo{fill:none;stroke:var(--page-bg);stroke-width:0}
.swatch:hover{transform:scale(1.18)}
.swatch:focus-visible{outline:2px solid var(--text);outline-offset:3px;border-radius:6px}

/* --- docked (vertical) state --- */
@keyframes pickerDock{from{opacity:0;transform:translateY(-10px) scale(.9)}to{opacity:1;transform:none}}

/* padding widens the hover target so the pointer can travel down the open
   stack without leaving the picker and collapsing it */
.accent-picker.compact{position:fixed;top:2px;right:10px;padding:10px;transform:none;gap:0;z-index:90;animation:pickerDock .28s cubic-bezier(.22,.61,.36,1)}
.accent-picker.compact .accent-label{opacity:0;width:0;overflow:hidden;pointer-events:none}
.accent-picker.compact .accent-swatches{
  position:relative;gap:0;
  width:var(--swatch);height:var(--swatch);
  transition:height .32s cubic-bezier(.22,.61,.36,1);
}
/* Backing panel: fades in only while the stack is open. */
.accent-picker.compact .accent-swatches::before{
  content:"";position:absolute;inset:-10px;border-radius:24px;
  background:rgba(10,13,16,.82);
  border:1px solid color-mix(in srgb,var(--accent) 28%,transparent);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  opacity:0;transform:scaleY(.9);transform-origin:top;pointer-events:none;
  transition:opacity .22s ease,transform .3s cubic-bezier(.22,.61,.36,1),border-color var(--accent-ease);
}
.accent-picker.compact .swatch{
  position:absolute;top:0;left:0;
  opacity:0;pointer-events:none;transform:scale(.55);
  transition:transform .34s cubic-bezier(.22,.61,.36,1),opacity .2s ease;
}
.accent-picker.compact .swatch svg{transform:rotate(90deg)}
.accent-picker.compact .swatch.active{opacity:1;pointer-events:auto;transform:none;z-index:3}
/* Docked, the active hex is the only thing on screen and it lands right on the
   accent wedge — same color, so the ring alone disappears. The rim rides the
   larger RIM_R hexagon, so it hugs the ring's outer edge and adds nothing
   inside the hex. ~3px at the default 34px swatch. */
.accent-picker.compact .swatch.active .halo{stroke-width:7}

.accent-picker.compact.open .accent-swatches{height:calc(var(--swatch) + var(--rows,6) * var(--swatch-step))}
.accent-picker.compact.open .accent-swatches::before{opacity:1;transform:none}
.accent-picker.compact.open .swatch{
  opacity:1;pointer-events:auto;
  transform:translateY(calc(var(--row,0) * var(--swatch-step)));
  transition-delay:calc(var(--row,0) * 32ms);
}
.accent-picker.compact.open .swatch:hover{
  transform:translateY(calc(var(--row,0) * var(--swatch-step))) scale(1.18);
  transition-delay:0s;
}

/* ==========================================================================
   HERO
   ========================================================================== */
.hero{height:clamp(500px,55vh,575px);min-height:500px;position:relative;overflow:visible}
.hero-copy{position:absolute;z-index:5;left:var(--gutter);top:clamp(58px,7.8vh,82px);width:min(38vw,630px);max-width:630px}
.hero-name{display:flex;flex-direction:column;align-items:flex-start;width:max-content;line-height:1;margin:0}
/* Wordmarks are graphics, not content: CIMINO is a CSS mask and can't be
   dragged, so DEX is opted out too rather than behaving differently. */
.dex-wordmark,.cimino-sizer{-webkit-user-drag:none;user-select:none;-webkit-user-select:none}
.dex-wordmark{display:block;width:clamp(300px,22.6vw,380px);height:auto}

/* CIMINO: the <img> is an invisible sizer so the real SVG file stays the source
   of truth for aspect ratio; the overlay paints it with an exact-color mask. */
.cimino-wordmark-shell{position:relative;display:block;width:clamp(240px,18vw,302px);margin-top:clamp(26px,2.6vw,38px);margin-left:1px;line-height:0}
.cimino-sizer{display:block;width:100%;height:auto;visibility:hidden}
.cimino-fill{
  position:absolute;inset:0;
  background-color:var(--accent);
  -webkit-mask:var(--cimino-mask) center / contain no-repeat;
  mask:var(--cimino-mask) center / contain no-repeat;
  transition:background-color var(--accent-ease);
}

.roles{margin:28px 0 0;color:#b8c0c6;font-size:clamp(13px,1.02vw,16px);letter-spacing:.07em;line-height:1.5}
.roles b{color:#9ea7ae;padding:0 6px}
.hero-divider{width:86px;height:5px;margin:24px 0;border-radius:999px;background:linear-gradient(90deg,var(--accent) 0%,color-mix(in srgb,var(--accent) 55%,transparent) 52%,transparent 100%);transition:background var(--accent-ease)}
.intro{max-width:540px;color:#b8c0c6;line-height:1.68;font-size:clamp(16px,1.08vw,18px)}
.hero-actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:27px}

.button{display:inline-flex;align-items:center;justify-content:center;gap:11px;min-height:50px;padding:0 22px;border:1px solid rgba(255,255,255,.28);border-radius:8px;background:rgba(13,16,19,.72);font-size:14px;font-weight:900;letter-spacing:.04em;transition:border-color var(--accent-ease),transform .2s ease,box-shadow var(--accent-ease),background var(--accent-ease)}
.button:hover{border-color:var(--accent);transform:translateY(-2px)}
.button.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink,#080a0b);box-shadow:0 12px 32px color-mix(in srgb,var(--accent) 22%,transparent)}
.button.ghost{background:transparent}
.btn-icon{width:16px;height:16px}
/* Arrows kick up-and-right; the download glyph gets no transform of its own so
   it simply rides the button's -2px lift instead of cancelling it out. */
.button:hover .btn-icon:not(.btn-icon-down){transform:translate(2px,-2px)}

/* Decorative hero layers sit on NEGATIVE z so they paint below every in-flow
   section. `.hero` is position:relative with z-index:auto (no stacking context),
   so these join the root negative layer: above .bg (-5), below all page content.
   Without this they overflow the hero and cover the sections underneath. */
/* The mascot and the archer share one coordinate system: the archer's position
   and size are both expressed against the mascot's, so they scale and clamp
   together and he can never drift off the mascot's shoulder. */
.hero-art,.hero-archer,.hero-goblin,.hero-note{--mascot-x:clamp(555px,40.5vw,720px);--mascot-w:clamp(650px,47vw,800px)}
.hero-art{position:absolute;z-index:-4;top:-22px;left:var(--mascot-x);width:var(--mascot-w);height:650px;overflow:visible;pointer-events:none}
.hero-art img{position:absolute;left:0;top:0;width:100%;height:auto;max-width:none;object-fit:contain;object-position:top left}

/* Hero cast, back to front: mascot (-4), front wedge (-3), lava goblin (-2),
   bone archer (-1). All still behind every in-flow section. */
.hero-goblin{
  position:absolute;z-index:-2;pointer-events:none;
  /* Recedes off the right edge as the viewport narrows (browser zoom shrinks
     the CSS viewport), so he slides away instead of piling onto the archer.
     min() keeps the design offset on anything 1800px and wider. */
  right:min(calc(var(--mascot-w) * -.145),
            calc(var(--mascot-w) * -.145 - (1800px - 100vw) * .712));
  top:calc(-22px + var(--mascot-w) * .055);
  width:calc(var(--mascot-w) * .663);
}
.hero-goblin img{display:block;width:100%;height:auto;max-width:none}

/* Hand-drawn aside, sitting in the gap above the cast. z -1 with a later DOM
   position than the archer, so it annotates over all of them but still sits
   behind every in-flow section. Ink stays white so it reads on the dark slab
   whatever the accent is; only the tongue takes the accent. */
.hero-note{
  position:absolute;z-index:-1;pointer-events:none;
  /* Rides the mascot's coordinate system like the archer and goblin, so the
     whole cast scales and shifts together under browser zoom. */
  /* Rides the mascot so it moves with the cast under browser zoom, but is
     clamped so it can never be swallowed by the goblin, whose left edge sits at
     100% - mascot-w*.518 and closes in as the viewport narrows. */
  left:min(calc(var(--mascot-x) + var(--mascot-w) * .849),
           calc(100% - var(--mascot-w) * .648));
  top:calc(-22px + var(--mascot-w) * .1038);
  width:calc(var(--mascot-w) * .195);
}
.hero-note svg{display:block;width:100%;height:auto;overflow:visible}
.note-ink{fill:var(--icon-idle);opacity:.5}  /* static gray, knocked back; the face stays full-strength accent */
.note-face{fill:var(--accent);transition:fill var(--accent-ease)}

.hero-archer{
  position:absolute;z-index:-1;pointer-events:none;
  left:calc(var(--mascot-x) + var(--mascot-w) * .668);
  top:calc(-22px + var(--mascot-w) * .241);
  width:calc(var(--mascot-w) * .423);
}
.hero-archer img{display:block;width:100%;height:auto;max-width:none;animation:archerBob 4.6s ease-in-out infinite}
@keyframes archerBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-15px)}}

/* ==========================================================================
   FEATURED WORK
   ========================================================================== */
.section{padding:90px var(--gutter);background:linear-gradient(180deg,rgba(8,10,12,.84),rgba(8,10,12,.96))}
.home-featured{padding:10px var(--gutter) 60px;background:linear-gradient(180deg,rgba(9,12,15,.88),rgba(8,10,12,.96))}
.section-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}
/* .section-head scope needed to outrank the big `.section-head h2` heading rule */
.section-head .featured-title{display:flex;align-items:center;gap:9px;margin:0;font-size:clamp(20px,1.5vw,23px);font-weight:700;letter-spacing:.02em;line-height:1}
.featured-mark{width:13px;height:17px;color:var(--accent);transition:color var(--accent-ease)}
.view-all{display:inline-flex;align-items:center;gap:9px;font-size:14px;color:var(--accent);font-weight:900;letter-spacing:.08em;transition:color var(--accent-ease)}
.view-all-arrow{width:14px;height:14px}
.view-all:hover .view-all-arrow{transform:translateX(4px)}

.work-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}
.work-card{height:clamp(200px,24vh,258px);position:relative;border-radius:14px;overflow:hidden;border:1px solid rgba(255,255,255,.13);background:#11161a;isolation:isolate}
.work-card img{width:100%;height:100%;object-fit:cover;transition:transform .55s cubic-bezier(.22,.61,.36,1)}
.work-card:hover img{transform:scale(1.045)}
.brand-card img{object-fit:contain;padding:22px;background:linear-gradient(140deg,#11161a,#20272d)}
.concept-card{background:linear-gradient(150deg,#1b212a 0%,#0e1216 70%)}
.concept-mark{position:absolute;inset:0;margin:auto;width:74px;height:74px;color:var(--accent);opacity:.4;transition:color var(--accent-ease),transform .55s cubic-bezier(.22,.61,.36,1)}
.concept-card:hover .concept-mark{transform:scale(1.08)}
.card-shade{position:absolute;inset:42% 0 0;background:linear-gradient(transparent,rgba(2,3,4,.94))}
.card-meta{position:absolute;left:16px;right:40px;bottom:14px}
.card-meta small{color:var(--accent);font-weight:900;font-size:12px;letter-spacing:.13em;transition:color var(--accent-ease)}
.card-meta h3{font-size:19px;margin:5px 0 0;letter-spacing:.01em}
.card-go{position:absolute;right:14px;bottom:15px;width:14px;height:14px;color:var(--text);opacity:.75}
.work-card:hover .card-go{opacity:1;transform:translate(2px,-2px)}

/* ==========================================================================
   LOWER SECTIONS
   ========================================================================== */
.eyebrow{color:var(--accent);font-size:15px;font-weight:900;letter-spacing:.2em;margin:0 0 12px;text-transform:uppercase;transition:color var(--accent-ease)}
.section-head h2,.statement h2,.about h2,.resume-strip h2{font-size:clamp(32px,4vw,64px);line-height:.95;margin:0;letter-spacing:-.045em}
.split-section{padding:110px var(--gutter);display:grid;grid-template-columns:.72fr 1.28fr;gap:clamp(40px,8vw,130px);background:rgba(14,17,20,.91);border-top:1px solid var(--line)}
.split-section.alt{background:rgba(8,10,12,.96)}
.statement p:last-child,.about-copy>p:not(.eyebrow){max-width:650px;color:#adb5bb;line-height:1.72;font-size:var(--copy-size)}

.stack{border-top:1px solid var(--line)}
.stack-row{display:grid;grid-template-columns:44px 1fr 160px 30px;align-items:center;min-height:86px;border-bottom:1px solid var(--line);transition:background .2s ease,padding .2s ease;padding:0 12px}
.stack-row span{color:var(--accent);font-size:13px;transition:color var(--accent-ease)}
.stack-row strong{font-size:25px}
.stack-row small{color:#959ea5;font-size:15px}
.row-arrow{width:21px;height:21px;color:var(--accent);transition:color var(--accent-ease),transform .2s ease}
.stack-row:hover{background:rgba(255,255,255,.04);padding-left:20px}
.stack-row:hover .row-arrow{transform:translate(2px,-2px)}

.ai-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.ai-card{min-height:190px;border:1px solid var(--line);border-radius:14px;background:linear-gradient(145deg,rgba(35,41,46,.83),rgba(12,15,18,.82));padding:24px;display:flex;flex-direction:column;justify-content:flex-end;position:relative;overflow:hidden;transition:transform .25s ease,border-color var(--accent-ease)}
.ai-card:before{content:"";position:absolute;right:-18%;top:-44%;width:70%;aspect-ratio:1;background:var(--accent);filter:blur(70px);opacity:.08;transition:background-color var(--accent-ease)}
.ai-card:hover{transform:translateY(-4px);border-color:color-mix(in srgb,var(--accent) 55%,transparent)}
.ai-card small{color:var(--accent);font-weight:900;font-size:12px;letter-spacing:.13em;transition:color var(--accent-ease)}
.ai-card strong{font-size:25px;margin:8px 0}
.ai-card>span{color:#9da5ab;font-size:12px;display:inline-flex;align-items:center;gap:6px}
.inline-arrow{width:13px;height:13px}
.ai-card:hover .inline-arrow{transform:translate(2px,-2px)}

.about{padding:110px var(--gutter);display:grid;grid-template-columns:minmax(260px,420px) minmax(300px,700px);align-items:center;gap:clamp(40px,7vw,110px);background:#0b0e11}
.about-photo{aspect-ratio:1;border-radius:28px;overflow:hidden;position:relative;border:1px solid var(--line)}
.about-photo:after{content:"";position:absolute;inset:auto 0 0;height:7px;background:var(--accent);transition:background-color var(--accent-ease)}
.about-photo img{width:100%;height:100%;object-fit:cover}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:24px}
.chips span{border:1px solid var(--line);border-radius:999px;padding:8px 12px;color:#b7bec4;font-size:11px;background:#11161a}

.resume-strip{padding:85px var(--gutter);display:flex;align-items:center;justify-content:space-between;gap:30px;background:linear-gradient(125deg,#1c2227,#0d1013);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.resume-actions{display:flex;gap:10px;flex-wrap:wrap}
footer{min-height:130px;padding:0 var(--gutter);display:flex;align-items:center;gap:24px;color:#778088;background:#080a0c;font-size:13px;letter-spacing:.08em}
footer strong{color:var(--accent);transition:color var(--accent-ease)}
footer small{margin-left:auto}

.reveal{opacity:0;transform:translateY(24px);transition:opacity .7s ease,transform .7s cubic-bezier(.22,.61,.36,1)}
/* The hero mascot is the LCP element. Chrome will not consider an element
   with opacity:0 as an LCP candidate at all, so fading it in cancels out the
   preload and fetchpriority=high. Keep the slide, drop the fade. */
.hero-art.reveal{opacity:1}
.reveal.in{opacity:1;transform:none}

/* ==========================================================================
   CONTACT MODAL
   <dialog> carries the focus trap, inertness and Esc handling; everything here
   is presentation. Accent shows up on the kicker, the field focus state, the
   left rule and the send button.
   ========================================================================== */
.contact-modal{
  border:0;padding:0;background:transparent;color:var(--text);
  max-width:min(560px,calc(100vw - 32px));width:100%;
  margin:auto;overflow:visible;
}
.contact-modal::backdrop{
  background:rgba(9,13,24,.82);          /* dark, faintly blue */
  backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
}
.contact-modal[open]{animation:contactIn .24s cubic-bezier(.22,.61,.36,1)}
@keyframes contactIn{from{opacity:0;transform:translateY(14px) scale(.985)}to{opacity:1;transform:none}}

.contact-panel{
  position:relative;display:grid;gap:14px;
  padding:clamp(26px,3.4vw,40px);
  border-radius:18px;
  background:linear-gradient(160deg,#161c24,#0e1319);
  border:1px solid var(--line);
  border-left:3px solid var(--accent);
  box-shadow:0 30px 90px rgba(0,0,0,.6);
  transition:border-color var(--accent-ease);
}
.contact-panel h2{margin:0;font-size:clamp(26px,2.6vw,34px);line-height:1;letter-spacing:-.03em}
.contact-intro{margin:0 0 4px;color:#a4adb5;font-size:15px;line-height:1.6}

.contact-close{
  position:absolute;top:14px;right:14px;width:36px;height:36px;
  display:grid;place-items:center;padding:0;cursor:pointer;
  border:1px solid var(--line);border-radius:10px;background:rgba(255,255,255,.04);
  color:var(--icon-idle);transition:color var(--accent-ease),border-color var(--accent-ease),background .2s ease;
}
.contact-close svg{width:17px;height:17px}
.contact-close:hover{color:var(--accent);border-color:var(--accent);background:rgba(255,255,255,.07)}

.contact-field{display:grid;gap:7px}
.contact-field>span{font-size:11px;font-weight:900;letter-spacing:.16em;color:#98a1a9}
.contact-field>span b{color:var(--accent);font-weight:900;transition:color var(--accent-ease)}
.contact-field input,.contact-field textarea{
  font:inherit;font-size:15px;color:var(--text);
  padding:13px 14px;border-radius:10px;
  border:1px solid var(--line);background:rgba(255,255,255,.035);
  transition:border-color .18s ease,background .18s ease,box-shadow .18s ease;
}
.contact-field textarea{resize:vertical;min-height:120px;line-height:1.55}
.contact-field input::placeholder,.contact-field textarea::placeholder{color:#6d757c}
.contact-field input:focus,.contact-field textarea:focus{
  outline:none;border-color:var(--accent);background:rgba(255,255,255,.06);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent);
}
.contact-field.invalid input,.contact-field.invalid textarea{border-color:#e0563c}

/* Bot trap: off-screen rather than display:none so headless fillers still see it. */
.contact-trap{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}

.contact-status{margin:0;min-height:20px;font-size:14px;line-height:1.45;color:#a4adb5}
.contact-status.error{color:#f08a72}
.contact-status.ok{color:var(--accent)}

.contact-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:2px}
.contact-actions .button{flex:0 0 auto}
.contact-actions .button[disabled]{opacity:.55;pointer-events:none}
body.modal-open{overflow:hidden}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
/* ==========================================================================
   ZOOM / NARROW-VIEWPORT DROP-OFF
   Browser zoom shrinks the CSS viewport, so plain width queries cover it. On a
   1990px window: 110% zoom ~= 1809px, 120% ~= 1658px, 150% ~= 1327px,
   175% ~= 1137px. The hero cast is anchored three different ways (mascot and
   archer from the left, goblin from the right, wedge proportional), so past a
   point they can only converge on each other — cheapest fix is to retire them
   in order of how much room they need.
   ========================================================================== */
/* Zooming OUT widens the CSS viewport; the mascot group clamps at a fixed size
   while the wedge and goblin keep spreading, so the note drifts out of its gap.
   95% zoom on a ~1975px inner width lands near 2080px. */
@media(min-width:2050px){ .hero-note{display:none} }         /* ~95% zoom or less */
@media(max-width:1830px){ .hero-note{display:none} }         /* ~110% zoom or more */
@media(max-width:1330px){ .hero-goblin{display:none} }       /* ~150%, already slid off */
@media(max-width:1140px){ .hero-archer,.bg-front,.bg-wedge{display:none} }  /* ~175% */

/* 1251-1400: the mascot's clamps park the archer a few px past the right edge.
   Same size, just anchored to the viewport instead of to the mascot. */
@media(min-width:1251px) and (max-width:1400px){
  .hero-archer{left:auto;right:1.5vw}
}
@media(max-width:1250px){
  .hero-copy{left:clamp(52px,7vw,90px);width:42vw}
  .hero-art,.hero-archer,.hero-goblin,.hero-note{--mascot-x:42vw;--mascot-w:58vw}
  .hero-art{top:-5px}
  /* Below this width the mascot deliberately bleeds off the right edge, so an
     archer placed against the mascot's width would follow it off-screen. Anchor
     him to the viewport instead. */
  .hero-archer{left:auto;right:3.5vw;width:25vw;top:calc(-5px + 13.6vw)}
}
@media(max-width:1100px){
  :root{--gutter:clamp(28px,5vw,60px)}
  .hero{height:auto;min-height:820px;padding:54px 28px 0}
  .hero-copy{position:relative;left:auto;top:auto;width:min(680px,86vw);max-width:680px}
  .hero-art{left:27vw;top:315px;width:78vw;height:auto}
  .bg-front,.hero-archer,.hero-goblin,.hero-note{display:none}
  .home-featured{padding-top:28px}
  .work-grid{grid-template-columns:1fr 1fr}
  .split-section{grid-template-columns:1fr}
  .about{grid-template-columns:320px 1fr}
}
@media(max-width:760px){
  :root{--sidebar:58px;--copy-size:16px;--swatch:28px;--swatch-step:34px}
  .sidebar:hover,.sidebar:focus-within{width:188px}
  .site-shell{margin-left:var(--sidebar)}
  .brand-mark{width:34px;height:34px}
  .nav-link,.resume-mini,.contact-mini{padding:0 17px;gap:14px}
  .nav-text{font-size:13px}
  .profile-mini{padding:10px;min-height:120px}
  .profile-mini .profile-photo{width:35px;height:35px;min-width:35px}
  .social-mini .icon{width:16px;height:16px}
  .topbar{padding:0 12px}
  .accent-picker{transform:translate(-4px,12px)}
  .accent-picker .accent-label{display:none}
  .accent-picker.compact{top:0;right:2px}
  .hero{min-height:790px;padding:46px 20px 0}
  .hero-copy{width:100%}
  .dex-wordmark{width:min(72vw,379px)}
  .cimino-wordmark-shell{width:min(57vw,302px);margin-top:26px}
  .hero-art{left:7vw;top:380px;width:100vw;margin:0}
  .home-featured .work-grid{grid-template-columns:1fr}
  .home-featured .work-card{height:300px}
  :root{--gutter:20px}
  .split-section,.section,.about{padding:72px var(--gutter)}
  .ai-grid{grid-template-columns:1fr}
  .about{grid-template-columns:1fr}
  .about-photo{max-width:330px}
  .contact-panel{padding:24px 20px}
  .resume-strip{padding:60px var(--gutter);align-items:flex-start;flex-direction:column}
  .stack-row{grid-template-columns:36px 1fr 24px}
  .stack-row small{display:none}
  footer{padding:0 20px;flex-wrap:wrap}
  footer small{margin-left:0}
}
@media(prefers-reduced-motion:reduce){
  *{scroll-behavior:auto!important;animation:none!important;transition-duration:.01ms!important}
  .reveal{opacity:1;transform:none}
}
